From 98dd0173969ff0905b49bf6236d51f69c5c05f65 Mon Sep 17 00:00:00 2001 From: Samuel Huang Date: Wed, 10 Oct 2018 15:48:10 +0000 Subject: [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::ParseAndStoreAbs32(): Initialize |abs32_locations_| with 3 steps: Naive extraction from relocs, RemoveUntranslatableAbs32(), and RemoveOverlappingAbs32Locations(). * DisassemblerElf::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 Reviewed-by: Samuel Huang Commit-Queue: Samuel Huang Cr-Commit-Position: refs/heads/master@{#598342} NOKEYCHECK=True GitOrigin-RevId: b6d108f1cabab2a9f3fe46a7cdeb92685a2c790e --- address_translator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'address_translator.h') diff --git a/address_translator.h b/address_translator.h index 821b9ad..5666b99 100644 --- a/address_translator.h +++ b/address_translator.h @@ -59,7 +59,7 @@ namespace zucchini { using rva_t = uint32_t; // Divide by 2 to match |kOffsetBound|. constexpr rva_t kRvaBound = static_cast(-1) / 2; -constexpr rva_t kInvalidRva = static_cast(-1); +constexpr rva_t kInvalidRva = static_cast(-2); // A utility to translate between offsets and RVAs in an image. class AddressTranslator { @@ -133,6 +133,7 @@ class AddressTranslator { explicit RvaToOffsetCache(const AddressTranslator& translator); bool IsValid(rva_t rva) const; + offset_t Convert(rva_t rva) const; private: -- cgit v1.2.3