summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/debug/elf_symtab_writer.h13
-rw-r--r--libelffile/elf/elf_builder.h20
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);
}