diff options
| -rw-r--r-- | compiler/debug/elf_symtab_writer.h | 13 | ||||
| -rw-r--r-- | libelffile/elf/elf_builder.h | 20 |
2 files changed, 25 insertions, 8 deletions
diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h index ac8c8128c4..410f704582 100644 --- a/compiler/debug/elf_symtab_writer.h +++ b/compiler/debug/elf_symtab_writer.h @@ -42,6 +42,11 @@ namespace debug { // Note that ARM's Streamline requires it to match function symbol. constexpr bool kGenerateArmMappingSymbol = true; +// Create magic symbol to let libunwindstack know that symtab is sorted by address. +constexpr bool kGenerateSortedSymbol = true; +constexpr const char kSortedSymbolName[] = "$android.symtab.sorted"; +constexpr size_t kSortedSymbolMinCount = 100; // Don't bother if the table is very small (JIT). + // Magic name for .symtab symbols which enumerate dex files used // by this ELF file (currently mmapped inside the .dex section). constexpr const char* kDexFileSymbolName = "$dexfile"; @@ -116,10 +121,14 @@ static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, } strtab->Start(); - strtab->Write(""); // strtab should start with empty string. + // Generate marker to annotate the symbol table as sorted (guaranteed by the ElfBuilder). + // Note that LOCAL symbols are sorted before GLOBAL ones, so don't mix the two types. + if (kGenerateSortedSymbol && debug_info.compiled_methods.size() >= kSortedSymbolMinCount) { + symtab->Add(strtab->Write(kSortedSymbolName), nullptr, 0, 0, STB_GLOBAL, STT_NOTYPE); + } // Generate ARM mapping symbols. ELF local symbols must be added first. if (mapping_symbol_address != std::numeric_limits<uint64_t>::max()) { - symtab->Add(strtab->Write("$t"), text, mapping_symbol_address, 0, STB_LOCAL, STT_NOTYPE); + symtab->Add(strtab->Write("$t"), text, mapping_symbol_address, 0, STB_GLOBAL, STT_NOTYPE); } // Add symbols for compiled methods. for (const MethodDebugInfo& info : debug_info.compiled_methods) { diff --git a/libelffile/elf/elf_builder.h b/libelffile/elf/elf_builder.h index 4dde150697..086bd41b6e 100644 --- a/libelffile/elf/elf_builder.h +++ b/libelffile/elf/elf_builder.h @@ -130,7 +130,7 @@ class ElfBuilder final { } // Start writing file data of this section. - void Start() { + virtual void Start() { CHECK(owner_->current_section_ == nullptr); Elf_Word align = AddSection(); CHECK_EQ(header_.sh_offset, 0u); @@ -139,7 +139,7 @@ class ElfBuilder final { } // Finish writing file data of this section. - void End() { + virtual void End() { CHECK(owner_->current_section_ == this); Elf_Word position = GetPosition(); CHECK(header_.sh_size == 0u || header_.sh_size == position); @@ -310,6 +310,11 @@ class ElfBuilder final { last_offset_ = 0; } + void Start() { + Section::Start(); + Write(""); // ELF specification requires that the section starts with empty string. + } + Elf_Word Write(std::string_view name) { if (current_offset_ == 0) { DCHECK(name.empty()); @@ -368,10 +373,13 @@ class ElfBuilder final { // Buffer symbol for this section. It will be written later. void Add(Elf_Sym sym, const Section* section) { - DCHECK(section != nullptr); - DCHECK_LE(section->GetAddress(), sym.st_value); - DCHECK_LE(sym.st_value, section->GetAddress() + section->header_.sh_size); - sym.st_shndx = section->GetSectionIndex(); + if (section != nullptr) { + DCHECK_LE(section->GetAddress(), sym.st_value); + DCHECK_LE(sym.st_value, section->GetAddress() + section->header_.sh_size); + sym.st_shndx = section->GetSectionIndex(); + } else { + sym.st_shndx = SHN_UNDEF; + } syms_.push_back(sym); } |