diff options
author | Samuel Huang <huangs@chromium.org> | 2019-03-21 20:40:55 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2021-07-25 20:52:44 -0700 |
commit | 0047fda863b1ebb43d2dc015643d3b59ec5734af (patch) | |
tree | aaa19ccd87130e3c1a9df2977aa45add1926b9b5 /disassembler_elf.cc | |
parent | 156a6f21e644f2186e7ed2ef72df76939f58931c (diff) | |
download | zucchini-0047fda863b1ebb43d2dc015643d3b59ec5734af.tar.gz |
[Zucchini] Rel32Finder: Make rel32 accept / reject semantics explicit.
Zucchini heuristically scans assembly code byte-by-byte for rel32
references. When found, the result needs validation, and on X86 / X64,
this directs where to scan next: If accepted, scan resumes after the
instruction containing the rel32 found; if rejected, scan resumes on
the next byte.
Rel32Finder implements the above interactively: GetNext() emits the
next candidate rel32, and the caller needs to call Accept() to signal
acceptance (else rejection is assumed).
Inherited classes of Rel32Finder implements architecture-specific code
via Scan(), which caches results. Previously, Scan() also returns a
range for the instruction found. If accepted, scan resumes after the
range; if rejected, scan resumes 1 byte after the start of range.
Problem: The "scan 1 byte after" scheme works well for X86 / X64 and
fixed-size instructions (by aligning in Scan()). However, for THUMB2
instructions in ARM, which has easily discernible 2-byte and 4-byte
op codes, for both "accept" and "reject", scan should resume on the
next instruction.
This CL refactors Rel32Finder to solve the above, with other cleanup.
Details:
* Change Scan() to return (new struct) NextIterators, which stores
iterator for "accept" and "reject" cases.
* Rename Reset() to SetRegion() to assign |region_|, and remove the
|region_| assignment via constructor.
* Add Rel32FinderIntel::SetResult().
* Move more code from .h to .cc.
* Rename |next_cursor_| to |accept_it_|.
* Extensive comment updates.
Bug: 943315,918867
Change-Id: Ie0a0b380975c35b0aedb013037f8d69673c9697c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1529166
Reviewed-by: Etienne Pierre-Doray <etiennep@chromium.org>
Reviewed-by: Samuel Huang <huangs@chromium.org>
Commit-Queue: Samuel Huang <huangs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#643098}
NOKEYCHECK=True
GitOrigin-RevId: 47fef62aa7626d9a47fc1986b8e51e6e866570d1
Diffstat (limited to 'disassembler_elf.cc')
-rw-r--r-- | disassembler_elf.cc | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/disassembler_elf.cc b/disassembler_elf.cc index ef050a4..474f43e 100644 --- a/disassembler_elf.cc +++ b/disassembler_elf.cc @@ -371,13 +371,12 @@ void DisassemblerElfIntel<Traits>::ParseExecSection( ConstBufferView region(image_.begin() + section.sh_offset, section.sh_size); Abs32GapFinder gap_finder(image_, region, abs32_locations_, 4); - std::unique_ptr<Rel32FinderIntel> finder = - std::make_unique<typename Traits::Rel32FinderUse>(image_); + typename Traits::Rel32FinderUse finder; for (auto gap = gap_finder.GetNext(); gap.has_value(); gap = gap_finder.GetNext()) { - finder->Reset(gap.value()); - for (auto rel32 = finder->GetNext(); rel32.has_value(); - rel32 = finder->GetNext()) { + finder.SetRegion(gap.value()); + for (auto rel32 = finder.GetNext(); rel32.has_value(); + rel32 = finder.GetNext()) { offset_t rel32_offset = base::checked_cast<offset_t>(rel32->location - image_.begin()); rva_t rel32_rva = rva_t(rel32_offset + from_offset_to_rva); @@ -385,7 +384,7 @@ void DisassemblerElfIntel<Traits>::ParseExecSection( if (target_rva_checker.IsValid(target_rva) && (rel32->can_point_outside_section || (start_rva <= target_rva && target_rva < end_rva))) { - finder->Accept(); + finder.Accept(); rel32_locations_.push_back(rel32_offset); } } |