diff options
author | Samuel Huang <huangs@chromium.org> | 2018-10-10 15:48:10 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2021-07-25 20:38:54 -0700 |
commit | 98dd0173969ff0905b49bf6236d51f69c5c05f65 (patch) | |
tree | d82ee350388331a379d0324f5e60439a0e9d2208 /address_translator.cc | |
parent | e53806a25b988acd67fe57b42eaa611f2ba96a75 (diff) | |
download | zucchini-98dd0173969ff0905b49bf6236d51f69c5c05f65.tar.gz |
[Zucchini] Fix patch apply failure from untranslatable abs32 references.
Disassembler (Win32 and ELF) uses reloc to find abs32 locations, which
are stored in (1) |abs32_locations_|. Later on, (1) is filtered to
generate (2) actual abs32 locations.
A patching failure case was discovered: Equivalence blocks must never
cut across reference boundaries. However, it turns out blocks generated
using (2) were subject to checks using (1), which triggers a failure
since (1) - (2) is nonempty.
One way for (1) != (2) to happen is from CURRENT_MODULE() usage, which
creates an abs32 reference outside a section. This results in an abs32
target whose RVA does not map to an offset using section data, and
gets rejected by filtering logic for (2).
Fix: Apply the filtering logic direcly to (1), so (1) == (2). Details:
* Add RemoveUntranslatableAbs32() (abs32_utils.h), which uses the
filtering logic for (2) to preemptively remove problematic RVAs
from (1), so |abs32_locations_| matches (2). Extensive unit tests
are added.
* DisassemblerWin32<Traits>::ParseAndStoreAbs32(): Initialize
|abs32_locations_| with 3 steps: Naive extraction from relocs,
RemoveUntranslatableAbs32(), and RemoveOverlappingAbs32Locations().
* DisassemblerElf<Traits>::GetAbs32FromRelocSections(): Do the same,
noting that ELF's image base is always 0.
Additional fixes:
* address_translator.h: kInvalidRva was -1, but it should be -2 to
better match kInvalidOffset.
* Abs32RvaExtractorWin32::Abs32RvaExtractorWin32: The lambda
|find_and_check| binds |addr|, which has been std::move()'ed.
Better to just bind |this| and use |addr_|.
Bug: 892284
Change-Id: I628f4668ea231c7e06f35bd924652ca4d74bb848
Reviewed-on: https://chromium-review.googlesource.com/c/1263877
Reviewed-by: Greg Thompson <grt@chromium.org>
Reviewed-by: Samuel Huang <huangs@chromium.org>
Commit-Queue: Samuel Huang <huangs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#598342}
NOKEYCHECK=True
GitOrigin-RevId: b6d108f1cabab2a9f3fe46a7cdeb92685a2c790e
Diffstat (limited to 'address_translator.cc')
-rw-r--r-- | address_translator.cc | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/address_translator.cc b/address_translator.cc index 5b388da..20f19b2 100644 --- a/address_translator.cc +++ b/address_translator.cc @@ -38,6 +38,8 @@ AddressTranslator::RvaToOffsetCache::RvaToOffsetCache( : translator_(translator) {} bool AddressTranslator::RvaToOffsetCache::IsValid(rva_t rva) const { + if (rva == kInvalidRva) + return false; if (!cached_unit_ || !cached_unit_->CoversRva(rva)) { const AddressTranslator::Unit* unit = translator_.RvaToUnit(rva); if (!unit) |