OLD | NEW |
---|---|
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 Loading... | |
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. |
grt (UTC plus 2)
2016/11/07 09:36:17
does it make sense to push these two passes into A
huangs
2016/11/07 19:46:52
Okay I'll hide the 2-pass detail from this functio
| |
183 InstructionCountReceptor* count_receptor = nullptr; | |
184 if (!target->CreateInstructionCountReceptor(&count_receptor) || | |
185 !ParseFile(target, count_receptor)) { | |
183 return false; | 186 return false; |
187 } | |
188 // Pass 2: Emit all instructions to preallocated buffer (uses Phase 1 count). | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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, ¤t_abs_offset, |
400 ¤t_abs_offset, | 411 end_abs_offset, ¤t_rel, end_rel, |
401 end_abs_offset, | 412 program, receptor)) { |
402 ¤t_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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |