xref: /aosp_15_r20/external/google-breakpad/src/common/windows/omap.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2013 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle // This contains a suite of tools for transforming symbol information when
30*9712c20fSFrederick Mayle // when that information has been extracted from a PDB containing OMAP
31*9712c20fSFrederick Mayle // information.
32*9712c20fSFrederick Mayle 
33*9712c20fSFrederick Mayle // OMAP information is a lightweight description of a mapping between two
34*9712c20fSFrederick Mayle // address spaces. It consists of two streams, each of them a vector 2-tuples.
35*9712c20fSFrederick Mayle // The OMAPTO stream contains tuples of the form
36*9712c20fSFrederick Mayle //
37*9712c20fSFrederick Mayle //   (RVA in transformed image, RVA in original image)
38*9712c20fSFrederick Mayle //
39*9712c20fSFrederick Mayle // while the OMAPFROM stream contains tuples of the form
40*9712c20fSFrederick Mayle //
41*9712c20fSFrederick Mayle //   (RVA in original image, RVA in transformed image)
42*9712c20fSFrederick Mayle //
43*9712c20fSFrederick Mayle // The entries in each vector are sorted by the first value of the tuple, and
44*9712c20fSFrederick Mayle // the lengths associated with a mapping are implicit as the distance between
45*9712c20fSFrederick Mayle // two successive addresses in the vector.
46*9712c20fSFrederick Mayle 
47*9712c20fSFrederick Mayle // Consider a trivial 10-byte function described by the following symbol:
48*9712c20fSFrederick Mayle //
49*9712c20fSFrederick Mayle //   Function: RVA 0x00001000, length 10, "foo"
50*9712c20fSFrederick Mayle //
51*9712c20fSFrederick Mayle // Now consider the same function, but with 5-bytes of instrumentation injected
52*9712c20fSFrederick Mayle // at offset 5. The OMAP streams describing this would look like:
53*9712c20fSFrederick Mayle //
54*9712c20fSFrederick Mayle //   OMAPTO  :  [ [0x00001000, 0x00001000],
55*9712c20fSFrederick Mayle //                [0x00001005, 0xFFFFFFFF],
56*9712c20fSFrederick Mayle //                [0x0000100a, 0x00001005] ]
57*9712c20fSFrederick Mayle //   OMAPFROM:  [ [0x00001000, 0x00001000],
58*9712c20fSFrederick Mayle //                [0x00001005, 0x0000100a] ]
59*9712c20fSFrederick Mayle //
60*9712c20fSFrederick Mayle // In this case the injected code has been marked as not originating in the
61*9712c20fSFrederick Mayle // source image, and thus it will have no symbol information at all. However,
62*9712c20fSFrederick Mayle // the injected code may also be associated with an original address range;
63*9712c20fSFrederick Mayle // for example, when prepending instrumentation to a basic block the
64*9712c20fSFrederick Mayle // instrumentation can be labelled as originating from the same source BB such
65*9712c20fSFrederick Mayle // that symbol resolution will still find the appropriate source code line
66*9712c20fSFrederick Mayle // number. In this case the OMAP stream would look like:
67*9712c20fSFrederick Mayle //
68*9712c20fSFrederick Mayle //   OMAPTO  :  [ [0x00001000, 0x00001000],
69*9712c20fSFrederick Mayle //                [0x00001005, 0x00001005],
70*9712c20fSFrederick Mayle //                [0x0000100a, 0x00001005] ]
71*9712c20fSFrederick Mayle //   OMAPFROM:  [ [0x00001000, 0x00001000],
72*9712c20fSFrederick Mayle //                [0x00001005, 0x0000100a] ]
73*9712c20fSFrederick Mayle //
74*9712c20fSFrederick Mayle // Suppose we asked DIA to lookup the symbol at location 0x0000100a of the
75*9712c20fSFrederick Mayle // instrumented image. It would first run this through the OMAPTO table and
76*9712c20fSFrederick Mayle // translate that address to 0x00001005. It would then lookup the symbol
77*9712c20fSFrederick Mayle // at that address and return the symbol for the function "foo". This is the
78*9712c20fSFrederick Mayle // correct result.
79*9712c20fSFrederick Mayle //
80*9712c20fSFrederick Mayle // However, if we query DIA for the length and address of the symbol it will
81*9712c20fSFrederick Mayle // tell us that it has length 10 and is at RVA 0x00001000. The location is
82*9712c20fSFrederick Mayle // correct, but the length doesn't take into account the 5-bytes of injected
83*9712c20fSFrederick Mayle // code. Symbol resolution works (starting from an instrumented address,
84*9712c20fSFrederick Mayle // mapping to an original address, and looking up a symbol), but the symbol
85*9712c20fSFrederick Mayle // metadata is incorrect.
86*9712c20fSFrederick Mayle //
87*9712c20fSFrederick Mayle // If we dump the symbols using DIA they will have their addresses
88*9712c20fSFrederick Mayle // appropriately transformed and reflect positions in the instrumented image.
89*9712c20fSFrederick Mayle // However, if we try to do a lookup using those symbols resolution can fail.
90*9712c20fSFrederick Mayle // For example, the address 0x0000100a will not map to the symbol for "foo",
91*9712c20fSFrederick Mayle // because DIA tells us it is at location 0x00001000 (correct) with length
92*9712c20fSFrederick Mayle // 10 (incorrect). The problem is one of order of operations: in this case
93*9712c20fSFrederick Mayle // we're attempting symbol resolution by looking up an instrumented address
94*9712c20fSFrederick Mayle // in the table of translated symbols.
95*9712c20fSFrederick Mayle //
96*9712c20fSFrederick Mayle // One way to handle this is to dump the OMAP information as part of the
97*9712c20fSFrederick Mayle // breakpad symbols. This requires the rest of the toolchain to be aware of
98*9712c20fSFrederick Mayle // OMAP information and to use it when present prior to performing lookup. The
99*9712c20fSFrederick Mayle // other option is to properly transform the symbols (updating length as well as
100*9712c20fSFrederick Mayle // position) so that resolution will work as expected for translated addresses.
101*9712c20fSFrederick Mayle // This is transparent to the rest of the toolchain.
102*9712c20fSFrederick Mayle 
103*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
104*9712c20fSFrederick Mayle #include <config.h>  // Must come first
105*9712c20fSFrederick Mayle #endif
106*9712c20fSFrederick Mayle 
107*9712c20fSFrederick Mayle #include "common/windows/omap.h"
108*9712c20fSFrederick Mayle 
109*9712c20fSFrederick Mayle #include <atlbase.h>
110*9712c20fSFrederick Mayle 
111*9712c20fSFrederick Mayle #include <algorithm>
112*9712c20fSFrederick Mayle #include <cassert>
113*9712c20fSFrederick Mayle #include <set>
114*9712c20fSFrederick Mayle 
115*9712c20fSFrederick Mayle #include "common/windows/dia_util.h"
116*9712c20fSFrederick Mayle 
117*9712c20fSFrederick Mayle namespace google_breakpad {
118*9712c20fSFrederick Mayle 
119*9712c20fSFrederick Mayle namespace {
120*9712c20fSFrederick Mayle 
121*9712c20fSFrederick Mayle static const wchar_t kOmapToDebugStreamName[] = L"OMAPTO";
122*9712c20fSFrederick Mayle static const wchar_t kOmapFromDebugStreamName[] = L"OMAPFROM";
123*9712c20fSFrederick Mayle 
124*9712c20fSFrederick Mayle // Dependending on where this is used in breakpad we sometimes get min/max from
125*9712c20fSFrederick Mayle // windef, and other times from algorithm. To get around this we simply
126*9712c20fSFrederick Mayle // define our own min/max functions.
127*9712c20fSFrederick Mayle template<typename T>
Min(const T & t1,const T & t2)128*9712c20fSFrederick Mayle const T& Min(const T& t1, const T& t2) { return t1 < t2 ? t1 : t2; }
129*9712c20fSFrederick Mayle template<typename T>
Max(const T & t1,const T & t2)130*9712c20fSFrederick Mayle const T& Max(const T& t1, const T& t2) { return t1 > t2 ? t1 : t2; }
131*9712c20fSFrederick Mayle 
132*9712c20fSFrederick Mayle // It makes things more readable to have two different OMAP types. We cast
133*9712c20fSFrederick Mayle // normal OMAPs into these. They must be the same size as the OMAP structure
134*9712c20fSFrederick Mayle // for this to work, hence the static asserts.
135*9712c20fSFrederick Mayle struct OmapOrigToTran {
136*9712c20fSFrederick Mayle   DWORD rva_original;
137*9712c20fSFrederick Mayle   DWORD rva_transformed;
138*9712c20fSFrederick Mayle };
139*9712c20fSFrederick Mayle struct OmapTranToOrig {
140*9712c20fSFrederick Mayle   DWORD rva_transformed;
141*9712c20fSFrederick Mayle   DWORD rva_original;
142*9712c20fSFrederick Mayle };
143*9712c20fSFrederick Mayle static_assert(sizeof(OmapOrigToTran) == sizeof(OMAP),
144*9712c20fSFrederick Mayle               "OmapOrigToTran must have same size as OMAP.");
145*9712c20fSFrederick Mayle static_assert(sizeof(OmapTranToOrig) == sizeof(OMAP),
146*9712c20fSFrederick Mayle               "OmapTranToOrig must have same size as OMAP.");
147*9712c20fSFrederick Mayle typedef std::vector<OmapOrigToTran> OmapFromTable;
148*9712c20fSFrederick Mayle typedef std::vector<OmapTranToOrig> OmapToTable;
149*9712c20fSFrederick Mayle 
150*9712c20fSFrederick Mayle // Used for sorting and searching through a Mapping.
MappedRangeOriginalLess(const MappedRange & lhs,const MappedRange & rhs)151*9712c20fSFrederick Mayle bool MappedRangeOriginalLess(const MappedRange& lhs, const MappedRange& rhs) {
152*9712c20fSFrederick Mayle   if (lhs.rva_original < rhs.rva_original)
153*9712c20fSFrederick Mayle     return true;
154*9712c20fSFrederick Mayle   if (lhs.rva_original > rhs.rva_original)
155*9712c20fSFrederick Mayle     return false;
156*9712c20fSFrederick Mayle   return lhs.length < rhs.length;
157*9712c20fSFrederick Mayle }
MappedRangeMappedLess(const MappedRange & lhs,const MappedRange & rhs)158*9712c20fSFrederick Mayle bool MappedRangeMappedLess(const MappedRange& lhs, const MappedRange& rhs) {
159*9712c20fSFrederick Mayle   if (lhs.rva_transformed < rhs.rva_transformed)
160*9712c20fSFrederick Mayle     return true;
161*9712c20fSFrederick Mayle   if (lhs.rva_transformed > rhs.rva_transformed)
162*9712c20fSFrederick Mayle     return false;
163*9712c20fSFrederick Mayle   return lhs.length < rhs.length;
164*9712c20fSFrederick Mayle }
165*9712c20fSFrederick Mayle 
166*9712c20fSFrederick Mayle // Used for searching through the EndpointIndexMap.
EndpointIndexLess(const EndpointIndex & ei1,const EndpointIndex & ei2)167*9712c20fSFrederick Mayle bool EndpointIndexLess(const EndpointIndex& ei1, const EndpointIndex& ei2) {
168*9712c20fSFrederick Mayle   return ei1.endpoint < ei2.endpoint;
169*9712c20fSFrederick Mayle }
170*9712c20fSFrederick Mayle 
171*9712c20fSFrederick Mayle // Finds the debug stream with the given |name| in the given |session|, and
172*9712c20fSFrederick Mayle // populates |table| with its contents. Casts the data directly into OMAP
173*9712c20fSFrederick Mayle // structs.
FindAndLoadOmapTable(const wchar_t * name,IDiaSession * session,OmapTable * table)174*9712c20fSFrederick Mayle bool FindAndLoadOmapTable(const wchar_t* name,
175*9712c20fSFrederick Mayle                           IDiaSession* session,
176*9712c20fSFrederick Mayle                           OmapTable* table) {
177*9712c20fSFrederick Mayle   assert(name != NULL);
178*9712c20fSFrederick Mayle   assert(session != NULL);
179*9712c20fSFrederick Mayle   assert(table != NULL);
180*9712c20fSFrederick Mayle 
181*9712c20fSFrederick Mayle   CComPtr<IDiaEnumDebugStreamData> stream;
182*9712c20fSFrederick Mayle   if (!FindDebugStream(name, session, &stream))
183*9712c20fSFrederick Mayle     return false;
184*9712c20fSFrederick Mayle   assert(stream.p != NULL);
185*9712c20fSFrederick Mayle 
186*9712c20fSFrederick Mayle   LONG count = 0;
187*9712c20fSFrederick Mayle   if (FAILED(stream->get_Count(&count))) {
188*9712c20fSFrederick Mayle     fprintf(stderr, "IDiaEnumDebugStreamData::get_Count failed for stream "
189*9712c20fSFrederick Mayle                     "\"%ws\"\n", name);
190*9712c20fSFrederick Mayle     return false;
191*9712c20fSFrederick Mayle   }
192*9712c20fSFrederick Mayle 
193*9712c20fSFrederick Mayle   // Get the length of the stream in bytes.
194*9712c20fSFrederick Mayle   DWORD bytes_read = 0;
195*9712c20fSFrederick Mayle   ULONG count_read = 0;
196*9712c20fSFrederick Mayle   if (FAILED(stream->Next(count, 0, &bytes_read, NULL, &count_read))) {
197*9712c20fSFrederick Mayle     fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
198*9712c20fSFrederick Mayle                     "length of stream \"%ws\"\n", name);
199*9712c20fSFrederick Mayle     return false;
200*9712c20fSFrederick Mayle   }
201*9712c20fSFrederick Mayle 
202*9712c20fSFrederick Mayle   // Ensure it's consistent with the OMAP data type.
203*9712c20fSFrederick Mayle   DWORD bytes_expected = count * sizeof(OmapTable::value_type);
204*9712c20fSFrederick Mayle   if (count * sizeof(OmapTable::value_type) != bytes_read) {
205*9712c20fSFrederick Mayle     fprintf(stderr, "DIA debug stream \"%ws\" has an unexpected length", name);
206*9712c20fSFrederick Mayle     return false;
207*9712c20fSFrederick Mayle   }
208*9712c20fSFrederick Mayle 
209*9712c20fSFrederick Mayle   // Read the table.
210*9712c20fSFrederick Mayle   table->resize(count);
211*9712c20fSFrederick Mayle   bytes_read = 0;
212*9712c20fSFrederick Mayle   count_read = 0;
213*9712c20fSFrederick Mayle   if (FAILED(stream->Next(count, bytes_expected, &bytes_read,
214*9712c20fSFrederick Mayle                           reinterpret_cast<BYTE*>(&table->at(0)),
215*9712c20fSFrederick Mayle                           &count_read))) {
216*9712c20fSFrederick Mayle     fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
217*9712c20fSFrederick Mayle                     "data from stream \"%ws\"\n", name);
218*9712c20fSFrederick Mayle     return false;
219*9712c20fSFrederick Mayle   }
220*9712c20fSFrederick Mayle 
221*9712c20fSFrederick Mayle   return true;
222*9712c20fSFrederick Mayle }
223*9712c20fSFrederick Mayle 
224*9712c20fSFrederick Mayle // This determines the original image length by looking through the segment
225*9712c20fSFrederick Mayle // table.
GetOriginalImageLength(IDiaSession * session,DWORD * image_length)226*9712c20fSFrederick Mayle bool GetOriginalImageLength(IDiaSession* session, DWORD* image_length) {
227*9712c20fSFrederick Mayle   assert(session != NULL);
228*9712c20fSFrederick Mayle   assert(image_length != NULL);
229*9712c20fSFrederick Mayle 
230*9712c20fSFrederick Mayle   CComPtr<IDiaEnumSegments> enum_segments;
231*9712c20fSFrederick Mayle   if (!FindTable(session, &enum_segments))
232*9712c20fSFrederick Mayle     return false;
233*9712c20fSFrederick Mayle   assert(enum_segments.p != NULL);
234*9712c20fSFrederick Mayle 
235*9712c20fSFrederick Mayle   DWORD temp_image_length = 0;
236*9712c20fSFrederick Mayle   CComPtr<IDiaSegment> segment;
237*9712c20fSFrederick Mayle   ULONG fetched = 0;
238*9712c20fSFrederick Mayle   while (SUCCEEDED(enum_segments->Next(1, &segment, &fetched)) &&
239*9712c20fSFrederick Mayle          fetched == 1) {
240*9712c20fSFrederick Mayle     assert(segment.p != NULL);
241*9712c20fSFrederick Mayle 
242*9712c20fSFrederick Mayle     DWORD rva = 0;
243*9712c20fSFrederick Mayle     DWORD length = 0;
244*9712c20fSFrederick Mayle     DWORD frame = 0;
245*9712c20fSFrederick Mayle     if (FAILED(segment->get_relativeVirtualAddress(&rva)) ||
246*9712c20fSFrederick Mayle         FAILED(segment->get_length(&length)) ||
247*9712c20fSFrederick Mayle         FAILED(segment->get_frame(&frame))) {
248*9712c20fSFrederick Mayle       fprintf(stderr, "Failed to get basic properties for IDiaSegment\n");
249*9712c20fSFrederick Mayle       return false;
250*9712c20fSFrederick Mayle     }
251*9712c20fSFrederick Mayle 
252*9712c20fSFrederick Mayle     if (frame > 0) {
253*9712c20fSFrederick Mayle       DWORD segment_end = rva + length;
254*9712c20fSFrederick Mayle       if (segment_end > temp_image_length)
255*9712c20fSFrederick Mayle         temp_image_length = segment_end;
256*9712c20fSFrederick Mayle     }
257*9712c20fSFrederick Mayle     segment.Release();
258*9712c20fSFrederick Mayle   }
259*9712c20fSFrederick Mayle 
260*9712c20fSFrederick Mayle   *image_length = temp_image_length;
261*9712c20fSFrederick Mayle   return true;
262*9712c20fSFrederick Mayle }
263*9712c20fSFrederick Mayle 
264*9712c20fSFrederick Mayle // Detects regions of the original image that have been removed in the
265*9712c20fSFrederick Mayle // transformed image, and sets the 'removed' property on all mapped ranges
266*9712c20fSFrederick Mayle // immediately preceding a gap. The mapped ranges must be sorted by
267*9712c20fSFrederick Mayle // 'rva_original'.
FillInRemovedLengths(Mapping * mapping)268*9712c20fSFrederick Mayle void FillInRemovedLengths(Mapping* mapping) {
269*9712c20fSFrederick Mayle   assert(mapping != NULL);
270*9712c20fSFrederick Mayle 
271*9712c20fSFrederick Mayle   // Find and fill gaps. We do this with two sweeps. We first sweep forward
272*9712c20fSFrederick Mayle   // looking for gaps. When we identify a gap we then sweep forward with a
273*9712c20fSFrederick Mayle   // second scan and set the 'removed' property for any intervals that
274*9712c20fSFrederick Mayle   // immediately precede the gap.
275*9712c20fSFrederick Mayle   //
276*9712c20fSFrederick Mayle   // Gaps are typically between two successive intervals, but not always:
277*9712c20fSFrederick Mayle   //
278*9712c20fSFrederick Mayle   //   Range 1: ---------------
279*9712c20fSFrederick Mayle   //   Range 2:     -------
280*9712c20fSFrederick Mayle   //   Range 3:                      -------------
281*9712c20fSFrederick Mayle   //   Gap    :                ******
282*9712c20fSFrederick Mayle   //
283*9712c20fSFrederick Mayle   // In the above example the gap is between range 1 and range 3. A forward
284*9712c20fSFrederick Mayle   // sweep finds the gap, and a second forward sweep identifies that range 1
285*9712c20fSFrederick Mayle   // immediately precedes the gap and sets its 'removed' property.
286*9712c20fSFrederick Mayle 
287*9712c20fSFrederick Mayle   size_t fill = 0;
288*9712c20fSFrederick Mayle   DWORD rva_front = 0;
289*9712c20fSFrederick Mayle   for (size_t find = 0; find < mapping->size(); ++find) {
290*9712c20fSFrederick Mayle #ifndef NDEBUG
291*9712c20fSFrederick Mayle     // We expect the mapped ranges to be sorted by 'rva_original'.
292*9712c20fSFrederick Mayle     if (find > 0) {
293*9712c20fSFrederick Mayle       assert(mapping->at(find - 1).rva_original <=
294*9712c20fSFrederick Mayle                  mapping->at(find).rva_original);
295*9712c20fSFrederick Mayle     }
296*9712c20fSFrederick Mayle #endif
297*9712c20fSFrederick Mayle 
298*9712c20fSFrederick Mayle     if (rva_front < mapping->at(find).rva_original) {
299*9712c20fSFrederick Mayle       // We've found a gap. Fill it in by setting the 'removed' property for
300*9712c20fSFrederick Mayle       // any affected intervals.
301*9712c20fSFrederick Mayle       DWORD removed = mapping->at(find).rva_original - rva_front;
302*9712c20fSFrederick Mayle       for (; fill < find; ++fill) {
303*9712c20fSFrederick Mayle         if (mapping->at(fill).rva_original + mapping->at(fill).length !=
304*9712c20fSFrederick Mayle                 rva_front) {
305*9712c20fSFrederick Mayle           continue;
306*9712c20fSFrederick Mayle         }
307*9712c20fSFrederick Mayle 
308*9712c20fSFrederick Mayle         // This interval ends right where the gap starts. It needs to have its
309*9712c20fSFrederick Mayle         // 'removed' information filled in.
310*9712c20fSFrederick Mayle         mapping->at(fill).removed = removed;
311*9712c20fSFrederick Mayle       }
312*9712c20fSFrederick Mayle     }
313*9712c20fSFrederick Mayle 
314*9712c20fSFrederick Mayle     // Advance the front that indicates the covered portion of the image.
315*9712c20fSFrederick Mayle     rva_front = mapping->at(find).rva_original + mapping->at(find).length;
316*9712c20fSFrederick Mayle   }
317*9712c20fSFrederick Mayle }
318*9712c20fSFrederick Mayle 
319*9712c20fSFrederick Mayle // Builds a unified view of the mapping between the original and transformed
320*9712c20fSFrederick Mayle // image space by merging OMAPTO and OMAPFROM data.
BuildMapping(const OmapData & omap_data,Mapping * mapping)321*9712c20fSFrederick Mayle void BuildMapping(const OmapData& omap_data, Mapping* mapping) {
322*9712c20fSFrederick Mayle   assert(mapping != NULL);
323*9712c20fSFrederick Mayle 
324*9712c20fSFrederick Mayle   mapping->clear();
325*9712c20fSFrederick Mayle 
326*9712c20fSFrederick Mayle   if (omap_data.omap_from.empty() || omap_data.omap_to.empty())
327*9712c20fSFrederick Mayle     return;
328*9712c20fSFrederick Mayle 
329*9712c20fSFrederick Mayle   // The names 'omap_to' and 'omap_from' are awfully confusing, so we make
330*9712c20fSFrederick Mayle   // ourselves more explicit here. This cast is only safe because the underlying
331*9712c20fSFrederick Mayle   // types have the exact same size.
332*9712c20fSFrederick Mayle   const OmapToTable& tran2orig =
333*9712c20fSFrederick Mayle       reinterpret_cast<const OmapToTable&>(omap_data.omap_to);
334*9712c20fSFrederick Mayle   const OmapFromTable& orig2tran = reinterpret_cast<const OmapFromTable&>(
335*9712c20fSFrederick Mayle       omap_data.omap_from);
336*9712c20fSFrederick Mayle 
337*9712c20fSFrederick Mayle   // Handle the range of data at the beginning of the image. This is not usually
338*9712c20fSFrederick Mayle   // specified by the OMAP data.
339*9712c20fSFrederick Mayle   if (tran2orig[0].rva_transformed > 0 && orig2tran[0].rva_original > 0) {
340*9712c20fSFrederick Mayle     DWORD header_transformed = tran2orig[0].rva_transformed;
341*9712c20fSFrederick Mayle     DWORD header_original = orig2tran[0].rva_original;
342*9712c20fSFrederick Mayle     DWORD header = Min(header_transformed, header_original);
343*9712c20fSFrederick Mayle 
344*9712c20fSFrederick Mayle     MappedRange mr = {};
345*9712c20fSFrederick Mayle     mr.length = header;
346*9712c20fSFrederick Mayle     mr.injected = header_transformed - header;
347*9712c20fSFrederick Mayle     mr.removed = header_original - header;
348*9712c20fSFrederick Mayle     mapping->push_back(mr);
349*9712c20fSFrederick Mayle   }
350*9712c20fSFrederick Mayle 
351*9712c20fSFrederick Mayle   // Convert the implied lengths to explicit lengths, and infer which content
352*9712c20fSFrederick Mayle   // has been injected into the transformed image. Injected content is inferred
353*9712c20fSFrederick Mayle   // as regions of the transformed address space that does not map back to
354*9712c20fSFrederick Mayle   // known valid content in the original image.
355*9712c20fSFrederick Mayle   for (size_t i = 0; i < tran2orig.size(); ++i) {
356*9712c20fSFrederick Mayle     const OmapTranToOrig& o1 = tran2orig[i];
357*9712c20fSFrederick Mayle 
358*9712c20fSFrederick Mayle     // This maps to content that is outside the original image, thus it
359*9712c20fSFrederick Mayle     // describes injected content. We can skip this entry.
360*9712c20fSFrederick Mayle     if (o1.rva_original >= omap_data.length_original)
361*9712c20fSFrederick Mayle       continue;
362*9712c20fSFrederick Mayle 
363*9712c20fSFrederick Mayle     // Calculate the length of the current OMAP entry. This is implicit as the
364*9712c20fSFrederick Mayle     // distance between successive |rva| values, capped at the end of the
365*9712c20fSFrederick Mayle     // original image.
366*9712c20fSFrederick Mayle     DWORD length = 0;
367*9712c20fSFrederick Mayle     if (i + 1 < tran2orig.size()) {
368*9712c20fSFrederick Mayle       const OmapTranToOrig& o2 = tran2orig[i + 1];
369*9712c20fSFrederick Mayle 
370*9712c20fSFrederick Mayle       // We expect the table to be sorted by rva_transformed.
371*9712c20fSFrederick Mayle       assert(o1.rva_transformed <= o2.rva_transformed);
372*9712c20fSFrederick Mayle 
373*9712c20fSFrederick Mayle       length = o2.rva_transformed - o1.rva_transformed;
374*9712c20fSFrederick Mayle       if (o1.rva_original + length > omap_data.length_original) {
375*9712c20fSFrederick Mayle         length = omap_data.length_original - o1.rva_original;
376*9712c20fSFrederick Mayle       }
377*9712c20fSFrederick Mayle     } else {
378*9712c20fSFrederick Mayle       length = omap_data.length_original - o1.rva_original;
379*9712c20fSFrederick Mayle     }
380*9712c20fSFrederick Mayle 
381*9712c20fSFrederick Mayle     // Zero-length entries don't describe anything and can be ignored.
382*9712c20fSFrederick Mayle     if (length == 0)
383*9712c20fSFrederick Mayle       continue;
384*9712c20fSFrederick Mayle 
385*9712c20fSFrederick Mayle     // Any gaps in the transformed address-space are due to injected content.
386*9712c20fSFrederick Mayle     if (!mapping->empty()) {
387*9712c20fSFrederick Mayle       MappedRange& prev_mr = mapping->back();
388*9712c20fSFrederick Mayle       prev_mr.injected += o1.rva_transformed -
389*9712c20fSFrederick Mayle           (prev_mr.rva_transformed + prev_mr.length);
390*9712c20fSFrederick Mayle     }
391*9712c20fSFrederick Mayle 
392*9712c20fSFrederick Mayle     MappedRange mr = {};
393*9712c20fSFrederick Mayle     mr.rva_original = o1.rva_original;
394*9712c20fSFrederick Mayle     mr.rva_transformed = o1.rva_transformed;
395*9712c20fSFrederick Mayle     mr.length = length;
396*9712c20fSFrederick Mayle     mapping->push_back(mr);
397*9712c20fSFrederick Mayle   }
398*9712c20fSFrederick Mayle 
399*9712c20fSFrederick Mayle   // Sort based on the original image addresses.
400*9712c20fSFrederick Mayle   std::sort(mapping->begin(), mapping->end(), MappedRangeOriginalLess);
401*9712c20fSFrederick Mayle 
402*9712c20fSFrederick Mayle   // Fill in the 'removed' lengths by looking for gaps in the coverage of the
403*9712c20fSFrederick Mayle   // original address space.
404*9712c20fSFrederick Mayle   FillInRemovedLengths(mapping);
405*9712c20fSFrederick Mayle 
406*9712c20fSFrederick Mayle   return;
407*9712c20fSFrederick Mayle }
408*9712c20fSFrederick Mayle 
BuildEndpointIndexMap(ImageMap * image_map)409*9712c20fSFrederick Mayle void BuildEndpointIndexMap(ImageMap* image_map) {
410*9712c20fSFrederick Mayle   assert(image_map != NULL);
411*9712c20fSFrederick Mayle 
412*9712c20fSFrederick Mayle   if (image_map->mapping.size() == 0)
413*9712c20fSFrederick Mayle     return;
414*9712c20fSFrederick Mayle 
415*9712c20fSFrederick Mayle   const Mapping& mapping = image_map->mapping;
416*9712c20fSFrederick Mayle   EndpointIndexMap& eim = image_map->endpoint_index_map;
417*9712c20fSFrederick Mayle 
418*9712c20fSFrederick Mayle   // Get the unique set of interval endpoints.
419*9712c20fSFrederick Mayle   std::set<DWORD> endpoints;
420*9712c20fSFrederick Mayle   for (size_t i = 0; i < mapping.size(); ++i) {
421*9712c20fSFrederick Mayle     endpoints.insert(mapping[i].rva_original);
422*9712c20fSFrederick Mayle     endpoints.insert(mapping[i].rva_original +
423*9712c20fSFrederick Mayle                          mapping[i].length +
424*9712c20fSFrederick Mayle                          mapping[i].removed);
425*9712c20fSFrederick Mayle   }
426*9712c20fSFrederick Mayle 
427*9712c20fSFrederick Mayle   // Use the endpoints to initialize the secondary search structure for the
428*9712c20fSFrederick Mayle   // mapping.
429*9712c20fSFrederick Mayle   eim.resize(endpoints.size());
430*9712c20fSFrederick Mayle   std::set<DWORD>::const_iterator it = endpoints.begin();
431*9712c20fSFrederick Mayle   for (size_t i = 0; it != endpoints.end(); ++it, ++i) {
432*9712c20fSFrederick Mayle     eim[i].endpoint = *it;
433*9712c20fSFrederick Mayle     eim[i].index = mapping.size();
434*9712c20fSFrederick Mayle   }
435*9712c20fSFrederick Mayle 
436*9712c20fSFrederick Mayle   // For each endpoint we want the smallest index of any interval containing
437*9712c20fSFrederick Mayle   // it. We iterate over the intervals and update the indices associated with
438*9712c20fSFrederick Mayle   // each interval endpoint contained in the current interval. In the general
439*9712c20fSFrederick Mayle   // case of an arbitrary set of intervals this is O(n^2), but the structure of
440*9712c20fSFrederick Mayle   // OMAP data makes this O(n).
441*9712c20fSFrederick Mayle   for (size_t i = 0; i < mapping.size(); ++i) {
442*9712c20fSFrederick Mayle     EndpointIndex ei1 = { mapping[i].rva_original, 0 };
443*9712c20fSFrederick Mayle     EndpointIndexMap::iterator it1 = std::lower_bound(
444*9712c20fSFrederick Mayle         eim.begin(), eim.end(), ei1, EndpointIndexLess);
445*9712c20fSFrederick Mayle 
446*9712c20fSFrederick Mayle     EndpointIndex ei2 = { mapping[i].rva_original + mapping[i].length +
447*9712c20fSFrederick Mayle                               mapping[i].removed, 0 };
448*9712c20fSFrederick Mayle     EndpointIndexMap::iterator it2 = std::lower_bound(
449*9712c20fSFrederick Mayle         eim.begin(), eim.end(), ei2, EndpointIndexLess);
450*9712c20fSFrederick Mayle 
451*9712c20fSFrederick Mayle     for (; it1 != it2; ++it1)
452*9712c20fSFrederick Mayle       it1->index = Min(i, it1->index);
453*9712c20fSFrederick Mayle   }
454*9712c20fSFrederick Mayle }
455*9712c20fSFrederick Mayle 
BuildSubsequentRVAMap(const OmapData & omap_data,std::map<DWORD,DWORD> * subsequent)456*9712c20fSFrederick Mayle void BuildSubsequentRVAMap(const OmapData& omap_data,
457*9712c20fSFrederick Mayle                            std::map<DWORD, DWORD>* subsequent) {
458*9712c20fSFrederick Mayle   assert(subsequent->empty());
459*9712c20fSFrederick Mayle   const OmapFromTable& orig2tran =
460*9712c20fSFrederick Mayle       reinterpret_cast<const OmapFromTable&>(omap_data.omap_from);
461*9712c20fSFrederick Mayle 
462*9712c20fSFrederick Mayle   if (orig2tran.empty())
463*9712c20fSFrederick Mayle     return;
464*9712c20fSFrederick Mayle 
465*9712c20fSFrederick Mayle   for (size_t i = 0; i < orig2tran.size() - 1; ++i) {
466*9712c20fSFrederick Mayle     // Expect that orig2tran is sorted.
467*9712c20fSFrederick Mayle     if (orig2tran[i].rva_original >= orig2tran[i + 1].rva_original) {
468*9712c20fSFrederick Mayle       fprintf(stderr, "OMAP 'from' table unexpectedly unsorted\n");
469*9712c20fSFrederick Mayle       subsequent->clear();
470*9712c20fSFrederick Mayle       return;
471*9712c20fSFrederick Mayle     }
472*9712c20fSFrederick Mayle     subsequent->insert(std::make_pair(orig2tran[i].rva_original,
473*9712c20fSFrederick Mayle                                       orig2tran[i + 1].rva_original));
474*9712c20fSFrederick Mayle   }
475*9712c20fSFrederick Mayle }
476*9712c20fSFrederick Mayle 
477*9712c20fSFrederick Mayle // Clips the given mapped range.
ClipMappedRangeOriginal(const AddressRange & clip_range,MappedRange * mapped_range)478*9712c20fSFrederick Mayle void ClipMappedRangeOriginal(const AddressRange& clip_range,
479*9712c20fSFrederick Mayle                              MappedRange* mapped_range) {
480*9712c20fSFrederick Mayle   assert(mapped_range != NULL);
481*9712c20fSFrederick Mayle 
482*9712c20fSFrederick Mayle   // The clipping range is entirely outside of the mapped range.
483*9712c20fSFrederick Mayle   if (clip_range.end() <= mapped_range->rva_original ||
484*9712c20fSFrederick Mayle       mapped_range->rva_original + mapped_range->length +
485*9712c20fSFrederick Mayle           mapped_range->removed <= clip_range.rva) {
486*9712c20fSFrederick Mayle     mapped_range->length = 0;
487*9712c20fSFrederick Mayle     mapped_range->injected = 0;
488*9712c20fSFrederick Mayle     mapped_range->removed = 0;
489*9712c20fSFrederick Mayle     return;
490*9712c20fSFrederick Mayle   }
491*9712c20fSFrederick Mayle 
492*9712c20fSFrederick Mayle   // Clip the left side.
493*9712c20fSFrederick Mayle   if (mapped_range->rva_original < clip_range.rva) {
494*9712c20fSFrederick Mayle     DWORD clip_left = clip_range.rva - mapped_range->rva_original;
495*9712c20fSFrederick Mayle     mapped_range->rva_original += clip_left;
496*9712c20fSFrederick Mayle     mapped_range->rva_transformed += clip_left;
497*9712c20fSFrederick Mayle 
498*9712c20fSFrederick Mayle     if (clip_left > mapped_range->length) {
499*9712c20fSFrederick Mayle       // The left clipping boundary entirely erases the content section of the
500*9712c20fSFrederick Mayle       // range.
501*9712c20fSFrederick Mayle       DWORD trim = clip_left - mapped_range->length;
502*9712c20fSFrederick Mayle       mapped_range->length = 0;
503*9712c20fSFrederick Mayle       mapped_range->injected -= Min(trim, mapped_range->injected);
504*9712c20fSFrederick Mayle       // We know that trim <= mapped_range->remove.
505*9712c20fSFrederick Mayle       mapped_range->removed -= trim;
506*9712c20fSFrederick Mayle     } else {
507*9712c20fSFrederick Mayle       // The left clipping boundary removes some, but not all, of the content.
508*9712c20fSFrederick Mayle       // As such it leaves the removed/injected component intact.
509*9712c20fSFrederick Mayle       mapped_range->length -= clip_left;
510*9712c20fSFrederick Mayle     }
511*9712c20fSFrederick Mayle   }
512*9712c20fSFrederick Mayle 
513*9712c20fSFrederick Mayle   // Clip the right side.
514*9712c20fSFrederick Mayle   DWORD end_original = mapped_range->rva_original + mapped_range->length;
515*9712c20fSFrederick Mayle   if (clip_range.end() < end_original) {
516*9712c20fSFrederick Mayle     // The right clipping boundary lands in the 'content' section of the range,
517*9712c20fSFrederick Mayle     // entirely clearing the injected/removed portion.
518*9712c20fSFrederick Mayle     DWORD clip_right = end_original - clip_range.end();
519*9712c20fSFrederick Mayle     mapped_range->length -= clip_right;
520*9712c20fSFrederick Mayle     mapped_range->injected = 0;
521*9712c20fSFrederick Mayle     mapped_range->removed = 0;
522*9712c20fSFrederick Mayle     return;
523*9712c20fSFrederick Mayle   } else {
524*9712c20fSFrederick Mayle     // The right clipping boundary is outside of the content, but may affect
525*9712c20fSFrederick Mayle     // the removed/injected portion of the range.
526*9712c20fSFrederick Mayle     DWORD end_removed = end_original + mapped_range->removed;
527*9712c20fSFrederick Mayle     if (clip_range.end() < end_removed)
528*9712c20fSFrederick Mayle       mapped_range->removed = clip_range.end() - end_original;
529*9712c20fSFrederick Mayle 
530*9712c20fSFrederick Mayle     DWORD end_injected = end_original + mapped_range->injected;
531*9712c20fSFrederick Mayle     if (clip_range.end() < end_injected)
532*9712c20fSFrederick Mayle       mapped_range->injected = clip_range.end() - end_original;
533*9712c20fSFrederick Mayle   }
534*9712c20fSFrederick Mayle 
535*9712c20fSFrederick Mayle   return;
536*9712c20fSFrederick Mayle }
537*9712c20fSFrederick Mayle 
538*9712c20fSFrederick Mayle }  // namespace
539*9712c20fSFrederick Mayle 
Compare(const AddressRange & rhs) const540*9712c20fSFrederick Mayle int AddressRange::Compare(const AddressRange& rhs) const {
541*9712c20fSFrederick Mayle   if (end() <= rhs.rva)
542*9712c20fSFrederick Mayle     return -1;
543*9712c20fSFrederick Mayle   if (rhs.end() <= rva)
544*9712c20fSFrederick Mayle     return 1;
545*9712c20fSFrederick Mayle   return 0;
546*9712c20fSFrederick Mayle }
547*9712c20fSFrederick Mayle 
GetOmapDataAndDisableTranslation(IDiaSession * session,OmapData * omap_data)548*9712c20fSFrederick Mayle bool GetOmapDataAndDisableTranslation(IDiaSession* session,
549*9712c20fSFrederick Mayle                                       OmapData* omap_data) {
550*9712c20fSFrederick Mayle   assert(session != NULL);
551*9712c20fSFrederick Mayle   assert(omap_data != NULL);
552*9712c20fSFrederick Mayle 
553*9712c20fSFrederick Mayle   CComPtr<IDiaAddressMap> address_map;
554*9712c20fSFrederick Mayle   if (FAILED(session->QueryInterface(&address_map))) {
555*9712c20fSFrederick Mayle     fprintf(stderr, "IDiaSession::QueryInterface(IDiaAddressMap) failed\n");
556*9712c20fSFrederick Mayle     return false;
557*9712c20fSFrederick Mayle   }
558*9712c20fSFrederick Mayle   assert(address_map.p != NULL);
559*9712c20fSFrederick Mayle 
560*9712c20fSFrederick Mayle   BOOL omap_enabled = FALSE;
561*9712c20fSFrederick Mayle   if (FAILED(address_map->get_addressMapEnabled(&omap_enabled))) {
562*9712c20fSFrederick Mayle     fprintf(stderr, "IDiaAddressMap::get_addressMapEnabled failed\n");
563*9712c20fSFrederick Mayle     return false;
564*9712c20fSFrederick Mayle   }
565*9712c20fSFrederick Mayle 
566*9712c20fSFrederick Mayle   if (!omap_enabled) {
567*9712c20fSFrederick Mayle     // We indicate the non-presence of OMAP data by returning empty tables.
568*9712c20fSFrederick Mayle     omap_data->omap_from.clear();
569*9712c20fSFrederick Mayle     omap_data->omap_to.clear();
570*9712c20fSFrederick Mayle     omap_data->length_original = 0;
571*9712c20fSFrederick Mayle     return true;
572*9712c20fSFrederick Mayle   }
573*9712c20fSFrederick Mayle 
574*9712c20fSFrederick Mayle   // OMAP data is present. Disable translation.
575*9712c20fSFrederick Mayle   if (FAILED(address_map->put_addressMapEnabled(FALSE))) {
576*9712c20fSFrederick Mayle     fprintf(stderr, "IDiaAddressMap::put_addressMapEnabled failed\n");
577*9712c20fSFrederick Mayle     return false;
578*9712c20fSFrederick Mayle   }
579*9712c20fSFrederick Mayle 
580*9712c20fSFrederick Mayle   // Read the OMAP streams.
581*9712c20fSFrederick Mayle   if (!FindAndLoadOmapTable(kOmapFromDebugStreamName,
582*9712c20fSFrederick Mayle                             session,
583*9712c20fSFrederick Mayle                             &omap_data->omap_from)) {
584*9712c20fSFrederick Mayle     return false;
585*9712c20fSFrederick Mayle   }
586*9712c20fSFrederick Mayle   if (!FindAndLoadOmapTable(kOmapToDebugStreamName,
587*9712c20fSFrederick Mayle                             session,
588*9712c20fSFrederick Mayle                             &omap_data->omap_to)) {
589*9712c20fSFrederick Mayle     return false;
590*9712c20fSFrederick Mayle   }
591*9712c20fSFrederick Mayle 
592*9712c20fSFrederick Mayle   // Get the lengths of the address spaces.
593*9712c20fSFrederick Mayle   if (!GetOriginalImageLength(session, &omap_data->length_original))
594*9712c20fSFrederick Mayle     return false;
595*9712c20fSFrederick Mayle 
596*9712c20fSFrederick Mayle   return true;
597*9712c20fSFrederick Mayle }
598*9712c20fSFrederick Mayle 
BuildImageMap(const OmapData & omap_data,ImageMap * image_map)599*9712c20fSFrederick Mayle void BuildImageMap(const OmapData& omap_data, ImageMap* image_map) {
600*9712c20fSFrederick Mayle   assert(image_map != NULL);
601*9712c20fSFrederick Mayle 
602*9712c20fSFrederick Mayle   BuildMapping(omap_data, &image_map->mapping);
603*9712c20fSFrederick Mayle   BuildEndpointIndexMap(image_map);
604*9712c20fSFrederick Mayle   BuildSubsequentRVAMap(omap_data, &image_map->subsequent_rva_block);
605*9712c20fSFrederick Mayle }
606*9712c20fSFrederick Mayle 
MapAddressRange(const ImageMap & image_map,const AddressRange & original_range,AddressRangeVector * mapped_ranges)607*9712c20fSFrederick Mayle void MapAddressRange(const ImageMap& image_map,
608*9712c20fSFrederick Mayle                      const AddressRange& original_range,
609*9712c20fSFrederick Mayle                      AddressRangeVector* mapped_ranges) {
610*9712c20fSFrederick Mayle   assert(mapped_ranges != NULL);
611*9712c20fSFrederick Mayle 
612*9712c20fSFrederick Mayle   const Mapping& map = image_map.mapping;
613*9712c20fSFrederick Mayle 
614*9712c20fSFrederick Mayle   // Handle the trivial case of an empty image_map. This means that there is
615*9712c20fSFrederick Mayle   // no transformation to be applied, and we can simply return the original
616*9712c20fSFrederick Mayle   // range.
617*9712c20fSFrederick Mayle   if (map.empty()) {
618*9712c20fSFrederick Mayle     mapped_ranges->push_back(original_range);
619*9712c20fSFrederick Mayle     return;
620*9712c20fSFrederick Mayle   }
621*9712c20fSFrederick Mayle 
622*9712c20fSFrederick Mayle   // If we get a query of length 0 we need to handle it by using a non-zero
623*9712c20fSFrederick Mayle   // query length.
624*9712c20fSFrederick Mayle   AddressRange query_range(original_range);
625*9712c20fSFrederick Mayle   if (query_range.length == 0)
626*9712c20fSFrederick Mayle     query_range.length = 1;
627*9712c20fSFrederick Mayle 
628*9712c20fSFrederick Mayle   // Find the range of intervals that can potentially intersect our query range.
629*9712c20fSFrederick Mayle   size_t imin = 0;
630*9712c20fSFrederick Mayle   size_t imax = 0;
631*9712c20fSFrederick Mayle   {
632*9712c20fSFrederick Mayle     // The index of the earliest possible range that can affect is us done by
633*9712c20fSFrederick Mayle     // searching through the secondary indexing structure.
634*9712c20fSFrederick Mayle     const EndpointIndexMap& eim = image_map.endpoint_index_map;
635*9712c20fSFrederick Mayle     EndpointIndex q1 = { query_range.rva, 0 };
636*9712c20fSFrederick Mayle     EndpointIndexMap::const_iterator it1 = std::lower_bound(
637*9712c20fSFrederick Mayle         eim.begin(), eim.end(), q1, EndpointIndexLess);
638*9712c20fSFrederick Mayle     if (it1 == eim.end()) {
639*9712c20fSFrederick Mayle       imin  = map.size();
640*9712c20fSFrederick Mayle     } else {
641*9712c20fSFrederick Mayle       // Backup to find the interval that contains our query point.
642*9712c20fSFrederick Mayle       if (it1 != eim.begin() && query_range.rva < it1->endpoint)
643*9712c20fSFrederick Mayle         --it1;
644*9712c20fSFrederick Mayle       imin = it1->index;
645*9712c20fSFrederick Mayle     }
646*9712c20fSFrederick Mayle 
647*9712c20fSFrederick Mayle     // The first range that can't possibly intersect us is found by searching
648*9712c20fSFrederick Mayle     // through the image map directly as it is already sorted by interval start
649*9712c20fSFrederick Mayle     // point.
650*9712c20fSFrederick Mayle     MappedRange q2 = { query_range.end(), 0 };
651*9712c20fSFrederick Mayle     Mapping::const_iterator it2 = std::lower_bound(
652*9712c20fSFrederick Mayle         map.begin(), map.end(), q2, MappedRangeOriginalLess);
653*9712c20fSFrederick Mayle     imax = it2 - map.begin();
654*9712c20fSFrederick Mayle   }
655*9712c20fSFrederick Mayle 
656*9712c20fSFrederick Mayle   // Find all intervals that intersect the query range.
657*9712c20fSFrederick Mayle   Mapping temp_map;
658*9712c20fSFrederick Mayle   for (size_t i = imin; i < imax; ++i) {
659*9712c20fSFrederick Mayle     MappedRange mr = map[i];
660*9712c20fSFrederick Mayle     ClipMappedRangeOriginal(query_range, &mr);
661*9712c20fSFrederick Mayle     if (mr.length + mr.injected > 0)
662*9712c20fSFrederick Mayle       temp_map.push_back(mr);
663*9712c20fSFrederick Mayle   }
664*9712c20fSFrederick Mayle 
665*9712c20fSFrederick Mayle   // If there are no intersecting ranges then the query range has been removed
666*9712c20fSFrederick Mayle   // from the image in question.
667*9712c20fSFrederick Mayle   if (temp_map.empty())
668*9712c20fSFrederick Mayle     return;
669*9712c20fSFrederick Mayle 
670*9712c20fSFrederick Mayle   // Sort based on transformed addresses.
671*9712c20fSFrederick Mayle   std::sort(temp_map.begin(), temp_map.end(), MappedRangeMappedLess);
672*9712c20fSFrederick Mayle 
673*9712c20fSFrederick Mayle   // Zero-length queries can't actually be merged. We simply output the set of
674*9712c20fSFrederick Mayle   // unique RVAs that correspond to the query RVA.
675*9712c20fSFrederick Mayle   if (original_range.length == 0) {
676*9712c20fSFrederick Mayle     mapped_ranges->push_back(AddressRange(temp_map[0].rva_transformed, 0));
677*9712c20fSFrederick Mayle     for (size_t i = 1; i < temp_map.size(); ++i) {
678*9712c20fSFrederick Mayle       if (temp_map[i].rva_transformed > mapped_ranges->back().rva)
679*9712c20fSFrederick Mayle         mapped_ranges->push_back(AddressRange(temp_map[i].rva_transformed, 0));
680*9712c20fSFrederick Mayle     }
681*9712c20fSFrederick Mayle     return;
682*9712c20fSFrederick Mayle   }
683*9712c20fSFrederick Mayle 
684*9712c20fSFrederick Mayle   // Merge any ranges that are consecutive in the mapped image. We merge over
685*9712c20fSFrederick Mayle   // injected content if it makes ranges contiguous, but we ignore any injected
686*9712c20fSFrederick Mayle   // content at the tail end of a range. This allows us to detect symbols that
687*9712c20fSFrederick Mayle   // have been lengthened by injecting content in the middle. However, it
688*9712c20fSFrederick Mayle   // misses the case where content has been injected at the head or the tail.
689*9712c20fSFrederick Mayle   // The problem is that it doesn't know whether to attribute it to the
690*9712c20fSFrederick Mayle   // preceding or following symbol. It is up to the author of the transform to
691*9712c20fSFrederick Mayle   // output explicit OMAP info in these cases to ensure full coverage of the
692*9712c20fSFrederick Mayle   // transformed address space.
693*9712c20fSFrederick Mayle   DWORD rva_begin = temp_map[0].rva_transformed;
694*9712c20fSFrederick Mayle   DWORD rva_cur_content = rva_begin + temp_map[0].length;
695*9712c20fSFrederick Mayle   DWORD rva_cur_injected = rva_cur_content + temp_map[0].injected;
696*9712c20fSFrederick Mayle   for (size_t i = 1; i < temp_map.size(); ++i) {
697*9712c20fSFrederick Mayle     if (rva_cur_injected < temp_map[i].rva_transformed) {
698*9712c20fSFrederick Mayle       // This marks the end of a continuous range in the image. Output the
699*9712c20fSFrederick Mayle       // current range and start a new one.
700*9712c20fSFrederick Mayle       if (rva_begin < rva_cur_content) {
701*9712c20fSFrederick Mayle         mapped_ranges->push_back(
702*9712c20fSFrederick Mayle             AddressRange(rva_begin, rva_cur_content - rva_begin));
703*9712c20fSFrederick Mayle       }
704*9712c20fSFrederick Mayle       rva_begin = temp_map[i].rva_transformed;
705*9712c20fSFrederick Mayle     }
706*9712c20fSFrederick Mayle 
707*9712c20fSFrederick Mayle     rva_cur_content = temp_map[i].rva_transformed + temp_map[i].length;
708*9712c20fSFrederick Mayle     rva_cur_injected = rva_cur_content + temp_map[i].injected;
709*9712c20fSFrederick Mayle   }
710*9712c20fSFrederick Mayle 
711*9712c20fSFrederick Mayle   // Output the range in progress.
712*9712c20fSFrederick Mayle   if (rva_begin < rva_cur_content) {
713*9712c20fSFrederick Mayle     mapped_ranges->push_back(
714*9712c20fSFrederick Mayle         AddressRange(rva_begin, rva_cur_content - rva_begin));
715*9712c20fSFrederick Mayle   }
716*9712c20fSFrederick Mayle 
717*9712c20fSFrederick Mayle   return;
718*9712c20fSFrederick Mayle }
719*9712c20fSFrederick Mayle 
720*9712c20fSFrederick Mayle }  // namespace google_breakpad
721