OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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.h" | 5 #include "courgette/disassembler_win32.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 // Pretend our in-memory copy is only as long as our detected length. | 214 // Pretend our in-memory copy is only as long as our detected length. |
215 ReduceLength(detected_length); | 215 ReduceLength(detected_length); |
216 | 216 |
217 if (!has_text_section()) { | 217 if (!has_text_section()) { |
218 return Bad("Resource-only executables are not yet supported"); | 218 return Bad("Resource-only executables are not yet supported"); |
219 } | 219 } |
220 | 220 |
221 return Good(); | 221 return Good(); |
222 } | 222 } |
223 | 223 |
224 bool DisassemblerWin32::Disassemble(AssemblyProgram* program) { | |
225 if (!ok()) | |
226 return false; | |
227 | |
228 if (!ParseAbs32Relocs()) | |
229 return false; | |
230 | |
231 ParseRel32RelocsFromSections(); | |
232 | |
233 PrecomputeLabels(program); | |
234 RemoveUnusedRel32Locations(program); | |
235 | |
236 if (!program->GenerateInstructions( | |
237 base::Bind(&DisassemblerWin32::ParseFile, base::Unretained(this)))) { | |
238 return false; | |
239 } | |
240 | |
241 program->DefaultAssignIndexes(); | |
242 return true; | |
243 } | |
244 | |
245 //////////////////////////////////////////////////////////////////////////////// | 224 //////////////////////////////////////////////////////////////////////////////// |
246 | 225 |
247 bool DisassemblerWin32::ParseRelocs(std::vector<RVA>* relocs) { | 226 bool DisassemblerWin32::ParseRelocs(std::vector<RVA>* relocs) { |
248 relocs->clear(); | 227 relocs->clear(); |
249 | 228 |
250 size_t relocs_size = base_relocation_table_.size_; | 229 size_t relocs_size = base_relocation_table_.size_; |
251 if (relocs_size == 0) | 230 if (relocs_size == 0) |
252 return true; | 231 return true; |
253 | 232 |
254 // The format of the base relocation table is a sequence of variable sized | 233 // The format of the base relocation table is a sequence of variable sized |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 const uint8_t* optional_header = pe_header + 4 + kSizeOfCoffHeader; | 337 const uint8_t* optional_header = pe_header + 4 + kSizeOfCoffHeader; |
359 // Check we can read the magic. | 338 // Check we can read the magic. |
360 if (optional_header + 2 >= start + length) | 339 if (optional_header + 2 >= start + length) |
361 return false; | 340 return false; |
362 if (magic != ReadU16(optional_header, 0)) | 341 if (magic != ReadU16(optional_header, 0)) |
363 return false; | 342 return false; |
364 | 343 |
365 return true; | 344 return true; |
366 } | 345 } |
367 | 346 |
368 bool DisassemblerWin32::ParseAbs32Relocs() { | 347 bool DisassemblerWin32::ExtractAbs32Locations() { |
369 abs32_locations_.clear(); | 348 abs32_locations_.clear(); |
370 if (!ParseRelocs(&abs32_locations_)) | 349 if (!ParseRelocs(&abs32_locations_)) |
371 return false; | 350 return false; |
372 | 351 |
373 #if COURGETTE_HISTOGRAM_TARGETS | 352 #if COURGETTE_HISTOGRAM_TARGETS |
374 for (size_t i = 0; i < abs32_locations_.size(); ++i) { | 353 for (size_t i = 0; i < abs32_locations_.size(); ++i) { |
375 RVA rva = abs32_locations_[i]; | 354 RVA rva = abs32_locations_[i]; |
376 // The 4 bytes at the relocation are a reference to some address. | 355 // The 4 bytes at the relocation are a reference to some address. |
377 ++abs32_target_rvas_[PointerToTargetRVA(RVAToPointer(rva))]; | 356 ++abs32_target_rvas_[PointerToTargetRVA(RVAToPointer(rva))]; |
378 } | 357 } |
379 #endif | 358 #endif |
380 return true; | 359 return true; |
381 } | 360 } |
382 | 361 |
383 void DisassemblerWin32::ParseRel32RelocsFromSections() { | 362 bool DisassemblerWin32::ExtractRel32Locations() { |
384 FileOffset file_offset = 0; | 363 FileOffset file_offset = 0; |
385 while (file_offset < length()) { | 364 while (file_offset < length()) { |
386 const Section* section = FindNextSection(file_offset); | 365 const Section* section = FindNextSection(file_offset); |
387 if (section == nullptr) | 366 if (section == nullptr) |
388 break; | 367 break; |
389 if (file_offset < section->file_offset_of_raw_data) | 368 if (file_offset < section->file_offset_of_raw_data) |
390 file_offset = section->file_offset_of_raw_data; | 369 file_offset = section->file_offset_of_raw_data; |
391 ParseRel32RelocsFromSection(section); | 370 ParseRel32RelocsFromSection(section); |
392 file_offset += section->size_of_raw_data; | 371 file_offset += section->size_of_raw_data; |
393 } | 372 } |
(...skipping 16 matching lines...) Expand all Loading... |
410 } else if (rel32_iter->first < abs32_iter->first) { | 389 } else if (rel32_iter->first < abs32_iter->first) { |
411 ++rel32_iter; | 390 ++rel32_iter; |
412 } else { | 391 } else { |
413 ++common; | 392 ++common; |
414 ++abs32_iter; | 393 ++abs32_iter; |
415 ++rel32_iter; | 394 ++rel32_iter; |
416 } | 395 } |
417 } | 396 } |
418 VLOG(1) << "common " << common; | 397 VLOG(1) << "common " << common; |
419 #endif | 398 #endif |
| 399 return true; |
420 } | 400 } |
421 | 401 |
422 RvaVisitor* DisassemblerWin32::CreateAbs32TargetRvaVisitor() { | 402 RvaVisitor* DisassemblerWin32::CreateAbs32TargetRvaVisitor() { |
423 return new RvaVisitor_Abs32(abs32_locations_, *this); | 403 return new RvaVisitor_Abs32(abs32_locations_, *this); |
424 } | 404 } |
425 | 405 |
426 RvaVisitor* DisassemblerWin32::CreateRel32TargetRvaVisitor() { | 406 RvaVisitor* DisassemblerWin32::CreateRel32TargetRvaVisitor() { |
427 return new RvaVisitor_Rel32(rel32_locations_, *this); | 407 return new RvaVisitor_Rel32(rel32_locations_, *this); |
428 } | 408 } |
429 | 409 |
430 void DisassemblerWin32::RemoveUnusedRel32Locations( | 410 void DisassemblerWin32::RemoveUnusedRel32Locations( |
431 AssemblyProgram* program) { | 411 AssemblyProgram* program) { |
432 auto cond = [this, program](RVA rva) -> bool { | 412 auto cond = [this, program](RVA rva) -> bool { |
433 // + 4 since offset is relative to start of next instruction. | 413 // + 4 since offset is relative to start of next instruction. |
434 RVA target_rva = rva + 4 + Read32LittleEndian(RVAToPointer(rva)); | 414 RVA target_rva = rva + 4 + Read32LittleEndian(RVAToPointer(rva)); |
435 return program->FindRel32Label(target_rva) == nullptr; | 415 return program->FindRel32Label(target_rva) == nullptr; |
436 }; | 416 }; |
437 rel32_locations_.erase( | 417 rel32_locations_.erase( |
438 std::remove_if(rel32_locations_.begin(), rel32_locations_.end(), cond), | 418 std::remove_if(rel32_locations_.begin(), rel32_locations_.end(), cond), |
439 rel32_locations_.end()); | 419 rel32_locations_.end()); |
440 } | 420 } |
441 | 421 |
| 422 InstructionGenerator DisassemblerWin32::GetInstructionGenerator( |
| 423 AssemblyProgram* program) { |
| 424 return base::Bind(&DisassemblerWin32::ParseFile, base::Unretained(this), |
| 425 program); |
| 426 } |
| 427 |
442 CheckBool DisassemblerWin32::ParseFile(AssemblyProgram* program, | 428 CheckBool DisassemblerWin32::ParseFile(AssemblyProgram* program, |
443 InstructionReceptor* receptor) const { | 429 InstructionReceptor* receptor) const { |
444 // Walk all the bytes in the file, whether or not in a section. | 430 // Walk all the bytes in the file, whether or not in a section. |
445 FileOffset file_offset = 0; | 431 FileOffset file_offset = 0; |
446 while (file_offset < length()) { | 432 while (file_offset < length()) { |
447 const Section* section = FindNextSection(file_offset); | 433 const Section* section = FindNextSection(file_offset); |
448 if (section == nullptr) { | 434 if (section == nullptr) { |
449 // No more sections. There should not be extra stuff following last | 435 // No more sections. There should not be extra stuff following last |
450 // section. | 436 // section. |
451 // ParseNonSectionFileRegion(file_offset, pe_info().length(), receptor); | 437 // ParseNonSectionFileRegion(file_offset, pe_info().length(), receptor); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 directory->size_ = static_cast<uint32_t>(size); | 663 directory->size_ = static_cast<uint32_t>(size); |
678 return true; | 664 return true; |
679 } else { | 665 } else { |
680 directory->address_ = 0; | 666 directory->address_ = 0; |
681 directory->size_ = 0; | 667 directory->size_ = 0; |
682 return true; | 668 return true; |
683 } | 669 } |
684 } | 670 } |
685 | 671 |
686 } // namespace courgette | 672 } // namespace courgette |
OLD | NEW |