1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_DEBUG_ELF_SYMTAB_WRITER_H_ 18 #define ART_COMPILER_DEBUG_ELF_SYMTAB_WRITER_H_ 19 20 #include <map> 21 #include <unordered_set> 22 23 #include "base/utils.h" 24 #include "debug/debug_info.h" 25 #include "debug/method_debug_info.h" 26 #include "dex/dex_file-inl.h" 27 #include "dex/code_item_accessors.h" 28 #include "elf/elf_builder.h" 29 30 namespace art { 31 namespace debug { 32 33 // The ARM specification defines three special mapping symbols 34 // $a, $t and $d which mark ARM, Thumb and data ranges respectively. 35 // These symbols can be used by tools, for example, to pretty 36 // print instructions correctly. Objdump will use them if they 37 // exist, but it will still work well without them. 38 // However, these extra symbols take space, so let's just generate 39 // one symbol which marks the whole .text section as code. 40 // Note that ARM's Streamline requires it to match function symbol. 41 constexpr bool kGenerateArmMappingSymbol = true; 42 43 // Magic name for .symtab symbols which enumerate dex files used 44 // by this ELF file (currently mmapped inside the .dex section). 45 constexpr const char* kDexFileSymbolName = "$dexfile"; 46 47 template <typename ElfTypes> 48 static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, 49 bool mini_debug_info, 50 const DebugInfo& debug_info) { 51 uint64_t mapping_symbol_address = std::numeric_limits<uint64_t>::max(); 52 const auto* text = builder->GetText(); 53 auto* strtab = builder->GetStrTab(); 54 auto* symtab = builder->GetSymTab(); 55 56 if (debug_info.Empty()) { 57 return; 58 } 59 60 // Find all addresses which contain deduped methods. 61 // The first instance of method is not marked deduped_, but the rest is. 62 std::unordered_set<uint64_t> deduped_addresses; 63 for (const MethodDebugInfo& info : debug_info.compiled_methods) { 64 if (info.deduped) { 65 deduped_addresses.insert(info.code_address); 66 } 67 if (kGenerateArmMappingSymbol && info.isa == InstructionSet::kThumb2) { 68 uint64_t address = info.code_address; 69 address += info.is_code_address_text_relative ? text->GetAddress() : 0; 70 mapping_symbol_address = std::min(mapping_symbol_address, address); 71 } 72 } 73 74 strtab->Start(); 75 strtab->Write(""); // strtab should start with empty string. 76 // Generate ARM mapping symbols. ELF local symbols must be added first. 77 if (mapping_symbol_address != std::numeric_limits<uint64_t>::max()) { 78 symtab->Add(strtab->Write("$t"), text, mapping_symbol_address, 0, STB_LOCAL, STT_NOTYPE); 79 } 80 // Add symbols for compiled methods. 81 for (const MethodDebugInfo& info : debug_info.compiled_methods) { 82 if (info.deduped) { 83 continue; // Add symbol only for the first instance. 84 } 85 size_t name_offset; 86 if (!info.custom_name.empty()) { 87 name_offset = strtab->Write(info.custom_name); 88 } else { 89 DCHECK(info.dex_file != nullptr); 90 std::string name = info.dex_file->PrettyMethod(info.dex_method_index, !mini_debug_info); 91 if (deduped_addresses.find(info.code_address) != deduped_addresses.end()) { 92 name += " [DEDUPED]"; 93 } 94 name_offset = strtab->Write(name); 95 } 96 97 uint64_t address = info.code_address; 98 address += info.is_code_address_text_relative ? text->GetAddress() : 0; 99 // Add in code delta, e.g., thumb bit 0 for Thumb2 code. 100 address += CompiledMethod::CodeDelta(info.isa); 101 symtab->Add(name_offset, text, address, info.code_size, STB_GLOBAL, STT_FUNC); 102 } 103 // Add symbols for dex files. 104 if (!debug_info.dex_files.empty() && builder->GetDex()->Exists()) { 105 auto dex = builder->GetDex(); 106 for (auto it : debug_info.dex_files) { 107 uint64_t dex_address = dex->GetAddress() + it.first /* offset within the section */; 108 const DexFile* dex_file = it.second; 109 typename ElfTypes::Word dex_name = strtab->Write(kDexFileSymbolName); 110 symtab->Add(dex_name, dex, dex_address, dex_file->Size(), STB_GLOBAL, STT_FUNC); 111 } 112 } 113 strtab->End(); 114 115 // Symbols are buffered and written after names (because they are smaller). 116 symtab->WriteCachedSection(); 117 } 118 119 } // namespace debug 120 } // namespace art 121 122 #endif // ART_COMPILER_DEBUG_ELF_SYMTAB_WRITER_H_ 123 124