Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: courgette/disassembler_win32_x64.cc

Issue 1676683002: [Courgette] Clean up Disassembler; fix ELF Memory leaks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_x64.h" 5 #include "courgette/disassembler_win32_x64.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <string> 11 #include <iostream>
12 #include <vector>
13 12
14 #include "base/logging.h" 13 #include "base/logging.h"
15 #include "base/numerics/safe_conversions.h" 14 #include "base/numerics/safe_conversions.h"
16
17 #include "courgette/assembly_program.h" 15 #include "courgette/assembly_program.h"
18 #include "courgette/courgette.h" 16 #include "courgette/courgette.h"
19 #include "courgette/encoded_program.h"
20 17
21 namespace courgette { 18 namespace courgette {
22 19
23 DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length) 20 DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length)
24 : Disassembler(start, length), 21 : Disassembler(start, length),
25 incomplete_disassembly_(false), 22 incomplete_disassembly_(false),
26 is_PE32_plus_(false), 23 is_PE32_plus_(false),
27 optional_header_(NULL), 24 optional_header_(nullptr),
28 size_of_optional_header_(0), 25 size_of_optional_header_(0),
29 offset_of_data_directories_(0), 26 offset_of_data_directories_(0),
30 machine_type_(0), 27 machine_type_(0),
31 number_of_sections_(0), 28 number_of_sections_(0),
32 sections_(NULL), 29 sections_(nullptr),
33 has_text_section_(false), 30 has_text_section_(false),
34 size_of_code_(0), 31 size_of_code_(0),
35 size_of_initialized_data_(0), 32 size_of_initialized_data_(0),
36 size_of_uninitialized_data_(0), 33 size_of_uninitialized_data_(0),
37 base_of_code_(0), 34 base_of_code_(0),
38 base_of_data_(0), 35 base_of_data_(0),
39 image_base_(0), 36 image_base_(0),
40 size_of_image_(0), 37 size_of_image_(0),
41 number_of_data_directories_(0) { 38 number_of_data_directories_(0) {
42 } 39 }
43 40
41 FileOffset DisassemblerWin32X64::RVAToFileOffset(RVA rva) const {
42 const Section* section = RVAToSection(rva);
43 if (section != nullptr) {
44 uint32_t offset_in_section = rva - section->virtual_address;
45 // Need this extra check, since an |rva| may be valid for a section, but is
46 // non-existent in an image (e.g. uninit data).
47 if (offset_in_section >= section->size_of_raw_data)
48 return kNoFileOffset;
49
50 return static_cast<FileOffset>(
51 section->file_offset_of_raw_data + offset_in_section);
52 }
53
54 // Small RVA values point into the file header in the loaded image.
55 // RVA 0 is the module load address which Windows uses as the module handle.
56 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the
57 // DOS header.
58 if (rva == 0 || rva == 2)
59 return static_cast<FileOffset>(rva);
60
61 NOTREACHED();
62 return kNoFileOffset;
63 }
64
65 RVA DisassemblerWin32X64::FileOffsetToRVA(FileOffset file_offset) const {
66 for (int i = 0; i < number_of_sections_; ++i) {
67 const Section* section = &sections_[i];
68 if (file_offset >= section->file_offset_of_raw_data) {
69 uint32_t offset_in_section =
70 file_offset - section->file_offset_of_raw_data;
71 if (offset_in_section < section->size_of_raw_data)
72 return static_cast<RVA>(section->virtual_address + offset_in_section);
73 }
74 }
75
76 NOTREACHED();
77 return kNoRVA;
78 }
79
44 // ParseHeader attempts to match up the buffer with the Windows data 80 // ParseHeader attempts to match up the buffer with the Windows data
45 // structures that exist within a Windows 'Portable Executable' format file. 81 // structures that exist within a Windows 'Portable Executable' format file.
46 // Returns 'true' if the buffer matches, and 'false' if the data looks 82 // Returns 'true' if the buffer matches, and 'false' if the data looks
47 // suspicious. Rather than try to 'map' the buffer to the numerous windows 83 // suspicious. Rather than try to 'map' the buffer to the numerous windows
48 // structures, we extract the information we need into the courgette::PEInfo 84 // structures, we extract the information we need into the courgette::PEInfo
49 // structure. 85 // structure.
50 // 86 //
51 bool DisassemblerWin32X64::ParseHeader() { 87 bool DisassemblerWin32X64::ParseHeader() {
52 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/) 88 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/)
53 return Bad("Too small"); 89 return Bad("Too small");
54 90
55 // Have 'MZ' magic for a DOS header? 91 // Have 'MZ' magic for a DOS header?
56 if (start()[0] != 'M' || start()[1] != 'Z') 92 if (start()[0] != 'M' || start()[1] != 'Z')
57 return Bad("Not MZ"); 93 return Bad("Not MZ");
58 94
59 // offset from DOS header to PE header is stored in DOS header. 95 // offset from DOS header to PE header is stored in DOS header.
60 uint32_t offset = ReadU32(start(), kOffsetOfFileAddressOfNewExeHeader); 96 FileOffset file_offset = static_cast<FileOffset>(
97 ReadU32(start(), kOffsetOfFileAddressOfNewExeHeader));
61 98
62 if (offset >= length()) 99 if (file_offset >= length())
63 return Bad("Bad offset to PE header"); 100 return Bad("Bad offset to PE header");
64 101
65 const uint8_t* const pe_header = OffsetToPointer(offset); 102 const uint8_t* const pe_header = FileOffsetToPointer(file_offset);
66 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader; 103 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
67 if (pe_header <= start() || 104 if (pe_header <= start() ||
68 pe_header >= end() - kMinPEHeaderSize) 105 pe_header >= end() - kMinPEHeaderSize)
69 return Bad("Bad offset to PE header"); 106 return Bad("Bad file offset to PE header");
70 107
71 if (offset % 8 != 0) 108 if (file_offset % 8 != 0)
72 return Bad("Misaligned PE header"); 109 return Bad("Misaligned PE header");
73 110
74 // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H. 111 // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H.
75 // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx 112 // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx
76 // 113 //
77 // The first field of the IMAGE_NT_HEADERS is the signature. 114 // The first field of the IMAGE_NT_HEADERS is the signature.
78 if (!(pe_header[0] == 'P' && 115 if (!(pe_header[0] == 'P' &&
79 pe_header[1] == 'E' && 116 pe_header[1] == 'E' &&
80 pe_header[2] == 0 && 117 pe_header[2] == 0 &&
81 pe_header[3] == 0)) 118 pe_header[3] == 0))
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 if (!b) { 199 if (!b) {
163 return Bad("malformed data directory"); 200 return Bad("malformed data directory");
164 } 201 }
165 202
166 // Sections follow the optional header. 203 // Sections follow the optional header.
167 sections_ = 204 sections_ =
168 reinterpret_cast<const Section*>(optional_header + 205 reinterpret_cast<const Section*>(optional_header +
169 size_of_optional_header_); 206 size_of_optional_header_);
170 size_t detected_length = 0; 207 size_t detected_length = 0;
171 208
172 for (int i = 0; i < number_of_sections_; ++i) { 209 for (int i = 0; i < number_of_sections_; ++i) {
173 const Section* section = &sections_[i]; 210 const Section* section = &sections_[i];
174 211
175 // TODO(sra): consider using the 'characteristics' field of the section 212 // TODO(sra): consider using the 'characteristics' field of the section
176 // header to see if the section contains instructions. 213 // header to see if the section contains instructions.
177 if (memcmp(section->name, ".text", 6) == 0) 214 if (memcmp(section->name, ".text", 6) == 0)
178 has_text_section_ = true; 215 has_text_section_ = true;
179 216
180 uint32_t section_end = 217 uint32_t section_end =
181 section->file_offset_of_raw_data + section->size_of_raw_data; 218 section->file_offset_of_raw_data + section->size_of_raw_data;
182 if (section_end > detected_length) 219 if (section_end > detected_length)
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 block += size; 317 block += size;
281 } 318 }
282 319
283 std::sort(relocs->begin(), relocs->end()); 320 std::sort(relocs->begin(), relocs->end());
284 DCHECK(relocs->empty() || relocs->back() != kUnassignedRVA); 321 DCHECK(relocs->empty() || relocs->back() != kUnassignedRVA);
285 322
286 return true; 323 return true;
287 } 324 }
288 325
289 const Section* DisassemblerWin32X64::RVAToSection(RVA rva) const { 326 const Section* DisassemblerWin32X64::RVAToSection(RVA rva) const {
290 for (int i = 0; i < number_of_sections_; i++) { 327 for (int i = 0; i < number_of_sections_; ++i) {
291 const Section* section = &sections_[i]; 328 const Section* section = &sections_[i];
292 uint32_t offset = rva - section->virtual_address; 329 if (rva >= section->virtual_address) {
293 if (offset < section->virtual_size) { 330 uint32_t offset_in_section = rva - section->virtual_address;
294 return section; 331 if (offset_in_section < section->virtual_size)
332 return section;
295 } 333 }
296 } 334 }
297 return NULL; 335 return nullptr;
298 }
299
300 int DisassemblerWin32X64::RVAToFileOffset(RVA rva) const {
301 const Section* section = RVAToSection(rva);
302 if (section) {
303 uint32_t offset = rva - section->virtual_address;
304 if (offset < section->size_of_raw_data) {
305 return section->file_offset_of_raw_data + offset;
306 } else {
307 return kNoOffset; // In section but not in file (e.g. uninit data).
308 }
309 }
310
311 // Small RVA values point into the file header in the loaded image.
312 // RVA 0 is the module load address which Windows uses as the module handle.
313 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the
314 // DOS header.
315 if (rva == 0 || rva == 2)
316 return rva;
317
318 NOTREACHED();
319 return kNoOffset;
320 }
321
322 const uint8_t* DisassemblerWin32X64::RVAToPointer(RVA rva) const {
323 int file_offset = RVAToFileOffset(rva);
324 if (file_offset == kNoOffset)
325 return NULL;
326 else
327 return OffsetToPointer(file_offset);
328 } 336 }
329 337
330 std::string DisassemblerWin32X64::SectionName(const Section* section) { 338 std::string DisassemblerWin32X64::SectionName(const Section* section) {
331 if (section == NULL) 339 if (section == nullptr)
332 return "<none>"; 340 return "<none>";
333 char name[9]; 341 char name[9];
334 memcpy(name, section->name, 8); 342 memcpy(name, section->name, 8);
335 name[8] = '\0'; // Ensure termination. 343 name[8] = '\0'; // Ensure termination.
336 return name; 344 return name;
337 } 345 }
338 346
339 CheckBool DisassemblerWin32X64::ParseFile(AssemblyProgram* program) { 347 CheckBool DisassemblerWin32X64::ParseFile(AssemblyProgram* program) {
340 // Walk all the bytes in the file, whether or not in a section. 348 // Walk all the bytes in the file, whether or not in a section.
341 uint32_t file_offset = 0; 349 FileOffset file_offset = 0;
342 while (file_offset < length()) { 350 while (file_offset < length()) {
343 const Section* section = FindNextSection(file_offset); 351 const Section* section = FindNextSection(file_offset);
344 if (section == NULL) { 352 if (section == nullptr) {
345 // No more sections. There should not be extra stuff following last 353 // No more sections. There should not be extra stuff following last
346 // section. 354 // section.
347 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program); 355 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program);
348 break; 356 break;
349 } 357 }
350 if (file_offset < section->file_offset_of_raw_data) { 358 if (file_offset < section->file_offset_of_raw_data) {
351 uint32_t section_start_offset = section->file_offset_of_raw_data; 359 FileOffset section_start_offset = section->file_offset_of_raw_data;
352 if(!ParseNonSectionFileRegion(file_offset, section_start_offset, 360 if(!ParseNonSectionFileRegion(file_offset, section_start_offset,
353 program)) 361 program)) {
354 return false; 362 return false;
363 }
355 364
356 file_offset = section_start_offset; 365 file_offset = section_start_offset;
357 } 366 }
358 uint32_t end = file_offset + section->size_of_raw_data; 367 FileOffset end = file_offset + section->size_of_raw_data;
359 if (!ParseFileRegion(section, file_offset, end, program)) 368 if (!ParseFileRegion(section, file_offset, end, program))
360 return false; 369 return false;
361 file_offset = end; 370 file_offset = end;
362 } 371 }
363 372
364 #if COURGETTE_HISTOGRAM_TARGETS 373 #if COURGETTE_HISTOGRAM_TARGETS
365 HistogramTargets("abs32 relocs", abs32_target_rvas_); 374 HistogramTargets("abs32 relocs", abs32_target_rvas_);
366 HistogramTargets("rel32 relocs", rel32_target_rvas_); 375 HistogramTargets("rel32 relocs", rel32_target_rvas_);
367 #endif 376 #endif
368 377
(...skipping 13 matching lines...) Expand all
382 ++abs32_target_rvas_[target_address - image_base()]; 391 ++abs32_target_rvas_[target_address - image_base()];
383 } 392 }
384 #endif 393 #endif
385 return true; 394 return true;
386 } 395 }
387 396
388 void DisassemblerWin32X64::ParseRel32RelocsFromSections() { 397 void DisassemblerWin32X64::ParseRel32RelocsFromSections() {
389 uint32_t file_offset = 0; 398 uint32_t file_offset = 0;
390 while (file_offset < length()) { 399 while (file_offset < length()) {
391 const Section* section = FindNextSection(file_offset); 400 const Section* section = FindNextSection(file_offset);
392 if (section == NULL) 401 if (section == nullptr)
393 break; 402 break;
394 if (file_offset < section->file_offset_of_raw_data) 403 if (file_offset < section->file_offset_of_raw_data)
395 file_offset = section->file_offset_of_raw_data; 404 file_offset = section->file_offset_of_raw_data;
396 ParseRel32RelocsFromSection(section); 405 ParseRel32RelocsFromSection(section);
397 file_offset += section->size_of_raw_data; 406 file_offset += section->size_of_raw_data;
398 } 407 }
399 std::sort(rel32_locations_.begin(), rel32_locations_.end()); 408 std::sort(rel32_locations_.begin(), rel32_locations_.end());
400 DCHECK(rel32_locations_.empty() || 409 DCHECK(rel32_locations_.empty() ||
401 rel32_locations_.back() != kUnassignedRVA); 410 rel32_locations_.back() != kUnassignedRVA);
402 411
403 #if COURGETTE_HISTOGRAM_TARGETS 412 #if COURGETTE_HISTOGRAM_TARGETS
404 VLOG(1) << "abs32_locations_ " << abs32_locations_.size() 413 VLOG(1) << "abs32_locations_ " << abs32_locations_.size()
405 << "\nrel32_locations_ " << rel32_locations_.size() 414 << "\nrel32_locations_ " << rel32_locations_.size()
406 << "\nabs32_target_rvas_ " << abs32_target_rvas_.size() 415 << "\nabs32_target_rvas_ " << abs32_target_rvas_.size()
407 << "\nrel32_target_rvas_ " << rel32_target_rvas_.size(); 416 << "\nrel32_target_rvas_ " << rel32_target_rvas_.size();
408 417
409 int common = 0; 418 int common = 0;
410 std::map<RVA, int>::iterator abs32_iter = abs32_target_rvas_.begin(); 419 std::map<RVA, int>::iterator abs32_iter = abs32_target_rvas_.begin();
411 std::map<RVA, int>::iterator rel32_iter = rel32_target_rvas_.begin(); 420 std::map<RVA, int>::iterator rel32_iter = rel32_target_rvas_.begin();
412 while (abs32_iter != abs32_target_rvas_.end() && 421 while (abs32_iter != abs32_target_rvas_.end() &&
413 rel32_iter != rel32_target_rvas_.end()) { 422 rel32_iter != rel32_target_rvas_.end()) {
414 if (abs32_iter->first < rel32_iter->first) 423 if (abs32_iter->first < rel32_iter->first) {
415 ++abs32_iter; 424 ++abs32_iter;
416 else if (rel32_iter->first < abs32_iter->first) 425 } else if (rel32_iter->first < abs32_iter->first) {
417 ++rel32_iter; 426 ++rel32_iter;
418 else { 427 } else {
419 ++common; 428 ++common;
420 ++abs32_iter; 429 ++abs32_iter;
421 ++rel32_iter; 430 ++rel32_iter;
422 } 431 }
423 } 432 }
424 VLOG(1) << "common " << common; 433 VLOG(1) << "common " << common;
425 #endif 434 #endif
426 } 435 }
427 436
428 void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) { 437 void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) {
429 // TODO(sra): use characteristic. 438 // TODO(sra): use characteristic.
430 bool isCode = strcmp(section->name, ".text") == 0; 439 bool isCode = strcmp(section->name, ".text") == 0;
431 if (!isCode) 440 if (!isCode)
432 return; 441 return;
433 442
434 uint32_t start_file_offset = section->file_offset_of_raw_data; 443 FileOffset start_file_offset = section->file_offset_of_raw_data;
435 uint32_t end_file_offset = start_file_offset + section->size_of_raw_data; 444 FileOffset end_file_offset = start_file_offset + section->size_of_raw_data;
436 RVA relocs_start_rva = base_relocation_table().address_; 445 RVA relocs_start_rva = base_relocation_table().address_;
437 446
438 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); 447 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset);
439 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); 448 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset);
440 449
441 RVA start_rva = FileOffsetToRVA(start_file_offset); 450 RVA start_rva = FileOffsetToRVA(start_file_offset);
442 RVA end_rva = start_rva + section->virtual_size; 451 RVA end_rva = start_rva + section->virtual_size;
443 452
444 // Quick way to convert from Pointer to RVA within a single Section is to 453 // Quick way to convert from Pointer to RVA within a single Section is to
445 // subtract 'pointer_to_rva'. 454 // subtract |pointer_to_rva|.
446 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva; 455 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva;
447 456
448 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin(); 457 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
449 458
450 // Find the rel32 relocations. 459 // Find the rel32 relocations.
451 const uint8_t* p = start_pointer; 460 const uint8_t* p = start_pointer;
452 while (p < end_pointer) { 461 while (p < end_pointer) {
453 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva); 462 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
454 if (current_rva == relocs_start_rva) { 463 if (current_rva == relocs_start_rva) {
455 uint32_t relocs_size = base_relocation_table().size_; 464 uint32_t relocs_size = base_relocation_table().size_;
456 if (relocs_size) { 465 if (relocs_size) {
457 p += relocs_size; 466 p += relocs_size;
458 continue; 467 continue;
459 } 468 }
460 } 469 }
461 470
462 //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva)
463 // ++abs32_pos;
464
465 // Heuristic discovery of rel32 locations in instruction stream: are the 471 // Heuristic discovery of rel32 locations in instruction stream: are the
466 // next few bytes the start of an instruction containing a rel32 472 // next few bytes the start of an instruction containing a rel32
467 // addressing mode? 473 // addressing mode?
468 const uint8_t* rel32 = NULL; 474 const uint8_t* rel32 = nullptr;
469 bool is_rip_relative = false; 475 bool is_rip_relative = false;
470 476
471 if (p + 5 <= end_pointer) { 477 if (p + 5 <= end_pointer) {
472 if (*p == 0xE8 || *p == 0xE9) // jmp rel32 and call rel32 478 if (*p == 0xE8 || *p == 0xE9) // jmp rel32 and call rel32
473 rel32 = p + 1; 479 rel32 = p + 1;
474 } 480 }
475 if (p + 6 <= end_pointer) { 481 if (p + 6 <= end_pointer) {
476 if (*p == 0x0F && (*(p + 1) & 0xF0) == 0x80) { // Jcc long form 482 if (*p == 0x0F && (*(p + 1) & 0xF0) == 0x80) { // Jcc long form
477 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely 483 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely
478 rel32 = p + 2; 484 rel32 = p + 2;
(...skipping 30 matching lines...) Expand all
509 // Beginning of abs32 reloc is before end of rel32 reloc so they 515 // Beginning of abs32 reloc is before end of rel32 reloc so they
510 // overlap. Skip four bytes past the abs32 reloc. 516 // overlap. Skip four bytes past the abs32 reloc.
511 p += (*abs32_pos + 4) - current_rva; 517 p += (*abs32_pos + 4) - current_rva;
512 continue; 518 continue;
513 } 519 }
514 } 520 }
515 521
516 RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32); 522 RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32);
517 // To be valid, rel32 target must be within image, and within this 523 // To be valid, rel32 target must be within image, and within this
518 // section. 524 // section.
519 if (IsValidRVA(target_rva) && 525 if (target_rva < size_of_image_ && // Subsumes rva != kUnassignedRVA.
520 (is_rip_relative || 526 (is_rip_relative ||
521 (start_rva <= target_rva && target_rva < end_rva))) { 527 (start_rva <= target_rva && target_rva < end_rva))) {
522 rel32_locations_.push_back(rel32_rva); 528 rel32_locations_.push_back(rel32_rva);
523 #if COURGETTE_HISTOGRAM_TARGETS 529 #if COURGETTE_HISTOGRAM_TARGETS
524 ++rel32_target_rvas_[target_rva]; 530 ++rel32_target_rvas_[target_rva];
525 #endif 531 #endif
526 p = rel32 + 4; 532 p = rel32 + 4;
527 continue; 533 continue;
528 } 534 }
529 } 535 }
530 p += 1; 536 p += 1;
531 } 537 }
532 } 538 }
533 539
534 CheckBool DisassemblerWin32X64::ParseNonSectionFileRegion( 540 CheckBool DisassemblerWin32X64::ParseNonSectionFileRegion(
535 uint32_t start_file_offset, 541 FileOffset start_file_offset,
536 uint32_t end_file_offset, 542 FileOffset end_file_offset,
537 AssemblyProgram* program) { 543 AssemblyProgram* program) {
538 if (incomplete_disassembly_) 544 if (incomplete_disassembly_)
539 return true; 545 return true;
540 546
541 if (end_file_offset > start_file_offset) { 547 if (end_file_offset > start_file_offset) {
542 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset), 548 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset),
543 end_file_offset - start_file_offset)) { 549 end_file_offset - start_file_offset)) {
544 return false; 550 return false;
545 } 551 }
546 } 552 }
547 553
548 return true; 554 return true;
549 } 555 }
550 556
551 CheckBool DisassemblerWin32X64::ParseFileRegion(const Section* section, 557 CheckBool DisassemblerWin32X64::ParseFileRegion(const Section* section,
552 uint32_t start_file_offset, 558 FileOffset start_file_offset,
553 uint32_t end_file_offset, 559 FileOffset end_file_offset,
554 AssemblyProgram* program) { 560 AssemblyProgram* program) {
555 RVA relocs_start_rva = base_relocation_table().address_; 561 RVA relocs_start_rva = base_relocation_table().address_;
556 562
557 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); 563 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset);
558 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); 564 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset);
559 565
560 RVA start_rva = FileOffsetToRVA(start_file_offset); 566 RVA start_rva = FileOffsetToRVA(start_file_offset);
561 RVA end_rva = start_rva + section->virtual_size; 567 RVA end_rva = start_rva + section->virtual_size;
562 568
563 // Quick way to convert from Pointer to RVA within a single Section is to 569 // Quick way to convert from Pointer to RVA within a single Section is to
564 // subtract 'pointer_to_rva'. 570 // subtract 'pointer_to_rva'.
565 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva; 571 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva;
566 572
567 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin(); 573 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin();
568 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin(); 574 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 p != h.rend(); 663 p != h.rend();
658 ++p) { 664 ++p) {
659 ++index; 665 ++index;
660 if (index <= kFirstN || p->first <= 3) { 666 if (index <= kFirstN || p->first <= 3) {
661 if (someSkipped) { 667 if (someSkipped) {
662 std::cout << "..." << std::endl; 668 std::cout << "..." << std::endl;
663 } 669 }
664 size_t count = p->second.size(); 670 size_t count = p->second.size();
665 std::cout << std::dec << p->first << ": " << count; 671 std::cout << std::dec << p->first << ": " << count;
666 if (count <= 2) { 672 if (count <= 2) {
667 for (size_t i = 0; i < count; ++i) 673 for (size_t i = 0; i < count; ++i)
668 std::cout << " " << DescribeRVA(p->second[i]); 674 std::cout << " " << DescribeRVA(p->second[i]);
669 } 675 }
670 std::cout << std::endl; 676 std::cout << std::endl;
671 someSkipped = false; 677 someSkipped = false;
672 } else { 678 } else {
673 someSkipped = true; 679 someSkipped = true;
674 } 680 }
675 } 681 }
676 } 682 }
677 #endif // COURGETTE_HISTOGRAM_TARGETS 683 #endif // COURGETTE_HISTOGRAM_TARGETS
678 684
679
680 // DescribeRVA is for debugging only. I would put it under #ifdef DEBUG except 685 // DescribeRVA is for debugging only. I would put it under #ifdef DEBUG except
681 // that during development I'm finding I need to call it when compiled in 686 // that during development I'm finding I need to call it when compiled in
682 // Release mode. Hence: 687 // Release mode. Hence:
683 // TODO(sra): make this compile only for debug mode. 688 // TODO(sra): make this compile only for debug mode.
684 std::string DisassemblerWin32X64::DescribeRVA(RVA rva) const { 689 std::string DisassemblerWin32X64::DescribeRVA(RVA rva) const {
685 const Section* section = RVAToSection(rva); 690 const Section* section = RVAToSection(rva);
686 std::ostringstream s; 691 std::ostringstream s;
687 s << std::hex << rva; 692 s << std::hex << rva;
688 if (section) { 693 if (section) {
689 s << " ("; 694 s << " (";
690 s << SectionName(section) << "+" 695 s << SectionName(section) << "+"
691 << std::hex << (rva - section->virtual_address) 696 << std::hex << (rva - section->virtual_address)
692 << ")"; 697 << ")";
693 } 698 }
694 return s.str(); 699 return s.str();
695 } 700 }
696 701
697 const Section* DisassemblerWin32X64::FindNextSection( 702 const Section* DisassemblerWin32X64::FindNextSection(
698 uint32_t fileOffset) const { 703 FileOffset file_offset) const {
699 const Section* best = 0; 704 const Section* best = 0;
700 for (int i = 0; i < number_of_sections_; i++) { 705 for (int i = 0; i < number_of_sections_; ++i) {
701 const Section* section = &sections_[i]; 706 const Section* section = &sections_[i];
702 if (section->size_of_raw_data > 0) { // i.e. has data in file. 707 if (section->size_of_raw_data > 0) { // i.e. has data in file.
703 if (fileOffset <= section->file_offset_of_raw_data) { 708 if (file_offset <= section->file_offset_of_raw_data) {
704 if (best == 0 || 709 if (best == 0 ||
705 section->file_offset_of_raw_data < best->file_offset_of_raw_data) { 710 section->file_offset_of_raw_data < best->file_offset_of_raw_data) {
706 best = section; 711 best = section;
707 } 712 }
708 } 713 }
709 } 714 }
710 } 715 }
711 return best; 716 return best;
712 } 717 }
713 718
714 RVA DisassemblerWin32X64::FileOffsetToRVA(uint32_t file_offset) const {
715 for (int i = 0; i < number_of_sections_; i++) {
716 const Section* section = &sections_[i];
717 uint32_t offset = file_offset - section->file_offset_of_raw_data;
718 if (offset < section->size_of_raw_data) {
719 return section->virtual_address + offset;
720 }
721 }
722 return 0;
723 }
724
725 bool DisassemblerWin32X64::ReadDataDirectory( 719 bool DisassemblerWin32X64::ReadDataDirectory(
726 int index, 720 int index,
727 ImageDataDirectory* directory) { 721 ImageDataDirectory* directory) {
728 722
729 if (index < number_of_data_directories_) { 723 if (index < number_of_data_directories_) {
730 size_t offset = index * 8 + offset_of_data_directories_; 724 FileOffset file_offset = index * 8 + offset_of_data_directories_;
731 if (offset >= size_of_optional_header_) 725 if (file_offset >= size_of_optional_header_)
732 return Bad("number of data directories inconsistent"); 726 return Bad("number of data directories inconsistent");
733 const uint8_t* data_directory = optional_header_ + offset; 727 const uint8_t* data_directory = optional_header_ + file_offset;
734 if (data_directory < start() || 728 if (data_directory < start() ||
735 data_directory + 8 >= end()) 729 data_directory + 8 >= end())
736 return Bad("data directory outside image"); 730 return Bad("data directory outside image");
737 RVA rva = ReadU32(data_directory, 0); 731 RVA rva = ReadU32(data_directory, 0);
738 size_t size = ReadU32(data_directory, 4); 732 size_t size = ReadU32(data_directory, 4);
739 if (size > size_of_image_) 733 if (size > size_of_image_)
740 return Bad("data directory size too big"); 734 return Bad("data directory size too big");
741 735
742 // TODO(sra): validate RVA. 736 // TODO(sra): validate RVA.
743 directory->address_ = rva; 737 directory->address_ = rva;
744 directory->size_ = static_cast<uint32_t>(size); 738 directory->size_ = static_cast<uint32_t>(size);
745 return true; 739 return true;
746 } else { 740 } else {
747 directory->address_ = 0; 741 directory->address_ = 0;
748 directory->size_ = 0; 742 directory->size_ = 0;
749 return true; 743 return true;
750 } 744 }
751 } 745 }
752 746
753 } // namespace courgette 747 } // namespace courgette
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698