Add binary search table to .eh_frame_hdr
The addresses in the search table must be relative to the start
of .eh_frame_hdr which results in yet another pointer type to patch.
I have moved the Patch method back to elf_writer_quick where
it can be specialized to one of the three pointer types.
The .eh_frame_hdr takes around 17% of .eh_frame now.
Change-Id: I4770d1355ded6cdff9489c33380f6b06c4e3f9fe
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 07976e8..63d3a0d 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -149,19 +149,20 @@
std::vector<ElfDynamicState> dynamics_;
};
+ using PatchFn = void (*)(const std::vector<uintptr_t>& patch_locations,
+ Elf_Addr buffer_address,
+ Elf_Addr base_address,
+ std::vector<uint8_t>* buffer);
+
// Section with content based on simple memory buffer.
// The buffer can be optionally patched before writing.
- // The resulting address can be either absolute memory
- // address or offset relative to the pointer location.
class RawSection FINAL : public Section {
public:
RawSection(const std::string& name, Elf_Word type, Elf_Word flags,
const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize,
- const Section* patch_base = nullptr, bool patch_relative = false,
- bool patch_64bit = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)))
+ PatchFn patch = nullptr, const Section* patch_base_section = nullptr)
: Section(name, type, flags, link, info, align, entsize),
- patched(false), patch_base_(patch_base),
- patch_relative_(patch_relative), patch_64bit_(patch_64bit) {
+ patched_(false), patch_(patch), patch_base_section_(patch_base_section) {
}
Elf_Word GetSize() const OVERRIDE {
@@ -170,22 +171,14 @@
bool Write(File* elf_file) OVERRIDE {
if (!patch_locations_.empty()) {
- DCHECK(patch_base_ != nullptr);
- DCHECK(!patched); // Do not patch twice.
- if (patch_relative_) {
- if (patch_64bit_) {
- Patch<true, uint64_t>();
- } else {
- Patch<true, uint32_t>();
- }
- } else {
- if (patch_64bit_) {
- Patch<false, uint64_t>();
- } else {
- Patch<false, uint32_t>();
- }
- }
- patched = true;
+ DCHECK(!patched_); // Do not patch twice.
+ DCHECK(patch_ != nullptr);
+ DCHECK(patch_base_section_ != nullptr);
+ patch_(patch_locations_,
+ this->GetHeader()->sh_addr,
+ patch_base_section_->GetHeader()->sh_addr,
+ &buffer_);
+ patched_ = true;
}
return WriteArray(elf_file, buffer_.data(), buffer_.size());
}
@@ -207,23 +200,13 @@
}
private:
- template <bool RelativeAddress = false, typename PatchedAddress = Elf_Addr>
- void Patch() {
- Elf_Addr base_addr = patch_base_->GetHeader()->sh_addr;
- Elf_Addr addr = this->GetHeader()->sh_addr;
- for (uintptr_t patch_location : patch_locations_) {
- typedef __attribute__((__aligned__(1))) PatchedAddress UnalignedAddress;
- auto* to_patch = reinterpret_cast<UnalignedAddress*>(buffer_.data() + patch_location);
- *to_patch = (base_addr + *to_patch) - (RelativeAddress ? (addr + patch_location) : 0);
- }
- }
-
std::vector<uint8_t> buffer_;
std::vector<uintptr_t> patch_locations_;
- bool patched;
- const Section* patch_base_;
- bool patch_relative_;
- bool patch_64bit_;
+ bool patched_;
+ // User-provided function to do the actual patching.
+ PatchFn patch_;
+ // The section that we patch against (usually .text).
+ const Section* patch_base_section_;
};
// Writer of .rodata section or .text section.