diff options
-rw-r--r-- | compiler/debug/elf_symtab_writer.h | 25 | ||||
-rw-r--r-- | compiler/linker/elf_builder.h | 9 |
2 files changed, 19 insertions, 15 deletions
diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h index 4b19547d28..1310e8dabd 100644 --- a/compiler/debug/elf_symtab_writer.h +++ b/compiler/debug/elf_symtab_writer.h @@ -37,7 +37,8 @@ namespace debug { // exist, but it will still work well without them. // However, these extra symbols take space, so let's just generate // one symbol which marks the whole .text section as code. -constexpr bool kGenerateSingleArmMappingSymbol = true; +// Note that ARM's Streamline requires it to match function symbol. +constexpr bool kGenerateArmMappingSymbol = true; // Magic name for .symtab symbols which enumerate dex files used // by this ELF file (currently mmapped inside the .dex section). @@ -48,6 +49,7 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, bool mini_debug_info, const DebugInfo& debug_info) { uint64_t mapping_symbol_address = std::numeric_limits<uint64_t>::max(); + const auto* text = builder->GetText(); auto* strtab = builder->GetStrTab(); auto* symtab = builder->GetSymTab(); @@ -62,10 +64,19 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, if (info.deduped) { deduped_addresses.insert(info.code_address); } + if (kGenerateArmMappingSymbol && info.isa == InstructionSet::kThumb2) { + uint64_t address = info.code_address; + address += info.is_code_address_text_relative ? text->GetAddress() : 0; + mapping_symbol_address = std::min(mapping_symbol_address, address); + } } strtab->Start(); strtab->Write(""); // strtab should start with empty string. + // 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); + } // Add symbols for compiled methods. for (const MethodDebugInfo& info : debug_info.compiled_methods) { if (info.deduped) { @@ -83,23 +94,11 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, name_offset = strtab->Write(name); } - const auto* text = builder->GetText(); uint64_t address = info.code_address; address += info.is_code_address_text_relative ? text->GetAddress() : 0; // Add in code delta, e.g., thumb bit 0 for Thumb2 code. address += CompiledMethod::CodeDelta(info.isa); symtab->Add(name_offset, text, address, info.code_size, STB_GLOBAL, STT_FUNC); - - // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2 - // instructions, so that disassembler tools can correctly disassemble. - // Note that even if we generate just a single mapping symbol, ARM's Streamline - // requires it to match function symbol. Just address 0 does not work. - if (info.isa == InstructionSet::kThumb2) { - if (address < mapping_symbol_address || !kGenerateSingleArmMappingSymbol) { - symtab->Add(strtab->Write("$t"), text, address & ~1, 0, STB_LOCAL, STT_NOTYPE); - mapping_symbol_address = address; - } - } } // Add symbols for dex files. if (!debug_info.dex_files.empty() && builder->GetDex()->Exists()) { diff --git a/compiler/linker/elf_builder.h b/compiler/linker/elf_builder.h index 3145497091..f4fcf49675 100644 --- a/compiler/linker/elf_builder.h +++ b/compiler/linker/elf_builder.h @@ -201,7 +201,7 @@ class ElfBuilder FINAL { return section_index_ != 0; } - private: + protected: // Add this section to the list of generated ELF sections (if not there already). // It also ensures the alignment is sufficient to generate valid program headers, // since that depends on the previous section. It returns the required alignment. @@ -345,7 +345,7 @@ class ElfBuilder FINAL { type, flags, strtab, - /* info */ 0, + /* info */ 1, sizeof(Elf_Off), sizeof(Elf_Sym)) { syms_.push_back(Elf_Sym()); // The symbol table always has to start with NULL symbol. @@ -386,6 +386,11 @@ class ElfBuilder FINAL { sym.st_shndx = section_index; sym.st_info = (binding << 4) + (type & 0xf); syms_.push_back(sym); + + // The sh_info file must be set to index one-past the last local symbol. + if (binding == STB_LOCAL) { + this->header_.sh_info = syms_.size(); + } } Elf_Word GetCacheSize() { return syms_.size() * sizeof(Elf_Sym); } |