OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "courgette/disassembler_win32_x86.h" | 5 #include "courgette/disassembler_win32_x86.h" |
6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
7 #include <algorithm> | 10 #include <algorithm> |
8 #include <string> | 11 #include <string> |
9 #include <vector> | 12 #include <vector> |
10 | 13 |
11 #include "base/basictypes.h" | |
12 #include "base/logging.h" | 14 #include "base/logging.h" |
13 | 15 |
14 #include "courgette/assembly_program.h" | 16 #include "courgette/assembly_program.h" |
15 #include "courgette/courgette.h" | 17 #include "courgette/courgette.h" |
16 #include "courgette/encoded_program.h" | 18 #include "courgette/encoded_program.h" |
17 #include "courgette/rel32_finder_win32_x86.h" | 19 #include "courgette/rel32_finder_win32_x86.h" |
18 | 20 |
19 namespace courgette { | 21 namespace courgette { |
20 | 22 |
21 DisassemblerWin32X86::DisassemblerWin32X86(const void* start, size_t length) | 23 DisassemblerWin32X86::DisassemblerWin32X86(const void* start, size_t length) |
(...skipping 26 matching lines...) Expand all Loading... |
48 // | 50 // |
49 bool DisassemblerWin32X86::ParseHeader() { | 51 bool DisassemblerWin32X86::ParseHeader() { |
50 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/) | 52 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/) |
51 return Bad("Too small"); | 53 return Bad("Too small"); |
52 | 54 |
53 // Have 'MZ' magic for a DOS header? | 55 // Have 'MZ' magic for a DOS header? |
54 if (start()[0] != 'M' || start()[1] != 'Z') | 56 if (start()[0] != 'M' || start()[1] != 'Z') |
55 return Bad("Not MZ"); | 57 return Bad("Not MZ"); |
56 | 58 |
57 // offset from DOS header to PE header is stored in DOS header. | 59 // offset from DOS header to PE header is stored in DOS header. |
58 uint32 offset = ReadU32(start(), | 60 uint32_t offset = ReadU32(start(), kOffsetOfFileAddressOfNewExeHeader); |
59 kOffsetOfFileAddressOfNewExeHeader); | |
60 | 61 |
61 if (offset >= length()) | 62 if (offset >= length()) |
62 return Bad("Bad offset to PE header"); | 63 return Bad("Bad offset to PE header"); |
63 | 64 |
64 const uint8* const pe_header = OffsetToPointer(offset); | 65 const uint8_t* const pe_header = OffsetToPointer(offset); |
65 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader; | 66 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader; |
66 if (pe_header <= start() || | 67 if (pe_header <= start() || |
67 pe_header >= end() - kMinPEHeaderSize) | 68 pe_header >= end() - kMinPEHeaderSize) |
68 return Bad("Bad offset to PE header"); | 69 return Bad("Bad offset to PE header"); |
69 | 70 |
70 if (offset % 8 != 0) | 71 if (offset % 8 != 0) |
71 return Bad("Misaligned PE header"); | 72 return Bad("Misaligned PE header"); |
72 | 73 |
73 // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H. | 74 // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H. |
74 // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx | 75 // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx |
75 // | 76 // |
76 // The first field of the IMAGE_NT_HEADERS is the signature. | 77 // The first field of the IMAGE_NT_HEADERS is the signature. |
77 if (!(pe_header[0] == 'P' && | 78 if (!(pe_header[0] == 'P' && |
78 pe_header[1] == 'E' && | 79 pe_header[1] == 'E' && |
79 pe_header[2] == 0 && | 80 pe_header[2] == 0 && |
80 pe_header[3] == 0)) | 81 pe_header[3] == 0)) |
81 return Bad("no PE signature"); | 82 return Bad("no PE signature"); |
82 | 83 |
83 // The second field of the IMAGE_NT_HEADERS is the COFF header. | 84 // The second field of the IMAGE_NT_HEADERS is the COFF header. |
84 // The COFF header is also called an IMAGE_FILE_HEADER | 85 // The COFF header is also called an IMAGE_FILE_HEADER |
85 // http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx | 86 // http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx |
86 const uint8* const coff_header = pe_header + 4; | 87 const uint8_t* const coff_header = pe_header + 4; |
87 machine_type_ = ReadU16(coff_header, 0); | 88 machine_type_ = ReadU16(coff_header, 0); |
88 number_of_sections_ = ReadU16(coff_header, 2); | 89 number_of_sections_ = ReadU16(coff_header, 2); |
89 size_of_optional_header_ = ReadU16(coff_header, 16); | 90 size_of_optional_header_ = ReadU16(coff_header, 16); |
90 | 91 |
91 // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64) | 92 // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64) |
92 const uint8* const optional_header = coff_header + kSizeOfCoffHeader; | 93 const uint8_t* const optional_header = coff_header + kSizeOfCoffHeader; |
93 optional_header_ = optional_header; | 94 optional_header_ = optional_header; |
94 | 95 |
95 if (optional_header + size_of_optional_header_ >= end()) | 96 if (optional_header + size_of_optional_header_ >= end()) |
96 return Bad("optional header past end of file"); | 97 return Bad("optional header past end of file"); |
97 | 98 |
98 // Check we can read the magic. | 99 // Check we can read the magic. |
99 if (size_of_optional_header_ < 2) | 100 if (size_of_optional_header_ < 2) |
100 return Bad("optional header no magic"); | 101 return Bad("optional header no magic"); |
101 | 102 |
102 uint16 magic = ReadU16(optional_header, 0); | 103 uint16_t magic = ReadU16(optional_header, 0); |
103 | 104 |
104 if (magic == kImageNtOptionalHdr32Magic) { | 105 if (magic == kImageNtOptionalHdr32Magic) { |
105 is_PE32_plus_ = false; | 106 is_PE32_plus_ = false; |
106 offset_of_data_directories_ = | 107 offset_of_data_directories_ = |
107 kOffsetOfDataDirectoryFromImageOptionalHeader32; | 108 kOffsetOfDataDirectoryFromImageOptionalHeader32; |
108 } else if (magic == kImageNtOptionalHdr64Magic) { | 109 } else if (magic == kImageNtOptionalHdr64Magic) { |
109 is_PE32_plus_ = true; | 110 is_PE32_plus_ = true; |
110 offset_of_data_directories_ = | 111 offset_of_data_directories_ = |
111 kOffsetOfDataDirectoryFromImageOptionalHeader64; | 112 kOffsetOfDataDirectoryFromImageOptionalHeader64; |
112 } else { | 113 } else { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 size_t detected_length = 0; | 170 size_t detected_length = 0; |
170 | 171 |
171 for (int i = 0; i < number_of_sections_; ++i) { | 172 for (int i = 0; i < number_of_sections_; ++i) { |
172 const Section* section = §ions_[i]; | 173 const Section* section = §ions_[i]; |
173 | 174 |
174 // TODO(sra): consider using the 'characteristics' field of the section | 175 // TODO(sra): consider using the 'characteristics' field of the section |
175 // header to see if the section contains instructions. | 176 // header to see if the section contains instructions. |
176 if (memcmp(section->name, ".text", 6) == 0) | 177 if (memcmp(section->name, ".text", 6) == 0) |
177 has_text_section_ = true; | 178 has_text_section_ = true; |
178 | 179 |
179 uint32 section_end = | 180 uint32_t section_end = |
180 section->file_offset_of_raw_data + section->size_of_raw_data; | 181 section->file_offset_of_raw_data + section->size_of_raw_data; |
181 if (section_end > detected_length) | 182 if (section_end > detected_length) |
182 detected_length = section_end; | 183 detected_length = section_end; |
183 } | 184 } |
184 | 185 |
185 // Pretend our in-memory copy is only as long as our detected length. | 186 // Pretend our in-memory copy is only as long as our detected length. |
186 ReduceLength(detected_length); | 187 ReduceLength(detected_length); |
187 | 188 |
188 if (!is_32bit()) { | 189 if (!is_32bit()) { |
189 return Bad("64 bit executables are not supported by this disassembler"); | 190 return Bad("64 bit executables are not supported by this disassembler"); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 | 223 |
223 size_t relocs_size = base_relocation_table_.size_; | 224 size_t relocs_size = base_relocation_table_.size_; |
224 if (relocs_size == 0) | 225 if (relocs_size == 0) |
225 return true; | 226 return true; |
226 | 227 |
227 // The format of the base relocation table is a sequence of variable sized | 228 // The format of the base relocation table is a sequence of variable sized |
228 // IMAGE_BASE_RELOCATION blocks. Search for | 229 // IMAGE_BASE_RELOCATION blocks. Search for |
229 // "The format of the base relocation data is somewhat quirky" | 230 // "The format of the base relocation data is somewhat quirky" |
230 // at http://msdn.microsoft.com/en-us/library/ms809762.aspx | 231 // at http://msdn.microsoft.com/en-us/library/ms809762.aspx |
231 | 232 |
232 const uint8* relocs_start = RVAToPointer(base_relocation_table_.address_); | 233 const uint8_t* relocs_start = RVAToPointer(base_relocation_table_.address_); |
233 const uint8* relocs_end = relocs_start + relocs_size; | 234 const uint8_t* relocs_end = relocs_start + relocs_size; |
234 | 235 |
235 // Make sure entire base relocation table is within the buffer. | 236 // Make sure entire base relocation table is within the buffer. |
236 if (relocs_start < start() || | 237 if (relocs_start < start() || |
237 relocs_start >= end() || | 238 relocs_start >= end() || |
238 relocs_end <= start() || | 239 relocs_end <= start() || |
239 relocs_end > end()) { | 240 relocs_end > end()) { |
240 return Bad(".relocs outside image"); | 241 return Bad(".relocs outside image"); |
241 } | 242 } |
242 | 243 |
243 const uint8* block = relocs_start; | 244 const uint8_t* block = relocs_start; |
244 | 245 |
245 // Walk the variable sized blocks. | 246 // Walk the variable sized blocks. |
246 while (block + 8 < relocs_end) { | 247 while (block + 8 < relocs_end) { |
247 RVA page_rva = ReadU32(block, 0); | 248 RVA page_rva = ReadU32(block, 0); |
248 uint32 size = ReadU32(block, 4); | 249 uint32_t size = ReadU32(block, 4); |
249 if (size < 8 || // Size includes header ... | 250 if (size < 8 || // Size includes header ... |
250 size % 4 != 0) // ... and is word aligned. | 251 size % 4 != 0) // ... and is word aligned. |
251 return Bad("unreasonable relocs block"); | 252 return Bad("unreasonable relocs block"); |
252 | 253 |
253 const uint8* end_entries = block + size; | 254 const uint8_t* end_entries = block + size; |
254 | 255 |
255 if (end_entries <= block || | 256 if (end_entries <= block || |
256 end_entries <= start() || | 257 end_entries <= start() || |
257 end_entries > end()) | 258 end_entries > end()) |
258 return Bad(".relocs block outside image"); | 259 return Bad(".relocs block outside image"); |
259 | 260 |
260 // Walk through the two-byte entries. | 261 // Walk through the two-byte entries. |
261 for (const uint8* p = block + 8; p < end_entries; p += 2) { | 262 for (const uint8_t* p = block + 8; p < end_entries; p += 2) { |
262 uint16 entry = ReadU16(p, 0); | 263 uint16_t entry = ReadU16(p, 0); |
263 int type = entry >> 12; | 264 int type = entry >> 12; |
264 int offset = entry & 0xFFF; | 265 int offset = entry & 0xFFF; |
265 | 266 |
266 RVA rva = page_rva + offset; | 267 RVA rva = page_rva + offset; |
267 // Skip the relocs that live outside of the image. It might be the case | 268 // Skip the relocs that live outside of the image. It might be the case |
268 // if a reloc is relative to a register, e.g.: | 269 // if a reloc is relative to a register, e.g.: |
269 // mov ecx,dword ptr [eax+044D5888h] | 270 // mov ecx,dword ptr [eax+044D5888h] |
270 uint32 target_address = Read32LittleEndian(RVAToPointer(rva)); | 271 uint32_t target_address = Read32LittleEndian(RVAToPointer(rva)); |
271 if (target_address < image_base_ || | 272 if (target_address < image_base_ || |
272 target_address > (image_base_ + size_of_image_)) { | 273 target_address > (image_base_ + size_of_image_)) { |
273 continue; | 274 continue; |
274 } | 275 } |
275 if (type == 3) { // IMAGE_REL_BASED_HIGHLOW | 276 if (type == 3) { // IMAGE_REL_BASED_HIGHLOW |
276 relocs->push_back(rva); | 277 relocs->push_back(rva); |
277 } else if (type == 0) { // IMAGE_REL_BASED_ABSOLUTE | 278 } else if (type == 0) { // IMAGE_REL_BASED_ABSOLUTE |
278 // Ignore, used as padding. | 279 // Ignore, used as padding. |
279 } else { | 280 } else { |
280 // Does not occur in Windows x86 executables. | 281 // Does not occur in Windows x86 executables. |
281 return Bad("unknown type of reloc"); | 282 return Bad("unknown type of reloc"); |
282 } | 283 } |
283 } | 284 } |
284 | 285 |
285 block += size; | 286 block += size; |
286 } | 287 } |
287 | 288 |
288 std::sort(relocs->begin(), relocs->end()); | 289 std::sort(relocs->begin(), relocs->end()); |
289 | 290 |
290 return true; | 291 return true; |
291 } | 292 } |
292 | 293 |
293 const Section* DisassemblerWin32X86::RVAToSection(RVA rva) const { | 294 const Section* DisassemblerWin32X86::RVAToSection(RVA rva) const { |
294 for (int i = 0; i < number_of_sections_; i++) { | 295 for (int i = 0; i < number_of_sections_; i++) { |
295 const Section* section = §ions_[i]; | 296 const Section* section = §ions_[i]; |
296 uint32 offset = rva - section->virtual_address; | 297 uint32_t offset = rva - section->virtual_address; |
297 if (offset < section->virtual_size) { | 298 if (offset < section->virtual_size) { |
298 return section; | 299 return section; |
299 } | 300 } |
300 } | 301 } |
301 return NULL; | 302 return NULL; |
302 } | 303 } |
303 | 304 |
304 int DisassemblerWin32X86::RVAToFileOffset(RVA rva) const { | 305 int DisassemblerWin32X86::RVAToFileOffset(RVA rva) const { |
305 const Section* section = RVAToSection(rva); | 306 const Section* section = RVAToSection(rva); |
306 if (section) { | 307 if (section) { |
307 uint32 offset = rva - section->virtual_address; | 308 uint32_t offset = rva - section->virtual_address; |
308 if (offset < section->size_of_raw_data) { | 309 if (offset < section->size_of_raw_data) { |
309 return section->file_offset_of_raw_data + offset; | 310 return section->file_offset_of_raw_data + offset; |
310 } else { | 311 } else { |
311 return kNoOffset; // In section but not in file (e.g. uninit data). | 312 return kNoOffset; // In section but not in file (e.g. uninit data). |
312 } | 313 } |
313 } | 314 } |
314 | 315 |
315 // Small RVA values point into the file header in the loaded image. | 316 // Small RVA values point into the file header in the loaded image. |
316 // RVA 0 is the module load address which Windows uses as the module handle. | 317 // RVA 0 is the module load address which Windows uses as the module handle. |
317 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the | 318 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the |
318 // DOS header. | 319 // DOS header. |
319 if (rva == 0 || rva == 2) | 320 if (rva == 0 || rva == 2) |
320 return rva; | 321 return rva; |
321 | 322 |
322 NOTREACHED(); | 323 NOTREACHED(); |
323 return kNoOffset; | 324 return kNoOffset; |
324 } | 325 } |
325 | 326 |
326 const uint8* DisassemblerWin32X86::RVAToPointer(RVA rva) const { | 327 const uint8_t* DisassemblerWin32X86::RVAToPointer(RVA rva) const { |
327 int file_offset = RVAToFileOffset(rva); | 328 int file_offset = RVAToFileOffset(rva); |
328 if (file_offset == kNoOffset) | 329 if (file_offset == kNoOffset) |
329 return NULL; | 330 return NULL; |
330 else | 331 else |
331 return OffsetToPointer(file_offset); | 332 return OffsetToPointer(file_offset); |
332 } | 333 } |
333 | 334 |
334 std::string DisassemblerWin32X86::SectionName(const Section* section) { | 335 std::string DisassemblerWin32X86::SectionName(const Section* section) { |
335 if (section == NULL) | 336 if (section == NULL) |
336 return "<none>"; | 337 return "<none>"; |
337 char name[9]; | 338 char name[9]; |
338 memcpy(name, section->name, 8); | 339 memcpy(name, section->name, 8); |
339 name[8] = '\0'; // Ensure termination. | 340 name[8] = '\0'; // Ensure termination. |
340 return name; | 341 return name; |
341 } | 342 } |
342 | 343 |
343 CheckBool DisassemblerWin32X86::ParseFile(AssemblyProgram* program) { | 344 CheckBool DisassemblerWin32X86::ParseFile(AssemblyProgram* program) { |
344 // Walk all the bytes in the file, whether or not in a section. | 345 // Walk all the bytes in the file, whether or not in a section. |
345 uint32 file_offset = 0; | 346 uint32_t file_offset = 0; |
346 while (file_offset < length()) { | 347 while (file_offset < length()) { |
347 const Section* section = FindNextSection(file_offset); | 348 const Section* section = FindNextSection(file_offset); |
348 if (section == NULL) { | 349 if (section == NULL) { |
349 // No more sections. There should not be extra stuff following last | 350 // No more sections. There should not be extra stuff following last |
350 // section. | 351 // section. |
351 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program); | 352 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program); |
352 break; | 353 break; |
353 } | 354 } |
354 if (file_offset < section->file_offset_of_raw_data) { | 355 if (file_offset < section->file_offset_of_raw_data) { |
355 uint32 section_start_offset = section->file_offset_of_raw_data; | 356 uint32_t section_start_offset = section->file_offset_of_raw_data; |
356 if(!ParseNonSectionFileRegion(file_offset, section_start_offset, | 357 if(!ParseNonSectionFileRegion(file_offset, section_start_offset, |
357 program)) | 358 program)) |
358 return false; | 359 return false; |
359 | 360 |
360 file_offset = section_start_offset; | 361 file_offset = section_start_offset; |
361 } | 362 } |
362 uint32 end = file_offset + section->size_of_raw_data; | 363 uint32_t end = file_offset + section->size_of_raw_data; |
363 if (!ParseFileRegion(section, file_offset, end, program)) | 364 if (!ParseFileRegion(section, file_offset, end, program)) |
364 return false; | 365 return false; |
365 file_offset = end; | 366 file_offset = end; |
366 } | 367 } |
367 | 368 |
368 #if COURGETTE_HISTOGRAM_TARGETS | 369 #if COURGETTE_HISTOGRAM_TARGETS |
369 HistogramTargets("abs32 relocs", abs32_target_rvas_); | 370 HistogramTargets("abs32 relocs", abs32_target_rvas_); |
370 HistogramTargets("rel32 relocs", rel32_target_rvas_); | 371 HistogramTargets("rel32 relocs", rel32_target_rvas_); |
371 #endif | 372 #endif |
372 | 373 |
373 return true; | 374 return true; |
374 } | 375 } |
375 | 376 |
376 bool DisassemblerWin32X86::ParseAbs32Relocs() { | 377 bool DisassemblerWin32X86::ParseAbs32Relocs() { |
377 abs32_locations_.clear(); | 378 abs32_locations_.clear(); |
378 if (!ParseRelocs(&abs32_locations_)) | 379 if (!ParseRelocs(&abs32_locations_)) |
379 return false; | 380 return false; |
380 | 381 |
381 #if COURGETTE_HISTOGRAM_TARGETS | 382 #if COURGETTE_HISTOGRAM_TARGETS |
382 for (size_t i = 0; i < abs32_locations_.size(); ++i) { | 383 for (size_t i = 0; i < abs32_locations_.size(); ++i) { |
383 RVA rva = abs32_locations_[i]; | 384 RVA rva = abs32_locations_[i]; |
384 // The 4 bytes at the relocation are a reference to some address. | 385 // The 4 bytes at the relocation are a reference to some address. |
385 uint32 target_address = Read32LittleEndian(RVAToPointer(rva)); | 386 uint32_t target_address = Read32LittleEndian(RVAToPointer(rva)); |
386 ++abs32_target_rvas_[target_address - image_base()]; | 387 ++abs32_target_rvas_[target_address - image_base()]; |
387 } | 388 } |
388 #endif | 389 #endif |
389 return true; | 390 return true; |
390 } | 391 } |
391 | 392 |
392 void DisassemblerWin32X86::ParseRel32RelocsFromSections() { | 393 void DisassemblerWin32X86::ParseRel32RelocsFromSections() { |
393 uint32 file_offset = 0; | 394 uint32_t file_offset = 0; |
394 while (file_offset < length()) { | 395 while (file_offset < length()) { |
395 const Section* section = FindNextSection(file_offset); | 396 const Section* section = FindNextSection(file_offset); |
396 if (section == NULL) | 397 if (section == NULL) |
397 break; | 398 break; |
398 if (file_offset < section->file_offset_of_raw_data) | 399 if (file_offset < section->file_offset_of_raw_data) |
399 file_offset = section->file_offset_of_raw_data; | 400 file_offset = section->file_offset_of_raw_data; |
400 ParseRel32RelocsFromSection(section); | 401 ParseRel32RelocsFromSection(section); |
401 file_offset += section->size_of_raw_data; | 402 file_offset += section->size_of_raw_data; |
402 } | 403 } |
403 std::sort(rel32_locations_.begin(), rel32_locations_.end()); | 404 std::sort(rel32_locations_.begin(), rel32_locations_.end()); |
(...skipping 22 matching lines...) Expand all Loading... |
426 VLOG(1) << "common " << common; | 427 VLOG(1) << "common " << common; |
427 #endif | 428 #endif |
428 } | 429 } |
429 | 430 |
430 void DisassemblerWin32X86::ParseRel32RelocsFromSection(const Section* section) { | 431 void DisassemblerWin32X86::ParseRel32RelocsFromSection(const Section* section) { |
431 // TODO(sra): use characteristic. | 432 // TODO(sra): use characteristic. |
432 bool isCode = strcmp(section->name, ".text") == 0; | 433 bool isCode = strcmp(section->name, ".text") == 0; |
433 if (!isCode) | 434 if (!isCode) |
434 return; | 435 return; |
435 | 436 |
436 uint32 start_file_offset = section->file_offset_of_raw_data; | 437 uint32_t start_file_offset = section->file_offset_of_raw_data; |
437 uint32 end_file_offset = start_file_offset + section->size_of_raw_data; | 438 uint32_t end_file_offset = start_file_offset + section->size_of_raw_data; |
438 | 439 |
439 const uint8* start_pointer = OffsetToPointer(start_file_offset); | 440 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); |
440 const uint8* end_pointer = OffsetToPointer(end_file_offset); | 441 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); |
441 | 442 |
442 RVA start_rva = FileOffsetToRVA(start_file_offset); | 443 RVA start_rva = FileOffsetToRVA(start_file_offset); |
443 RVA end_rva = start_rva + section->virtual_size; | 444 RVA end_rva = start_rva + section->virtual_size; |
444 | 445 |
445 Rel32FinderWin32X86_Basic finder( | 446 Rel32FinderWin32X86_Basic finder( |
446 base_relocation_table().address_, | 447 base_relocation_table().address_, |
447 base_relocation_table().address_ + base_relocation_table().size_, | 448 base_relocation_table().address_ + base_relocation_table().size_, |
448 size_of_image_); | 449 size_of_image_); |
449 finder.Find(start_pointer, end_pointer, start_rva, end_rva, abs32_locations_); | 450 finder.Find(start_pointer, end_pointer, start_rva, end_rva, abs32_locations_); |
450 finder.SwapRel32Locations(&rel32_locations_); | 451 finder.SwapRel32Locations(&rel32_locations_); |
451 | 452 |
452 #if COURGETTE_HISTOGRAM_TARGETS | 453 #if COURGETTE_HISTOGRAM_TARGETS |
453 DCHECK(rel32_target_rvas_.empty()); | 454 DCHECK(rel32_target_rvas_.empty()); |
454 finder.SwapRel32TargetRVAs(&rel32_target_rvas_); | 455 finder.SwapRel32TargetRVAs(&rel32_target_rvas_); |
455 #endif | 456 #endif |
456 } | 457 } |
457 | 458 |
458 CheckBool DisassemblerWin32X86::ParseNonSectionFileRegion( | 459 CheckBool DisassemblerWin32X86::ParseNonSectionFileRegion( |
459 uint32 start_file_offset, | 460 uint32_t start_file_offset, |
460 uint32 end_file_offset, | 461 uint32_t end_file_offset, |
461 AssemblyProgram* program) { | 462 AssemblyProgram* program) { |
462 if (incomplete_disassembly_) | 463 if (incomplete_disassembly_) |
463 return true; | 464 return true; |
464 | 465 |
465 if (end_file_offset > start_file_offset) { | 466 if (end_file_offset > start_file_offset) { |
466 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset), | 467 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset), |
467 end_file_offset - start_file_offset)) { | 468 end_file_offset - start_file_offset)) { |
468 return false; | 469 return false; |
469 } | 470 } |
470 } | 471 } |
471 | 472 |
472 return true; | 473 return true; |
473 } | 474 } |
474 | 475 |
475 CheckBool DisassemblerWin32X86::ParseFileRegion( | 476 CheckBool DisassemblerWin32X86::ParseFileRegion(const Section* section, |
476 const Section* section, | 477 uint32_t start_file_offset, |
477 uint32 start_file_offset, uint32 end_file_offset, | 478 uint32_t end_file_offset, |
478 AssemblyProgram* program) { | 479 AssemblyProgram* program) { |
479 RVA relocs_start_rva = base_relocation_table().address_; | 480 RVA relocs_start_rva = base_relocation_table().address_; |
480 | 481 |
481 const uint8* start_pointer = OffsetToPointer(start_file_offset); | 482 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); |
482 const uint8* end_pointer = OffsetToPointer(end_file_offset); | 483 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); |
483 | 484 |
484 RVA start_rva = FileOffsetToRVA(start_file_offset); | 485 RVA start_rva = FileOffsetToRVA(start_file_offset); |
485 RVA end_rva = start_rva + section->virtual_size; | 486 RVA end_rva = start_rva + section->virtual_size; |
486 | 487 |
487 // Quick way to convert from Pointer to RVA within a single Section is to | 488 // Quick way to convert from Pointer to RVA within a single Section is to |
488 // subtract 'pointer_to_rva'. | 489 // subtract 'pointer_to_rva'. |
489 const uint8* const adjust_pointer_to_rva = start_pointer - start_rva; | 490 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva; |
490 | 491 |
491 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin(); | 492 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin(); |
492 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin(); | 493 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin(); |
493 | 494 |
494 if (!program->EmitOriginInstruction(start_rva)) | 495 if (!program->EmitOriginInstruction(start_rva)) |
495 return false; | 496 return false; |
496 | 497 |
497 const uint8* p = start_pointer; | 498 const uint8_t* p = start_pointer; |
498 | 499 |
499 while (p < end_pointer) { | 500 while (p < end_pointer) { |
500 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 501 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
501 | 502 |
502 // The base relocation table is usually in the .relocs section, but it could | 503 // The base relocation table is usually in the .relocs section, but it could |
503 // actually be anywhere. Make sure we skip it because we will regenerate it | 504 // actually be anywhere. Make sure we skip it because we will regenerate it |
504 // during assembly. | 505 // during assembly. |
505 if (current_rva == relocs_start_rva) { | 506 if (current_rva == relocs_start_rva) { |
506 if (!program->EmitPeRelocsInstruction()) | 507 if (!program->EmitPeRelocsInstruction()) |
507 return false; | 508 return false; |
508 uint32 relocs_size = base_relocation_table().size_; | 509 uint32_t relocs_size = base_relocation_table().size_; |
509 if (relocs_size) { | 510 if (relocs_size) { |
510 p += relocs_size; | 511 p += relocs_size; |
511 continue; | 512 continue; |
512 } | 513 } |
513 } | 514 } |
514 | 515 |
515 while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) | 516 while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) |
516 ++abs32_pos; | 517 ++abs32_pos; |
517 | 518 |
518 if (abs32_pos != abs32_locations_.end() && *abs32_pos == current_rva) { | 519 if (abs32_pos != abs32_locations_.end() && *abs32_pos == current_rva) { |
519 uint32 target_address = Read32LittleEndian(p); | 520 uint32_t target_address = Read32LittleEndian(p); |
520 RVA target_rva = target_address - image_base(); | 521 RVA target_rva = target_address - image_base(); |
521 // TODO(sra): target could be Label+offset. It is not clear how to guess | 522 // TODO(sra): target could be Label+offset. It is not clear how to guess |
522 // which it might be. We assume offset==0. | 523 // which it might be. We assume offset==0. |
523 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva))) | 524 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva))) |
524 return false; | 525 return false; |
525 p += 4; | 526 p += 4; |
526 continue; | 527 continue; |
527 } | 528 } |
528 | 529 |
529 while (rel32_pos != rel32_locations_.end() && *rel32_pos < current_rva) | 530 while (rel32_pos != rel32_locations_.end() && *rel32_pos < current_rva) |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 s << std::hex << rva; | 612 s << std::hex << rva; |
612 if (section) { | 613 if (section) { |
613 s << " ("; | 614 s << " ("; |
614 s << SectionName(section) << "+" | 615 s << SectionName(section) << "+" |
615 << std::hex << (rva - section->virtual_address) | 616 << std::hex << (rva - section->virtual_address) |
616 << ")"; | 617 << ")"; |
617 } | 618 } |
618 return s.str(); | 619 return s.str(); |
619 } | 620 } |
620 | 621 |
621 const Section* DisassemblerWin32X86::FindNextSection(uint32 fileOffset) const { | 622 const Section* DisassemblerWin32X86::FindNextSection( |
| 623 uint32_t fileOffset) const { |
622 const Section* best = 0; | 624 const Section* best = 0; |
623 for (int i = 0; i < number_of_sections_; i++) { | 625 for (int i = 0; i < number_of_sections_; i++) { |
624 const Section* section = §ions_[i]; | 626 const Section* section = §ions_[i]; |
625 if (section->size_of_raw_data > 0) { // i.e. has data in file. | 627 if (section->size_of_raw_data > 0) { // i.e. has data in file. |
626 if (fileOffset <= section->file_offset_of_raw_data) { | 628 if (fileOffset <= section->file_offset_of_raw_data) { |
627 if (best == 0 || | 629 if (best == 0 || |
628 section->file_offset_of_raw_data < best->file_offset_of_raw_data) { | 630 section->file_offset_of_raw_data < best->file_offset_of_raw_data) { |
629 best = section; | 631 best = section; |
630 } | 632 } |
631 } | 633 } |
632 } | 634 } |
633 } | 635 } |
634 return best; | 636 return best; |
635 } | 637 } |
636 | 638 |
637 RVA DisassemblerWin32X86::FileOffsetToRVA(uint32 file_offset) const { | 639 RVA DisassemblerWin32X86::FileOffsetToRVA(uint32_t file_offset) const { |
638 for (int i = 0; i < number_of_sections_; i++) { | 640 for (int i = 0; i < number_of_sections_; i++) { |
639 const Section* section = §ions_[i]; | 641 const Section* section = §ions_[i]; |
640 uint32 offset = file_offset - section->file_offset_of_raw_data; | 642 uint32_t offset = file_offset - section->file_offset_of_raw_data; |
641 if (offset < section->size_of_raw_data) { | 643 if (offset < section->size_of_raw_data) { |
642 return section->virtual_address + offset; | 644 return section->virtual_address + offset; |
643 } | 645 } |
644 } | 646 } |
645 return 0; | 647 return 0; |
646 } | 648 } |
647 | 649 |
648 bool DisassemblerWin32X86::ReadDataDirectory( | 650 bool DisassemblerWin32X86::ReadDataDirectory( |
649 int index, | 651 int index, |
650 ImageDataDirectory* directory) { | 652 ImageDataDirectory* directory) { |
651 | 653 |
652 if (index < number_of_data_directories_) { | 654 if (index < number_of_data_directories_) { |
653 size_t offset = index * 8 + offset_of_data_directories_; | 655 size_t offset = index * 8 + offset_of_data_directories_; |
654 if (offset >= size_of_optional_header_) | 656 if (offset >= size_of_optional_header_) |
655 return Bad("number of data directories inconsistent"); | 657 return Bad("number of data directories inconsistent"); |
656 const uint8* data_directory = optional_header_ + offset; | 658 const uint8_t* data_directory = optional_header_ + offset; |
657 if (data_directory < start() || | 659 if (data_directory < start() || |
658 data_directory + 8 >= end()) | 660 data_directory + 8 >= end()) |
659 return Bad("data directory outside image"); | 661 return Bad("data directory outside image"); |
660 RVA rva = ReadU32(data_directory, 0); | 662 RVA rva = ReadU32(data_directory, 0); |
661 size_t size = ReadU32(data_directory, 4); | 663 size_t size = ReadU32(data_directory, 4); |
662 if (size > size_of_image_) | 664 if (size > size_of_image_) |
663 return Bad("data directory size too big"); | 665 return Bad("data directory size too big"); |
664 | 666 |
665 // TODO(sra): validate RVA. | 667 // TODO(sra): validate RVA. |
666 directory->address_ = rva; | 668 directory->address_ = rva; |
667 directory->size_ = static_cast<uint32>(size); | 669 directory->size_ = static_cast<uint32_t>(size); |
668 return true; | 670 return true; |
669 } else { | 671 } else { |
670 directory->address_ = 0; | 672 directory->address_ = 0; |
671 directory->size_ = 0; | 673 directory->size_ = 0; |
672 return true; | 674 return true; |
673 } | 675 } |
674 } | 676 } |
675 | 677 |
676 } // namespace courgette | 678 } // namespace courgette |
OLD | NEW |