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

Side by Side Diff: courgette/disassembler_win32_x86.cc

Issue 1676683002: [Courgette] Clean up Disassembler; fix ELF Memory leaks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wrap #include <iostream> under #if COURGETTE_HISTOGRAM_TARGETS. Created 4 years, 9 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
« no previous file with comments | « courgette/disassembler_win32_x86.h ('k') | courgette/disassembler_win32_x86_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <string>
12 #include <vector>
13 11
14 #include "base/logging.h" 12 #include "base/logging.h"
15
16 #include "courgette/assembly_program.h" 13 #include "courgette/assembly_program.h"
17 #include "courgette/courgette.h" 14 #include "courgette/courgette.h"
18 #include "courgette/encoded_program.h"
19 #include "courgette/rel32_finder_win32_x86.h" 15 #include "courgette/rel32_finder_win32_x86.h"
20 16
17 #if COURGETTE_HISTOGRAM_TARGETS
18 #include <iostream>
19 #endif
20
21 namespace courgette { 21 namespace courgette {
22 22
23 DisassemblerWin32X86::DisassemblerWin32X86(const void* start, size_t length) 23 DisassemblerWin32X86::DisassemblerWin32X86(const void* start, size_t length)
24 : Disassembler(start, length), 24 : Disassembler(start, length),
25 incomplete_disassembly_(false), 25 incomplete_disassembly_(false),
26 is_PE32_plus_(false), 26 is_PE32_plus_(false),
27 optional_header_(NULL), 27 optional_header_(nullptr),
28 size_of_optional_header_(0), 28 size_of_optional_header_(0),
29 offset_of_data_directories_(0), 29 offset_of_data_directories_(0),
30 machine_type_(0), 30 machine_type_(0),
31 number_of_sections_(0), 31 number_of_sections_(0),
32 sections_(NULL), 32 sections_(nullptr),
33 has_text_section_(false), 33 has_text_section_(false),
34 size_of_code_(0), 34 size_of_code_(0),
35 size_of_initialized_data_(0), 35 size_of_initialized_data_(0),
36 size_of_uninitialized_data_(0), 36 size_of_uninitialized_data_(0),
37 base_of_code_(0), 37 base_of_code_(0),
38 base_of_data_(0), 38 base_of_data_(0),
39 image_base_(0), 39 image_base_(0),
40 size_of_image_(0), 40 size_of_image_(0),
41 number_of_data_directories_(0) { 41 number_of_data_directories_(0) {
42 }
43
44 FileOffset DisassemblerWin32X86::RVAToFileOffset(RVA rva) const {
45 const Section* section = RVAToSection(rva);
46 if (section != nullptr) {
47 FileOffset offset_in_section = rva - section->virtual_address;
48 // Need this extra check, since an |rva| may be valid for a section, but is
49 // non-existent in an image (e.g. uninit data).
50 if (offset_in_section >= section->size_of_raw_data)
51 return kNoFileOffset;
52
53 return static_cast<FileOffset>(section->file_offset_of_raw_data +
54 offset_in_section);
55 }
56
57 // Small RVA values point into the file header in the loaded image.
58 // RVA 0 is the module load address which Windows uses as the module handle.
59 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the
60 // DOS header.
61 if (rva == 0 || rva == 2)
62 return static_cast<FileOffset>(rva);
63
64 NOTREACHED();
65 return kNoFileOffset;
66 }
67
68 RVA DisassemblerWin32X86::FileOffsetToRVA(FileOffset file_offset) const {
69 for (int i = 0; i < number_of_sections_; ++i) {
70 const Section* section = &sections_[i];
71 if (file_offset >= section->file_offset_of_raw_data) {
72 FileOffset offset_in_section =
73 file_offset - section->file_offset_of_raw_data;
74 if (offset_in_section < section->size_of_raw_data)
75 return static_cast<RVA>(section->virtual_address + offset_in_section);
76 }
77 }
78
79 NOTREACHED();
80 return kNoRVA;
42 } 81 }
43 82
44 // ParseHeader attempts to match up the buffer with the Windows data 83 // ParseHeader attempts to match up the buffer with the Windows data
45 // structures that exist within a Windows 'Portable Executable' format file. 84 // structures that exist within a Windows 'Portable Executable' format file.
46 // Returns 'true' if the buffer matches, and 'false' if the data looks 85 // 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 86 // suspicious. Rather than try to 'map' the buffer to the numerous windows
48 // structures, we extract the information we need into the courgette::PEInfo 87 // structures, we extract the information we need into the courgette::PEInfo
49 // structure. 88 // structure.
50 // 89 //
51 bool DisassemblerWin32X86::ParseHeader() { 90 bool DisassemblerWin32X86::ParseHeader() {
52 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/) 91 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/)
53 return Bad("Too small"); 92 return Bad("Too small");
54 93
55 // Have 'MZ' magic for a DOS header? 94 // Have 'MZ' magic for a DOS header?
56 if (start()[0] != 'M' || start()[1] != 'Z') 95 if (start()[0] != 'M' || start()[1] != 'Z')
57 return Bad("Not MZ"); 96 return Bad("Not MZ");
58 97
59 // offset from DOS header to PE header is stored in DOS header. 98 // offset from DOS header to PE header is stored in DOS header.
60 uint32_t offset = ReadU32(start(), kOffsetOfFileAddressOfNewExeHeader); 99 FileOffset file_offset = static_cast<FileOffset>(
100 ReadU32(start(), kOffsetOfFileAddressOfNewExeHeader));
61 101
62 if (offset >= length()) 102 if (file_offset >= length())
63 return Bad("Bad offset to PE header"); 103 return Bad("Bad offset to PE header");
64 104
65 const uint8_t* const pe_header = OffsetToPointer(offset); 105 const uint8_t* const pe_header = FileOffsetToPointer(file_offset);
66 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader; 106 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
67 if (pe_header <= start() || 107 if (pe_header <= start() ||
68 pe_header >= end() - kMinPEHeaderSize) 108 pe_header >= end() - kMinPEHeaderSize)
69 return Bad("Bad offset to PE header"); 109 return Bad("Bad file offset to PE header");
70 110
71 if (offset % 8 != 0) 111 if (file_offset % 8 != 0)
72 return Bad("Misaligned PE header"); 112 return Bad("Misaligned PE header");
73 113
74 // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H. 114 // 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 115 // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx
76 // 116 //
77 // The first field of the IMAGE_NT_HEADERS is the signature. 117 // The first field of the IMAGE_NT_HEADERS is the signature.
78 if (!(pe_header[0] == 'P' && 118 if (!(pe_header[0] == 'P' &&
79 pe_header[1] == 'E' && 119 pe_header[1] == 'E' &&
80 pe_header[2] == 0 && 120 pe_header[2] == 0 &&
81 pe_header[3] == 0)) 121 pe_header[3] == 0))
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 if (!b) { 202 if (!b) {
163 return Bad("malformed data directory"); 203 return Bad("malformed data directory");
164 } 204 }
165 205
166 // Sections follow the optional header. 206 // Sections follow the optional header.
167 sections_ = 207 sections_ =
168 reinterpret_cast<const Section*>(optional_header + 208 reinterpret_cast<const Section*>(optional_header +
169 size_of_optional_header_); 209 size_of_optional_header_);
170 size_t detected_length = 0; 210 size_t detected_length = 0;
171 211
172 for (int i = 0; i < number_of_sections_; ++i) { 212 for (int i = 0; i < number_of_sections_; ++i) {
173 const Section* section = &sections_[i]; 213 const Section* section = &sections_[i];
174 214
175 // TODO(sra): consider using the 'characteristics' field of the section 215 // TODO(sra): consider using the 'characteristics' field of the section
176 // header to see if the section contains instructions. 216 // header to see if the section contains instructions.
177 if (memcmp(section->name, ".text", 6) == 0) 217 if (memcmp(section->name, ".text", 6) == 0)
178 has_text_section_ = true; 218 has_text_section_ = true;
179 219
180 uint32_t section_end = 220 uint32_t section_end =
181 section->file_offset_of_raw_data + section->size_of_raw_data; 221 section->file_offset_of_raw_data + section->size_of_raw_data;
182 if (section_end > detected_length) 222 if (section_end > detected_length)
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 block += size; 326 block += size;
287 } 327 }
288 328
289 std::sort(relocs->begin(), relocs->end()); 329 std::sort(relocs->begin(), relocs->end());
290 DCHECK(relocs->empty() || relocs->back() != kUnassignedRVA); 330 DCHECK(relocs->empty() || relocs->back() != kUnassignedRVA);
291 331
292 return true; 332 return true;
293 } 333 }
294 334
295 const Section* DisassemblerWin32X86::RVAToSection(RVA rva) const { 335 const Section* DisassemblerWin32X86::RVAToSection(RVA rva) const {
296 for (int i = 0; i < number_of_sections_; i++) { 336 for (int i = 0; i < number_of_sections_; ++i) {
297 const Section* section = &sections_[i]; 337 const Section* section = &sections_[i];
298 uint32_t offset = rva - section->virtual_address; 338 if (rva >= section->virtual_address) {
299 if (offset < section->virtual_size) { 339 FileOffset offset_in_section = rva - section->virtual_address;
300 return section; 340 if (offset_in_section < section->virtual_size)
341 return section;
301 } 342 }
302 } 343 }
303 return NULL; 344 return nullptr;
304 }
305
306 int DisassemblerWin32X86::RVAToFileOffset(RVA rva) const {
307 const Section* section = RVAToSection(rva);
308 if (section) {
309 uint32_t offset = rva - section->virtual_address;
310 if (offset < section->size_of_raw_data) {
311 return section->file_offset_of_raw_data + offset;
312 } else {
313 return kNoOffset; // In section but not in file (e.g. uninit data).
314 }
315 }
316
317 // Small RVA values point into the file header in the loaded image.
318 // RVA 0 is the module load address which Windows uses as the module handle.
319 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the
320 // DOS header.
321 if (rva == 0 || rva == 2)
322 return rva;
323
324 NOTREACHED();
325 return kNoOffset;
326 }
327
328 const uint8_t* DisassemblerWin32X86::RVAToPointer(RVA rva) const {
329 int file_offset = RVAToFileOffset(rva);
330 if (file_offset == kNoOffset)
331 return NULL;
332 else
333 return OffsetToPointer(file_offset);
334 } 345 }
335 346
336 std::string DisassemblerWin32X86::SectionName(const Section* section) { 347 std::string DisassemblerWin32X86::SectionName(const Section* section) {
337 if (section == NULL) 348 if (section == nullptr)
338 return "<none>"; 349 return "<none>";
339 char name[9]; 350 char name[9];
340 memcpy(name, section->name, 8); 351 memcpy(name, section->name, 8);
341 name[8] = '\0'; // Ensure termination. 352 name[8] = '\0'; // Ensure termination.
342 return name; 353 return name;
343 } 354 }
344 355
345 CheckBool DisassemblerWin32X86::ParseFile(AssemblyProgram* program) { 356 CheckBool DisassemblerWin32X86::ParseFile(AssemblyProgram* program) {
346 // Walk all the bytes in the file, whether or not in a section. 357 // Walk all the bytes in the file, whether or not in a section.
347 uint32_t file_offset = 0; 358 FileOffset file_offset = 0;
348 while (file_offset < length()) { 359 while (file_offset < length()) {
349 const Section* section = FindNextSection(file_offset); 360 const Section* section = FindNextSection(file_offset);
350 if (section == NULL) { 361 if (section == nullptr) {
351 // No more sections. There should not be extra stuff following last 362 // No more sections. There should not be extra stuff following last
352 // section. 363 // section.
353 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program); 364 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program);
354 break; 365 break;
355 } 366 }
356 if (file_offset < section->file_offset_of_raw_data) { 367 if (file_offset < section->file_offset_of_raw_data) {
357 uint32_t section_start_offset = section->file_offset_of_raw_data; 368 FileOffset section_start_offset = section->file_offset_of_raw_data;
358 if(!ParseNonSectionFileRegion(file_offset, section_start_offset, 369 if (!ParseNonSectionFileRegion(file_offset, section_start_offset,
359 program)) 370 program)) {
360 return false; 371 return false;
372 }
361 373
362 file_offset = section_start_offset; 374 file_offset = section_start_offset;
363 } 375 }
364 uint32_t end = file_offset + section->size_of_raw_data; 376 FileOffset end = file_offset + section->size_of_raw_data;
365 if (!ParseFileRegion(section, file_offset, end, program)) 377 if (!ParseFileRegion(section, file_offset, end, program))
366 return false; 378 return false;
367 file_offset = end; 379 file_offset = end;
368 } 380 }
369 381
370 #if COURGETTE_HISTOGRAM_TARGETS 382 #if COURGETTE_HISTOGRAM_TARGETS
371 HistogramTargets("abs32 relocs", abs32_target_rvas_); 383 HistogramTargets("abs32 relocs", abs32_target_rvas_);
372 HistogramTargets("rel32 relocs", rel32_target_rvas_); 384 HistogramTargets("rel32 relocs", rel32_target_rvas_);
373 #endif 385 #endif
374 386
375 return true; 387 return true;
376 } 388 }
377 389
378 bool DisassemblerWin32X86::ParseAbs32Relocs() { 390 bool DisassemblerWin32X86::ParseAbs32Relocs() {
379 abs32_locations_.clear(); 391 abs32_locations_.clear();
380 if (!ParseRelocs(&abs32_locations_)) 392 if (!ParseRelocs(&abs32_locations_))
381 return false; 393 return false;
382 394
383 #if COURGETTE_HISTOGRAM_TARGETS 395 #if COURGETTE_HISTOGRAM_TARGETS
384 for (size_t i = 0; i < abs32_locations_.size(); ++i) { 396 for (size_t i = 0; i < abs32_locations_.size(); ++i) {
385 RVA rva = abs32_locations_[i]; 397 RVA rva = abs32_locations_[i];
386 // The 4 bytes at the relocation are a reference to some address. 398 // The 4 bytes at the relocation are a reference to some address.
387 uint32_t target_address = Read32LittleEndian(RVAToPointer(rva)); 399 uint32_t target_address = Read32LittleEndian(RVAToPointer(rva));
388 ++abs32_target_rvas_[target_address - image_base()]; 400 ++abs32_target_rvas_[target_address - image_base()];
389 } 401 }
390 #endif 402 #endif
391 return true; 403 return true;
392 } 404 }
393 405
394 void DisassemblerWin32X86::ParseRel32RelocsFromSections() { 406 void DisassemblerWin32X86::ParseRel32RelocsFromSections() {
395 uint32_t file_offset = 0; 407 FileOffset file_offset = 0;
396 while (file_offset < length()) { 408 while (file_offset < length()) {
397 const Section* section = FindNextSection(file_offset); 409 const Section* section = FindNextSection(file_offset);
398 if (section == NULL) 410 if (section == nullptr)
399 break; 411 break;
400 if (file_offset < section->file_offset_of_raw_data) 412 if (file_offset < section->file_offset_of_raw_data)
401 file_offset = section->file_offset_of_raw_data; 413 file_offset = section->file_offset_of_raw_data;
402 ParseRel32RelocsFromSection(section); 414 ParseRel32RelocsFromSection(section);
403 file_offset += section->size_of_raw_data; 415 file_offset += section->size_of_raw_data;
404 } 416 }
405 std::sort(rel32_locations_.begin(), rel32_locations_.end()); 417 std::sort(rel32_locations_.begin(), rel32_locations_.end());
406 DCHECK(rel32_locations_.empty() || 418 DCHECK(rel32_locations_.empty() ||
407 rel32_locations_.back() != kUnassignedRVA); 419 rel32_locations_.back() != kUnassignedRVA);
408 420
409 #if COURGETTE_HISTOGRAM_TARGETS 421 #if COURGETTE_HISTOGRAM_TARGETS
410 VLOG(1) << "abs32_locations_ " << abs32_locations_.size() 422 VLOG(1) << "abs32_locations_ " << abs32_locations_.size()
411 << "\nrel32_locations_ " << rel32_locations_.size() 423 << "\nrel32_locations_ " << rel32_locations_.size()
412 << "\nabs32_target_rvas_ " << abs32_target_rvas_.size() 424 << "\nabs32_target_rvas_ " << abs32_target_rvas_.size()
413 << "\nrel32_target_rvas_ " << rel32_target_rvas_.size(); 425 << "\nrel32_target_rvas_ " << rel32_target_rvas_.size();
414 426
415 int common = 0; 427 int common = 0;
416 std::map<RVA, int>::iterator abs32_iter = abs32_target_rvas_.begin(); 428 std::map<RVA, int>::iterator abs32_iter = abs32_target_rvas_.begin();
417 std::map<RVA, int>::iterator rel32_iter = rel32_target_rvas_.begin(); 429 std::map<RVA, int>::iterator rel32_iter = rel32_target_rvas_.begin();
418 while (abs32_iter != abs32_target_rvas_.end() && 430 while (abs32_iter != abs32_target_rvas_.end() &&
419 rel32_iter != rel32_target_rvas_.end()) { 431 rel32_iter != rel32_target_rvas_.end()) {
420 if (abs32_iter->first < rel32_iter->first) 432 if (abs32_iter->first < rel32_iter->first) {
421 ++abs32_iter; 433 ++abs32_iter;
422 else if (rel32_iter->first < abs32_iter->first) 434 } else if (rel32_iter->first < abs32_iter->first) {
423 ++rel32_iter; 435 ++rel32_iter;
424 else { 436 } else {
425 ++common; 437 ++common;
426 ++abs32_iter; 438 ++abs32_iter;
427 ++rel32_iter; 439 ++rel32_iter;
428 } 440 }
429 } 441 }
430 VLOG(1) << "common " << common; 442 VLOG(1) << "common " << common;
431 #endif 443 #endif
432 } 444 }
433 445
434 void DisassemblerWin32X86::ParseRel32RelocsFromSection(const Section* section) { 446 void DisassemblerWin32X86::ParseRel32RelocsFromSection(const Section* section) {
435 // TODO(sra): use characteristic. 447 // TODO(sra): use characteristic.
436 bool isCode = strcmp(section->name, ".text") == 0; 448 bool isCode = strcmp(section->name, ".text") == 0;
437 if (!isCode) 449 if (!isCode)
438 return; 450 return;
439 451
440 uint32_t start_file_offset = section->file_offset_of_raw_data; 452 FileOffset start_file_offset = section->file_offset_of_raw_data;
441 uint32_t end_file_offset = start_file_offset + section->size_of_raw_data; 453 FileOffset end_file_offset = start_file_offset + section->size_of_raw_data;
442 454
443 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); 455 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset);
444 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); 456 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset);
445 457
446 RVA start_rva = FileOffsetToRVA(start_file_offset); 458 RVA start_rva = FileOffsetToRVA(start_file_offset);
447 RVA end_rva = start_rva + section->virtual_size; 459 RVA end_rva = start_rva + section->virtual_size;
448 460
449 Rel32FinderWin32X86_Basic finder( 461 Rel32FinderWin32X86_Basic finder(
450 base_relocation_table().address_, 462 base_relocation_table().address_,
451 base_relocation_table().address_ + base_relocation_table().size_, 463 base_relocation_table().address_ + base_relocation_table().size_);
452 size_of_image_);
453 finder.Find(start_pointer, end_pointer, start_rva, end_rva, abs32_locations_); 464 finder.Find(start_pointer, end_pointer, start_rva, end_rva, abs32_locations_);
454 finder.SwapRel32Locations(&rel32_locations_); 465 finder.SwapRel32Locations(&rel32_locations_);
455 466
456 #if COURGETTE_HISTOGRAM_TARGETS 467 #if COURGETTE_HISTOGRAM_TARGETS
457 DCHECK(rel32_target_rvas_.empty()); 468 DCHECK(rel32_target_rvas_.empty());
458 finder.SwapRel32TargetRVAs(&rel32_target_rvas_); 469 finder.SwapRel32TargetRVAs(&rel32_target_rvas_);
459 #endif 470 #endif
460 } 471 }
461 472
462 CheckBool DisassemblerWin32X86::ParseNonSectionFileRegion( 473 CheckBool DisassemblerWin32X86::ParseNonSectionFileRegion(
463 uint32_t start_file_offset, 474 FileOffset start_file_offset,
464 uint32_t end_file_offset, 475 FileOffset end_file_offset,
465 AssemblyProgram* program) { 476 AssemblyProgram* program) {
466 if (incomplete_disassembly_) 477 if (incomplete_disassembly_)
467 return true; 478 return true;
468 479
469 if (end_file_offset > start_file_offset) { 480 if (end_file_offset > start_file_offset) {
470 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset), 481 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset),
471 end_file_offset - start_file_offset)) { 482 end_file_offset - start_file_offset)) {
472 return false; 483 return false;
473 } 484 }
474 } 485 }
475 486
476 return true; 487 return true;
477 } 488 }
478 489
479 CheckBool DisassemblerWin32X86::ParseFileRegion(const Section* section, 490 CheckBool DisassemblerWin32X86::ParseFileRegion(const Section* section,
480 uint32_t start_file_offset, 491 FileOffset start_file_offset,
481 uint32_t end_file_offset, 492 FileOffset end_file_offset,
482 AssemblyProgram* program) { 493 AssemblyProgram* program) {
483 RVA relocs_start_rva = base_relocation_table().address_; 494 RVA relocs_start_rva = base_relocation_table().address_;
484 495
485 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); 496 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset);
486 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); 497 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset);
487 498
488 RVA start_rva = FileOffsetToRVA(start_file_offset); 499 RVA start_rva = FileOffsetToRVA(start_file_offset);
489 RVA end_rva = start_rva + section->virtual_size; 500 RVA end_rva = start_rva + section->virtual_size;
490 501
491 // Quick way to convert from Pointer to RVA within a single Section is to 502 // Quick way to convert from Pointer to RVA within a single Section is to
492 // subtract 'pointer_to_rva'. 503 // subtract 'pointer_to_rva'.
493 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva; 504 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva;
494 505
495 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin(); 506 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin();
496 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin(); 507 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 p != h.rend(); 596 p != h.rend();
586 ++p) { 597 ++p) {
587 ++index; 598 ++index;
588 if (index <= kFirstN || p->first <= 3) { 599 if (index <= kFirstN || p->first <= 3) {
589 if (someSkipped) { 600 if (someSkipped) {
590 std::cout << "..." << std::endl; 601 std::cout << "..." << std::endl;
591 } 602 }
592 size_t count = p->second.size(); 603 size_t count = p->second.size();
593 std::cout << std::dec << p->first << ": " << count; 604 std::cout << std::dec << p->first << ": " << count;
594 if (count <= 2) { 605 if (count <= 2) {
595 for (size_t i = 0; i < count; ++i) 606 for (size_t i = 0; i < count; ++i)
596 std::cout << " " << DescribeRVA(p->second[i]); 607 std::cout << " " << DescribeRVA(p->second[i]);
597 } 608 }
598 std::cout << std::endl; 609 std::cout << std::endl;
599 someSkipped = false; 610 someSkipped = false;
600 } else { 611 } else {
601 someSkipped = true; 612 someSkipped = true;
602 } 613 }
603 } 614 }
604 } 615 }
605 #endif // COURGETTE_HISTOGRAM_TARGETS 616 #endif // COURGETTE_HISTOGRAM_TARGETS
606 617
607
608 // DescribeRVA is for debugging only. I would put it under #ifdef DEBUG except 618 // DescribeRVA is for debugging only. I would put it under #ifdef DEBUG except
609 // that during development I'm finding I need to call it when compiled in 619 // that during development I'm finding I need to call it when compiled in
610 // Release mode. Hence: 620 // Release mode. Hence:
611 // TODO(sra): make this compile only for debug mode. 621 // TODO(sra): make this compile only for debug mode.
612 std::string DisassemblerWin32X86::DescribeRVA(RVA rva) const { 622 std::string DisassemblerWin32X86::DescribeRVA(RVA rva) const {
613 const Section* section = RVAToSection(rva); 623 const Section* section = RVAToSection(rva);
614 std::ostringstream s; 624 std::ostringstream s;
615 s << std::hex << rva; 625 s << std::hex << rva;
616 if (section) { 626 if (section) {
617 s << " ("; 627 s << " (";
618 s << SectionName(section) << "+" 628 s << SectionName(section) << "+"
619 << std::hex << (rva - section->virtual_address) 629 << std::hex << (rva - section->virtual_address)
620 << ")"; 630 << ")";
621 } 631 }
622 return s.str(); 632 return s.str();
623 } 633 }
624 634
625 const Section* DisassemblerWin32X86::FindNextSection( 635 const Section* DisassemblerWin32X86::FindNextSection(
626 uint32_t fileOffset) const { 636 FileOffset file_offset) const {
627 const Section* best = 0; 637 const Section* best = 0;
628 for (int i = 0; i < number_of_sections_; i++) { 638 for (int i = 0; i < number_of_sections_; ++i) {
629 const Section* section = &sections_[i]; 639 const Section* section = &sections_[i];
630 if (section->size_of_raw_data > 0) { // i.e. has data in file. 640 if (section->size_of_raw_data > 0) { // i.e. has data in file.
631 if (fileOffset <= section->file_offset_of_raw_data) { 641 if (file_offset <= section->file_offset_of_raw_data) {
632 if (best == 0 || 642 if (best == 0 ||
633 section->file_offset_of_raw_data < best->file_offset_of_raw_data) { 643 section->file_offset_of_raw_data < best->file_offset_of_raw_data) {
634 best = section; 644 best = section;
635 } 645 }
636 } 646 }
637 } 647 }
638 } 648 }
639 return best; 649 return best;
640 } 650 }
641 651
642 RVA DisassemblerWin32X86::FileOffsetToRVA(uint32_t file_offset) const {
643 for (int i = 0; i < number_of_sections_; i++) {
644 const Section* section = &sections_[i];
645 uint32_t offset = file_offset - section->file_offset_of_raw_data;
646 if (offset < section->size_of_raw_data) {
647 return section->virtual_address + offset;
648 }
649 }
650 return 0;
651 }
652
653 bool DisassemblerWin32X86::ReadDataDirectory( 652 bool DisassemblerWin32X86::ReadDataDirectory(
654 int index, 653 int index,
655 ImageDataDirectory* directory) { 654 ImageDataDirectory* directory) {
656 655
657 if (index < number_of_data_directories_) { 656 if (index < number_of_data_directories_) {
658 size_t offset = index * 8 + offset_of_data_directories_; 657 FileOffset file_offset = index * 8 + offset_of_data_directories_;
659 if (offset >= size_of_optional_header_) 658 if (file_offset >= size_of_optional_header_)
660 return Bad("number of data directories inconsistent"); 659 return Bad("number of data directories inconsistent");
661 const uint8_t* data_directory = optional_header_ + offset; 660 const uint8_t* data_directory = optional_header_ + file_offset;
662 if (data_directory < start() || 661 if (data_directory < start() ||
663 data_directory + 8 >= end()) 662 data_directory + 8 >= end())
664 return Bad("data directory outside image"); 663 return Bad("data directory outside image");
665 RVA rva = ReadU32(data_directory, 0); 664 RVA rva = ReadU32(data_directory, 0);
666 size_t size = ReadU32(data_directory, 4); 665 size_t size = ReadU32(data_directory, 4);
667 if (size > size_of_image_) 666 if (size > size_of_image_)
668 return Bad("data directory size too big"); 667 return Bad("data directory size too big");
669 668
670 // TODO(sra): validate RVA. 669 // TODO(sra): validate RVA.
671 directory->address_ = rva; 670 directory->address_ = rva;
672 directory->size_ = static_cast<uint32_t>(size); 671 directory->size_ = static_cast<uint32_t>(size);
673 return true; 672 return true;
674 } else { 673 } else {
675 directory->address_ = 0; 674 directory->address_ = 0;
676 directory->size_ = 0; 675 directory->size_ = 0;
677 return true; 676 return true;
678 } 677 }
679 } 678 }
680 679
681 } // namespace courgette 680 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/disassembler_win32_x86.h ('k') | courgette/disassembler_win32_x86_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698