OLD | NEW |
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 ref.size(), | 540 ref.size(), |
541 it->second.first, | 541 it->second.first, |
542 it->second.second, | 542 it->second.second, |
543 it->second.second + delta); | 543 it->second.second + delta); |
544 referrer->SetReference(reference_it->first, new_reference); | 544 referrer->SetReference(reference_it->first, new_reference); |
545 } | 545 } |
546 } | 546 } |
547 } | 547 } |
548 } | 548 } |
549 | 549 |
| 550 size_t GetSectionOffset(const ImageLayout& image_layout, |
| 551 const RelativeAddress rel_addr, |
| 552 size_t section_index) { |
| 553 if (section_index == BlockGraph::kInvalidSectionId) |
| 554 return rel_addr.value(); |
| 555 |
| 556 DCHECK_GT(image_layout.sections.size(), section_index); |
| 557 const ImageLayout::SectionInfo& section_info = |
| 558 image_layout.sections[section_index]; |
| 559 |
| 560 DCHECK_GE(rel_addr, section_info.addr); |
| 561 return rel_addr - section_info.addr; |
| 562 } |
| 563 |
| 564 template <class Type> |
| 565 bool UpdateReference(size_t start, Type new_value, std::vector<uint8_t>* data) { |
| 566 common::BinaryBufferParser parser(&data->at(0), data->size()); |
| 567 |
| 568 Type* ref_ptr = NULL; |
| 569 if (!parser.GetAtIgnoreAlignment(start, |
| 570 const_cast<const Type**>(&ref_ptr))) { |
| 571 LOG(ERROR) << "Reference data not in block"; |
| 572 return false; |
| 573 } |
| 574 * ref_ptr = new_value; |
| 575 |
| 576 return true; |
| 577 } |
| 578 |
| 579 bool ResolveReferences2(core::AbsoluteAddress image_base, |
| 580 core::RelativeAddress addr, |
| 581 BlockGraph::Block::ReferenceMap::const_iterator ref_it, |
| 582 const ImageLayout& image_layout) { |
| 583 BlockGraph::Offset start = ref_it->first; |
| 584 const BlockGraph::Reference& ref = ref_it->second; |
| 585 BlockGraph::Block* dst = ref.referenced(); |
| 586 |
| 587 RelativeAddress src_addr(addr + start); |
| 588 RelativeAddress dst_addr; |
| 589 if (!image_layout.blocks.GetAddressOf(dst, &dst_addr)) { |
| 590 LOG(ERROR) << "All blocks must have an address."; |
| 591 return false; |
| 592 } |
| 593 dst_addr += ref.offset(); |
| 594 |
| 595 // Compute the new value of the reference. |
| 596 uint32_t value = 0; |
| 597 switch (ref.type()) { |
| 598 case BlockGraph::ABSOLUTE_REF: |
| 599 value = image_base.value() + dst_addr.value(); |
| 600 break; |
| 601 |
| 602 case BlockGraph::PC_RELATIVE_REF: |
| 603 value = dst_addr - (src_addr + ref.size()); |
| 604 break; |
| 605 |
| 606 case BlockGraph::RELATIVE_REF: |
| 607 value = dst_addr.value(); |
| 608 break; |
| 609 } |
| 610 |
| 611 return true; |
| 612 } |
| 613 |
| 614 bool ResolveReferences(core::AbsoluteAddress image_base, |
| 615 const block_graph::BlockGraph::Block* block, |
| 616 core::RelativeAddress addr, |
| 617 const core::FileOffsetAddress file_offs, |
| 618 SectionIndexFileRangeMap section_file_range_map, |
| 619 SectionIndexSpace section_index_space, |
| 620 bool write_references_in_place, |
| 621 std::vector<uint8_t>* buffer, |
| 622 const ImageLayout& image_layout) { |
| 623 BlockGraph::Block::ReferenceMap::const_iterator ref_it( |
| 624 block->references().begin()); |
| 625 BlockGraph::Block::ReferenceMap::const_iterator ref_end( |
| 626 block->references().end()); |
| 627 for (; ref_it != ref_end; ++ref_it) { |
| 628 BlockGraph::Offset start = ref_it->first; |
| 629 const BlockGraph::Reference& ref = ref_it->second; |
| 630 BlockGraph::Block* dst = ref.referenced(); |
| 631 |
| 632 RelativeAddress src_addr(addr + start); |
| 633 RelativeAddress dst_addr; |
| 634 if (!image_layout.blocks.GetAddressOf(dst, &dst_addr)) { |
| 635 LOG(ERROR) << "All blocks must have an address."; |
| 636 return false; |
| 637 } |
| 638 dst_addr += ref.offset(); |
| 639 |
| 640 // Compute the new value of the reference. |
| 641 uint32_t value = 0; |
| 642 switch (ref.type()) { |
| 643 case BlockGraph::ABSOLUTE_REF: |
| 644 value = image_base.value() + dst_addr.value(); |
| 645 break; |
| 646 |
| 647 case BlockGraph::PC_RELATIVE_REF: |
| 648 value = dst_addr - (src_addr + ref.size()); |
| 649 break; |
| 650 |
| 651 case BlockGraph::RELATIVE_REF: |
| 652 value = dst_addr.value(); |
| 653 break; |
| 654 |
| 655 case BlockGraph::FILE_OFFSET_REF: { |
| 656 // Get the index of the section containing the destination block. |
| 657 SectionIndexSpace::const_iterator section_index_space_it = |
| 658 section_index_space.FindContaining( |
| 659 SectionIndexSpace::Range(dst_addr, 1)); |
| 660 DCHECK(section_index_space_it != section_index_space.end()); |
| 661 size_t dst_section_index = section_index_space_it->second; |
| 662 |
| 663 // Get the offset of the block in its section, as well as the range of |
| 664 // the section on disk. Validate that the referred location is |
| 665 // actually directly represented on disk (not in implicit virtual data). |
| 666 const FileRange& file_range = |
| 667 section_file_range_map[dst_section_index]; |
| 668 size_t section_offset = GetSectionOffset(image_layout, |
| 669 dst_addr, |
| 670 dst_section_index); |
| 671 if (section_offset >= file_range.size()) { |
| 672 LOG(ERROR) << "Encountered file offset reference that refers to " |
| 673 << "a location outside of the explicit section data."; |
| 674 return false; |
| 675 } |
| 676 |
| 677 // Finally, calculate the value of the file offset. |
| 678 value = file_range.start().value() + section_offset; |
| 679 break; |
| 680 } |
| 681 |
| 682 default: |
| 683 LOG(ERROR) << "Impossible reference type"; |
| 684 return false; |
| 685 } |
| 686 |
| 687 if (!write_references_in_place) |
| 688 return true; |
| 689 |
| 690 // Now store the new value. |
| 691 BlockGraph::Offset ref_offset = file_offs.value() + start; |
| 692 switch (ref.size()) { |
| 693 case sizeof(uint8_t) : |
| 694 if (!UpdateReference(ref_offset, static_cast<uint8_t>(value), buffer)) |
| 695 return false; |
| 696 break; |
| 697 |
| 698 case sizeof(uint16_t) : |
| 699 if (!UpdateReference(ref_offset, static_cast<uint16_t>(value), buffer)) |
| 700 return false; |
| 701 break; |
| 702 |
| 703 case sizeof(uint32_t) : |
| 704 if (!UpdateReference(ref_offset, static_cast<uint32_t>(value), buffer)) |
| 705 return false; |
| 706 break; |
| 707 |
| 708 default: |
| 709 LOG(ERROR) << "Unsupported reference size."; |
| 710 return false; |
| 711 } |
| 712 } |
| 713 return true; |
| 714 } |
550 } // namespace pe | 715 } // namespace pe |
OLD | NEW |