diff options
author | David Srbecky <dsrbecky@google.com> | 2015-04-11 00:17:53 +0100 |
---|---|---|
committer | David Srbecky <dsrbecky@google.com> | 2015-04-11 19:14:10 +0100 |
commit | 2f6cdb01f74772c1c521a125776ef57ea3c73d43 (patch) | |
tree | 163f90841f02b9529997f4e3eea65e512e4795a3 /compiler/elf_writer_quick.cc | |
parent | 58565098b2298041ccc97371a3cc486df88d51b3 (diff) | |
download | android_art-2f6cdb01f74772c1c521a125776ef57ea3c73d43.tar.gz android_art-2f6cdb01f74772c1c521a125776ef57ea3c73d43.tar.bz2 android_art-2f6cdb01f74772c1c521a125776ef57ea3c73d43.zip |
Relocate DWARF using .oat_patches.
The current solution is to hard-code knowledge of DWARF in the linker.
This works for simple use of DWARF, but breaks as soon as I try to do
anything more complex. Making the linker fully support DWARF would be
non-trivial task and would be essentially rewrite. Using .oat_patches
is much easier solution.
Relocating .debug_* sections required extending .oat_patches to support
more sections than just .text. I have encoded each section as
null-terminated section name followed by ULEB128 deltas.
The ULEB128 encoding shrinks .oat_patches for .text by factor of
about 6 with 64-bit compiler, and factor of 3 with 32-bit compiler.
On the other hand, it grows by the extra .oat_patches for DWARF which
were not present before (if debug symbols are included).
Overall, it is still a clear improvement even with the DWARF patches.
Change-Id: I78ffeda0f8a3da03341995a3b5ef15c954e16e9f
Diffstat (limited to 'compiler/elf_writer_quick.cc')
-rw-r--r-- | compiler/elf_writer_quick.cc | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index e9af25f293..da1f81a52e 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -74,6 +74,40 @@ static void WriteDebugSymbols(const CompilerDriver* compiler_driver, Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder, OatWriter* oat_writer); +// Encode patch locations in .oat_patches format. +template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, + typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, + typename Elf_Phdr, typename Elf_Shdr> +void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, Elf_Sym, Elf_Ehdr, + Elf_Phdr, Elf_Shdr>::EncodeOatPatches(const OatWriter::PatchLocationsMap& sections, + std::vector<uint8_t>* buffer) { + for (const auto& section : sections) { + const std::string& name = section.first; + std::vector<uintptr_t>* locations = section.second.get(); + DCHECK(!name.empty()); + std::sort(locations->begin(), locations->end()); + // Reserve buffer space - guess 2 bytes per ULEB128. + buffer->reserve(buffer->size() + name.size() + locations->size() * 2); + // Write null-terminated section name. + const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str()); + buffer->insert(buffer->end(), name_data, name_data + name.size() + 1); + // Write placeholder for data length. + size_t length_pos = buffer->size(); + EncodeUnsignedLeb128(buffer, UINT32_MAX); + // Write LEB128 encoded list of advances (deltas between consequtive addresses). + size_t data_pos = buffer->size(); + uintptr_t address = 0; // relative to start of section. + for (uintptr_t location : *locations) { + DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations"; + EncodeUnsignedLeb128(buffer, location - address); + address = location; + } + // Update length. + UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos); + } + buffer->push_back(0); // End of sections. +} + template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr> @@ -115,16 +149,13 @@ bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer); } - if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) { + if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() || + // ElfWriter::Fixup will be called regardless and it needs to be able + // to patch debug sections so we have to include patches for them. + compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) { ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches( - ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, sizeof(uintptr_t), sizeof(uintptr_t)); - const std::vector<uintptr_t>& locations = oat_writer->GetAbsolutePatchLocations(); - const uint8_t* begin = reinterpret_cast<const uint8_t*>(&locations[0]); - const uint8_t* end = begin + locations.size() * sizeof(locations[0]); - oat_patches.GetBuffer()->assign(begin, end); - if (debug) { - LOG(INFO) << "Prepared .oat_patches for " << locations.size() << " patches."; - } + ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, 1, 0); + EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer()); builder->RegisterRawSection(oat_patches); } |