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

Side by Side Diff: courgette/disassembler_elf_32.cc

Issue 2462993003: [Courgette] Refactor: Add and use Instruction*Receptor classes; call ParseFile() in 2 passes. (Closed)
Patch Set: Fix comments. Created 4 years, 1 month 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_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('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 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_elf_32.h" 5 #include "courgette/disassembler_elf_32.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "courgette/assembly_program.h" 13 #include "courgette/assembly_program.h"
13 #include "courgette/courgette.h" 14 #include "courgette/courgette.h"
14 15
15 namespace courgette { 16 namespace courgette {
16 17
17 namespace { 18 namespace {
18 19
19 // Sorts |section_headers| by file offset and stores the resulting permutation 20 // Sorts |section_headers| by file offset and stores the resulting permutation
20 // of section ids in |order|. 21 // of section ids in |order|.
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 173
173 if (!ParseAbs32Relocs()) 174 if (!ParseAbs32Relocs())
174 return false; 175 return false;
175 176
176 if (!ParseRel32RelocsFromSections()) // Does not sort rel32 locations. 177 if (!ParseRel32RelocsFromSections()) // Does not sort rel32 locations.
177 return false; 178 return false;
178 179
179 PrecomputeLabels(target); 180 PrecomputeLabels(target);
180 RemoveUnusedRel32Locations(target); 181 RemoveUnusedRel32Locations(target);
181 182
182 if (!ParseFile(target)) 183 if (!target->GenerateInstructions(
184 base::Bind(&DisassemblerElf32::ParseFile, base::Unretained(this)))) {
183 return false; 185 return false;
186 }
184 187
185 // Finally sort rel32 locations. 188 // Finally sort rel32 locations.
186 std::sort(rel32_locations_.begin(), 189 std::sort(rel32_locations_.begin(),
187 rel32_locations_.end(), 190 rel32_locations_.end(),
188 TypedRVA::IsLessThanByRVA); 191 TypedRVA::IsLessThanByRVA);
189 DCHECK(rel32_locations_.empty() || 192 DCHECK(rel32_locations_.empty() ||
190 rel32_locations_.back()->rva() != kUnassignedRVA); 193 rel32_locations_.back()->rva() != kUnassignedRVA);
191 194
192 target->DefaultAssignIndexes(); 195 target->DefaultAssignIndexes();
193 return true; 196 return true;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 if (string_pos >= default_string_section_size_) 297 if (string_pos >= default_string_section_size_)
295 return false; 298 return false;
296 // Safe because string section must terminate with null. 299 // Safe because string section must terminate with null.
297 *name = default_string_section_ + string_pos; 300 *name = default_string_section_ + string_pos;
298 } 301 }
299 return true; 302 return true;
300 } 303 }
301 304
302 CheckBool DisassemblerElf32::RVAsToFileOffsets( 305 CheckBool DisassemblerElf32::RVAsToFileOffsets(
303 const std::vector<RVA>& rvas, 306 const std::vector<RVA>& rvas,
304 std::vector<FileOffset>* file_offsets) { 307 std::vector<FileOffset>* file_offsets) const {
305 file_offsets->clear(); 308 file_offsets->clear();
306 file_offsets->reserve(rvas.size()); 309 file_offsets->reserve(rvas.size());
307 for (RVA rva : rvas) { 310 for (RVA rva : rvas) {
308 FileOffset file_offset = RVAToFileOffset(rva); 311 FileOffset file_offset = RVAToFileOffset(rva);
309 if (file_offset == kNoFileOffset) 312 if (file_offset == kNoFileOffset)
310 return false; 313 return false;
311 file_offsets->push_back(file_offset); 314 file_offsets->push_back(file_offset);
312 } 315 }
313 return true; 316 return true;
314 } 317 }
315 318
316 CheckBool DisassemblerElf32::RVAsToFileOffsets( 319 CheckBool DisassemblerElf32::RVAsToFileOffsets(
317 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) { 320 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) const {
318 for (auto& typed_rva : *typed_rvas) { 321 for (auto& typed_rva : *typed_rvas) {
319 FileOffset file_offset = RVAToFileOffset(typed_rva->rva()); 322 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
320 if (file_offset == kNoFileOffset) 323 if (file_offset == kNoFileOffset)
321 return false; 324 return false;
322 typed_rva->set_file_offset(file_offset); 325 typed_rva->set_file_offset(file_offset);
323 } 326 }
324 return true; 327 return true;
325 } 328 }
326 329
327 RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() { 330 RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() {
(...skipping 15 matching lines...) Expand all
343 } else { 346 } else {
344 // Else squeeze nullptr to end to compactify. 347 // Else squeeze nullptr to end to compactify.
345 if (tail_it != head_it) 348 if (tail_it != head_it)
346 (*tail_it).swap(*head_it); 349 (*tail_it).swap(*head_it);
347 ++tail_it; 350 ++tail_it;
348 } 351 }
349 } 352 }
350 rel32_locations_.resize(std::distance(rel32_locations_.begin(), tail_it)); 353 rel32_locations_.resize(std::distance(rel32_locations_.begin(), tail_it));
351 } 354 }
352 355
353 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) { 356 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program,
357 InstructionReceptor* receptor) const {
354 // Walk all the bytes in the file, whether or not in a section. 358 // Walk all the bytes in the file, whether or not in a section.
355 FileOffset file_offset = 0; 359 FileOffset file_offset = 0;
356 360
357 std::vector<FileOffset> abs_offsets; 361 std::vector<FileOffset> abs_offsets;
358 362
359 // File parsing follows file offset order, and we visit abs32 and rel32 363 // File parsing follows file offset order, and we visit abs32 and rel32
360 // locations in lockstep. Therefore we need to extract and sort file offsets 364 // locations in lockstep. Therefore we need to extract and sort file offsets
361 // of all abs32 and rel32 locations. 365 // of all abs32 and rel32 locations.
362 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets)) 366 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
363 return false; 367 return false;
(...skipping 13 matching lines...) Expand all
377 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel = 381 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel =
378 rel32_locations_.end(); 382 rel32_locations_.end();
379 383
380 // Visit section headers ordered by file offset. 384 // Visit section headers ordered by file offset.
381 for (Elf32_Half section_id : section_header_file_offset_order_) { 385 for (Elf32_Half section_id : section_header_file_offset_order_) {
382 const Elf32_Shdr* section_header = SectionHeader(section_id); 386 const Elf32_Shdr* section_header = SectionHeader(section_id);
383 387
384 if (section_header->sh_type == SHT_NOBITS) 388 if (section_header->sh_type == SHT_NOBITS)
385 continue; 389 continue;
386 390
387 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program)) 391 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, receptor))
388 return false; 392 return false;
389 393
390 file_offset = section_header->sh_offset; 394 file_offset = section_header->sh_offset;
391 395
392 switch (section_header->sh_type) { 396 switch (section_header->sh_type) {
393 case SHT_REL: 397 case SHT_REL:
394 if (!ParseRelocationSection(section_header, program)) 398 if (!ParseRelocationSection(section_header, receptor))
395 return false; 399 return false;
396 file_offset = section_header->sh_offset + section_header->sh_size; 400 file_offset = section_header->sh_offset + section_header->sh_size;
397 break; 401 break;
398 case SHT_PROGBITS: 402 case SHT_PROGBITS:
399 if (!ParseProgbitsSection(section_header, 403 if (!ParseProgbitsSection(section_header, &current_abs_offset,
400 &current_abs_offset, 404 end_abs_offset, &current_rel, end_rel,
401 end_abs_offset, 405 program, receptor)) {
402 &current_rel,
403 end_rel,
404 program)) {
405 return false; 406 return false;
406 } 407 }
407 file_offset = section_header->sh_offset + section_header->sh_size; 408 file_offset = section_header->sh_offset + section_header->sh_size;
408 break; 409 break;
409 case SHT_INIT_ARRAY: 410 case SHT_INIT_ARRAY:
410 // Fall through 411 // Fall through
411 case SHT_FINI_ARRAY: 412 case SHT_FINI_ARRAY:
412 while (current_abs_offset != end_abs_offset && 413 while (current_abs_offset != end_abs_offset &&
413 *current_abs_offset >= section_header->sh_offset && 414 *current_abs_offset >= section_header->sh_offset &&
414 *current_abs_offset < 415 *current_abs_offset <
(...skipping 10 matching lines...) Expand all
425 *current_abs_offset < 426 *current_abs_offset <
426 section_header->sh_offset + section_header->sh_size) { 427 section_header->sh_offset + section_header->sh_size) {
427 VLOG(1) << "Relocation address in unrecognized ELF section: " 428 VLOG(1) << "Relocation address in unrecognized ELF section: "
428 << section_header->sh_type; 429 << section_header->sh_type;
429 } 430 }
430 break; 431 break;
431 } 432 }
432 } 433 }
433 434
434 // Rest of the file past the last section 435 // Rest of the file past the last section
435 if (!ParseSimpleRegion(file_offset, length(), program)) 436 if (!ParseSimpleRegion(file_offset, length(), receptor))
436 return false; 437 return false;
437 438
438 // Make certain we consume all of the relocations as expected 439 // Make certain we consume all of the relocations as expected
439 return (current_abs_offset == end_abs_offset); 440 return (current_abs_offset == end_abs_offset);
440 } 441 }
441 442
442 CheckBool DisassemblerElf32::ParseProgbitsSection( 443 CheckBool DisassemblerElf32::ParseProgbitsSection(
443 const Elf32_Shdr* section_header, 444 const Elf32_Shdr* section_header,
444 std::vector<FileOffset>::iterator* current_abs_offset, 445 std::vector<FileOffset>::iterator* current_abs_offset,
445 std::vector<FileOffset>::iterator end_abs_offset, 446 std::vector<FileOffset>::iterator end_abs_offset,
446 std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel, 447 std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
447 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel, 448 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
448 AssemblyProgram* program) { 449 AssemblyProgram* program,
450 InstructionReceptor* receptor) const {
449 // Walk all the bytes in the file, whether or not in a section. 451 // Walk all the bytes in the file, whether or not in a section.
450 FileOffset file_offset = section_header->sh_offset; 452 FileOffset file_offset = section_header->sh_offset;
451 FileOffset section_end = section_header->sh_offset + section_header->sh_size; 453 FileOffset section_end = section_header->sh_offset + section_header->sh_size;
452 454
453 Elf32_Addr origin = section_header->sh_addr; 455 Elf32_Addr origin = section_header->sh_addr;
454 FileOffset origin_offset = section_header->sh_offset; 456 FileOffset origin_offset = section_header->sh_offset;
455 if (!program->EmitOriginInstruction(origin)) 457 if (!receptor->EmitOrigin(origin))
456 return false; 458 return false;
457 459
458 while (file_offset < section_end) { 460 while (file_offset < section_end) {
459 if (*current_abs_offset != end_abs_offset && 461 if (*current_abs_offset != end_abs_offset &&
460 file_offset > **current_abs_offset) 462 file_offset > **current_abs_offset)
461 return false; 463 return false;
462 464
463 while (*current_rel != end_rel && 465 while (*current_rel != end_rel &&
464 file_offset > (**current_rel)->file_offset()) { 466 file_offset > (**current_rel)->file_offset()) {
465 ++(*current_rel); 467 ++(*current_rel);
466 } 468 }
467 469
468 FileOffset next_relocation = section_end; 470 FileOffset next_relocation = section_end;
469 471
470 if (*current_abs_offset != end_abs_offset && 472 if (*current_abs_offset != end_abs_offset &&
471 next_relocation > **current_abs_offset) 473 next_relocation > **current_abs_offset)
472 next_relocation = **current_abs_offset; 474 next_relocation = **current_abs_offset;
473 475
474 // Rel offsets are heuristically derived, and might (incorrectly) overlap 476 // Rel offsets are heuristically derived, and might (incorrectly) overlap
475 // an Abs value, or the end of the section, so +3 to make sure there is 477 // an Abs value, or the end of the section, so +3 to make sure there is
476 // room for the full 4 byte value. 478 // room for the full 4 byte value.
477 if (*current_rel != end_rel && 479 if (*current_rel != end_rel &&
478 next_relocation > ((**current_rel)->file_offset() + 3)) 480 next_relocation > ((**current_rel)->file_offset() + 3))
479 next_relocation = (**current_rel)->file_offset(); 481 next_relocation = (**current_rel)->file_offset();
480 482
481 if (next_relocation > file_offset) { 483 if (next_relocation > file_offset) {
482 if (!ParseSimpleRegion(file_offset, next_relocation, program)) 484 if (!ParseSimpleRegion(file_offset, next_relocation, receptor))
483 return false; 485 return false;
484 486
485 file_offset = next_relocation; 487 file_offset = next_relocation;
486 continue; 488 continue;
487 } 489 }
488 490
489 if (*current_abs_offset != end_abs_offset && 491 if (*current_abs_offset != end_abs_offset &&
490 file_offset == **current_abs_offset) { 492 file_offset == **current_abs_offset) {
491 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset)); 493 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset));
492 DCHECK_NE(kNoRVA, target_rva); 494 DCHECK_NE(kNoRVA, target_rva);
493 495
494 Label* label = program->FindAbs32Label(target_rva); 496 Label* label = program->FindAbs32Label(target_rva);
495 CHECK(label); 497 CHECK(label);
496 if (!program->EmitAbs32(label)) 498 if (!receptor->EmitAbs32(label))
497 return false; 499 return false;
498 file_offset += sizeof(RVA); 500 file_offset += sizeof(RVA);
499 ++(*current_abs_offset); 501 ++(*current_abs_offset);
500 continue; 502 continue;
501 } 503 }
502 504
503 if (*current_rel != end_rel && 505 if (*current_rel != end_rel &&
504 file_offset == (**current_rel)->file_offset()) { 506 file_offset == (**current_rel)->file_offset()) {
505 uint32_t relative_target = (**current_rel)->relative_target(); 507 uint32_t relative_target = (**current_rel)->relative_target();
506 CHECK_EQ(RVA(origin + (file_offset - origin_offset)), 508 CHECK_EQ(RVA(origin + (file_offset - origin_offset)),
507 (**current_rel)->rva()); 509 (**current_rel)->rva());
508 // This cast is for 64 bit systems, and is only safe because we 510 // This cast is for 64 bit systems, and is only safe because we
509 // are working on 32 bit executables. 511 // are working on 32 bit executables.
510 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + 512 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
511 relative_target); 513 relative_target);
512 514
513 Label* label = program->FindRel32Label(target_rva); 515 Label* label = program->FindRel32Label(target_rva);
514 CHECK(label); 516 CHECK(label);
515 517
516 if (!(**current_rel)->EmitInstruction(program, label)) 518 if (!(**current_rel)->EmitInstruction(label, receptor))
517 return false; 519 return false;
518 file_offset += (**current_rel)->op_size(); 520 file_offset += (**current_rel)->op_size();
519 ++(*current_rel); 521 ++(*current_rel);
520 continue; 522 continue;
521 } 523 }
522 } 524 }
523 525
524 // Rest of the section (if any) 526 // Rest of the section (if any)
525 return ParseSimpleRegion(file_offset, section_end, program); 527 return ParseSimpleRegion(file_offset, section_end, receptor);
526 } 528 }
527 529
528 CheckBool DisassemblerElf32::ParseSimpleRegion(FileOffset start_file_offset, 530 CheckBool DisassemblerElf32::ParseSimpleRegion(
529 FileOffset end_file_offset, 531 FileOffset start_file_offset,
530 AssemblyProgram* program) { 532 FileOffset end_file_offset,
533 InstructionReceptor* receptor) const {
531 // Callers don't guarantee start < end 534 // Callers don't guarantee start < end
532 if (start_file_offset >= end_file_offset) 535 if (start_file_offset >= end_file_offset)
533 return true; 536 return true;
534 537
535 const size_t len = end_file_offset - start_file_offset; 538 const size_t len = end_file_offset - start_file_offset;
536 539
537 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset), 540 if (!receptor->EmitMultipleBytes(FileOffsetToPointer(start_file_offset),
538 len)) { 541 len)) {
539 return false; 542 return false;
540 } 543 }
541 544
542 return true; 545 return true;
543 } 546 }
544 547
545 CheckBool DisassemblerElf32::ParseAbs32Relocs() { 548 CheckBool DisassemblerElf32::ParseAbs32Relocs() {
546 abs32_locations_.clear(); 549 abs32_locations_.clear();
547 550
548 // Loop through sections for relocation sections 551 // Loop through sections for relocation sections
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 if (!ParseRel32RelocsFromSection(section_header)) 627 if (!ParseRel32RelocsFromSection(section_header))
625 return false; 628 return false;
626 } 629 }
627 if (!found_rel32) 630 if (!found_rel32)
628 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?"; 631 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?";
629 632
630 return true; 633 return true;
631 } 634 }
632 635
633 } // namespace courgette 636 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/disassembler_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698