1 : // Copyright 2011 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/pe/image_source_map.h"
16 :
17 : namespace pe {
18 :
19 : using block_graph::BlockGraph;
20 : using core::RelativeAddress;
21 :
22 : // When inverting, in order to have as much address space available for the
23 : // destination image as is available to the source image, we peg this constant
24 : // to the middle of the possible address space. Thus, we are able to build OMAPs
25 : // for images up to 2GB in size.
26 : const ULONG kInvalidOmapRvaTo = 0x80000000;
27 :
28 : void BuildImageSourceMap(const ImageLayout& image_layout,
29 E : ImageSourceMap* new_to_old) {
30 : // Walk through all blocks in the image.
31 : BlockGraph::AddressSpace::RangeMapConstIter block_it =
32 E : image_layout.blocks.begin();
33 E : for (; block_it != image_layout.blocks.end(); ++block_it) {
34 E : const BlockGraph::Block* block = block_it->second;
35 E : DCHECK(block != NULL);
36 :
37 : // Walk through all of the source ranges for this block.
38 : BlockGraph::Block::SourceRanges::RangePairs::const_iterator src_it =
39 E : block->source_ranges().range_pairs().begin();
40 E : for (; src_it != block->source_ranges().range_pairs().end(); ++src_it) {
41 : RelativeAddress new_start =
42 E : block_it->first.start() + src_it->first.start();
43 E : RelativeAddress old_start = src_it->second.start();
44 E : size_t new_size = src_it->first.size();
45 E : size_t old_size = src_it->second.size();
46 :
47 : // Add this range mapping to the image range map.
48 : bool pushed = new_to_old->Push(
49 : RelativeAddressRange(new_start, new_size),
50 E : RelativeAddressRange(old_start, old_size));
51 E : DCHECK(pushed);
52 E : }
53 E : }
54 E : }
55 :
56 : void BuildOmapVectorFromImageSourceMap(const RelativeAddressRange& range,
57 : const ImageSourceMap& source_map,
58 E : std::vector<OMAP>* omaps) {
59 : // The image size must be less than the constant we use as an indication of
60 : // invalid addresses.
61 E : DCHECK_LE(range.end().value(), kInvalidOmapRvaTo);
62 E : DCHECK(omaps != NULL);
63 :
64 : // We know that we will have roughly as many OMAP entries as there are range
65 : // pairs.
66 E : omaps->reserve(source_map.size());
67 :
68 E : RelativeAddress address = range.start();
69 : ImageSourceMap::RangePairs::const_iterator pair_it =
70 E : source_map.range_pairs().begin();
71 E : for (; pair_it != source_map.range_pairs().end(); ++pair_it) {
72 : // Skip any source ranges that come before us.
73 E : if (pair_it->first.end() < range.start())
74 E : continue;
75 :
76 : // Stop if this source range is beyond the end of the range we're concerned
77 : // with.
78 E : if (range.end() < pair_it->first.start())
79 i : break;
80 :
81 : // Have a gap to fill?
82 E : if (address < pair_it->first.start()) {
83 E : OMAP omap = { address.value(), kInvalidOmapRvaTo };
84 E : omaps->push_back(omap);
85 : }
86 :
87 : // A long mapping means that there is some range of source addresses that
88 : // mapped to a shorter range of destination addresses. This means that
89 : // source pointers pointing to the tail end of the source range will be
90 : // mapped to an address outside of the intended detination range.
91 : //
92 : // We patch these by making several OMAP entries for them, each one covering
93 : // a portion of the source range and repeatedly mapping it to the same
94 : // destination range.
95 E : if (pair_it->first.size() > pair_it->second.size()) {
96 E : address = pair_it->first.start();
97 E : while (address < pair_it->first.end()) {
98 E : OMAP omap = { address.value(), pair_it->second.start().value() };
99 E : omaps->push_back(omap);
100 E : address += pair_it->second.size();
101 E : }
102 E : } else {
103 : OMAP omap = { pair_it->first.start().value(),
104 E : pair_it->second.start().value() };
105 E : omaps->push_back(omap);
106 :
107 E : address = pair_it->first.end();
108 : }
109 E : }
110 :
111 : // Do we need an entry for the end of the range?
112 E : if (address < range.end()) {
113 E : OMAP omap = { address.value(), kInvalidOmapRvaTo };
114 E : omaps->push_back(omap);
115 : }
116 :
117 : // Cap off the OMAP vector with an entry for the first address beyond the end
118 : // of the part of the image we're concerned with.
119 E : OMAP last_omap = { range.end().value(), kInvalidOmapRvaTo };
120 E : omaps->push_back(last_omap);
121 E : }
122 :
123 : } // namespace pe
|