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

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

Powered by Google App Engine
This is Rietveld 408576698