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 #include "elf_debug_writer.h" 18 19 #include <type_traits> 20 #include <unordered_map> 21 #include <vector> 22 23 #include "base/array_ref.h" 24 #include "base/stl_util.h" 25 #include "debug/elf_compilation_unit.h" 26 #include "debug/elf_debug_frame_writer.h" 27 #include "debug/elf_debug_info_writer.h" 28 #include "debug/elf_debug_line_writer.h" 29 #include "debug/elf_debug_loc_writer.h" 30 #include "debug/elf_symtab_writer.h" 31 #include "debug/method_debug_info.h" 32 #include "dwarf/dwarf_constants.h" 33 #include "elf/elf_builder.h" 34 #include "elf/elf_debug_reader.h" 35 #include "elf/elf_utils.h" 36 #include "elf/xz_utils.h" 37 #include "oat.h" 38 #include "stream/vector_output_stream.h" 39 40 namespace art { 41 namespace debug { 42 43 using ElfRuntimeTypes = std::conditional<sizeof(void*) == 4, ElfTypes32, ElfTypes64>::type; 44 45 template <typename ElfTypes> 46 void WriteDebugInfo(ElfBuilder<ElfTypes>* builder, 47 const DebugInfo& debug_info) { 48 // Write .strtab and .symtab. 49 WriteDebugSymbols(builder, /* mini-debug-info= */ false, debug_info); 50 51 // Write .debug_frame. 52 WriteCFISection(builder, debug_info.compiled_methods); 53 54 // Group the methods into compilation units based on class. 55 std::unordered_map<const dex::ClassDef*, ElfCompilationUnit> class_to_compilation_unit; 56 for (const MethodDebugInfo& mi : debug_info.compiled_methods) { 57 if (mi.dex_file != nullptr) { 58 auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index); 59 ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def]; 60 cu.methods.push_back(&mi); 61 // All methods must have the same addressing mode otherwise the min/max below does not work. 62 DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative); 63 cu.is_code_address_text_relative = mi.is_code_address_text_relative; 64 cu.code_address = std::min(cu.code_address, mi.code_address); 65 cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size); 66 } 67 } 68 69 // Sort compilation units to make the compiler output deterministic. 70 std::vector<ElfCompilationUnit> compilation_units; 71 compilation_units.reserve(class_to_compilation_unit.size()); 72 for (auto& it : class_to_compilation_unit) { 73 // The .debug_line section requires the methods to be sorted by code address. 74 std::stable_sort(it.second.methods.begin(), 75 it.second.methods.end(), 76 [](const MethodDebugInfo* a, const MethodDebugInfo* b) { 77 return a->code_address < b->code_address; 78 }); 79 compilation_units.push_back(std::move(it.second)); 80 } 81 std::sort(compilation_units.begin(), 82 compilation_units.end(), 83 [](ElfCompilationUnit& a, ElfCompilationUnit& b) { 84 // Sort by index of the first method within the method_infos array. 85 // This assumes that the order of method_infos is deterministic. 86 // Code address is not good for sorting due to possible duplicates. 87 return a.methods.front() < b.methods.front(); 88 }); 89 90 // Write .debug_line section. 91 if (!compilation_units.empty()) { 92 ElfDebugLineWriter<ElfTypes> line_writer(builder); 93 line_writer.Start(); 94 for (auto& compilation_unit : compilation_units) { 95 line_writer.WriteCompilationUnit(compilation_unit); 96 } 97 line_writer.End(); 98 } 99 100 // Write .debug_info section. 101 if (!compilation_units.empty()) { 102 ElfDebugInfoWriter<ElfTypes> info_writer(builder); 103 info_writer.Start(); 104 for (const auto& compilation_unit : compilation_units) { 105 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer); 106 cu_writer.Write(compilation_unit); 107 } 108 info_writer.End(); 109 } 110 } 111 112 template <typename ElfTypes> 113 static std::vector<uint8_t> MakeMiniDebugInfoInternal( 114 InstructionSet isa, 115 const InstructionSetFeatures* features ATTRIBUTE_UNUSED, 116 typename ElfTypes::Addr text_section_address, 117 size_t text_section_size, 118 typename ElfTypes::Addr dex_section_address, 119 size_t dex_section_size, 120 const DebugInfo& debug_info) { 121 std::vector<uint8_t> buffer; 122 buffer.reserve(KB); 123 VectorOutputStream out("Mini-debug-info ELF file", &buffer); 124 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); 125 builder->Start(/* write_program_headers= */ false); 126 // Mirror ELF sections as NOBITS since the added symbols will reference them. 127 if (text_section_size != 0) { 128 builder->GetText()->AllocateVirtualMemory(text_section_address, text_section_size); 129 } 130 if (dex_section_size != 0) { 131 builder->GetDex()->AllocateVirtualMemory(dex_section_address, dex_section_size); 132 } 133 if (!debug_info.Empty()) { 134 WriteDebugSymbols(builder.get(), /* mini-debug-info= */ true, debug_info); 135 } 136 if (!debug_info.compiled_methods.empty()) { 137 WriteCFISection(builder.get(), debug_info.compiled_methods); 138 } 139 builder->End(); 140 CHECK(builder->Good()); 141 std::vector<uint8_t> compressed_buffer; 142 compressed_buffer.reserve(buffer.size() / 4); 143 XzCompress(ArrayRef<const uint8_t>(buffer), &compressed_buffer); 144 return compressed_buffer; 145 } 146 147 std::vector<uint8_t> MakeMiniDebugInfo( 148 InstructionSet isa, 149 const InstructionSetFeatures* features, 150 uint64_t text_section_address, 151 size_t text_section_size, 152 uint64_t dex_section_address, 153 size_t dex_section_size, 154 const DebugInfo& debug_info) { 155 if (Is64BitInstructionSet(isa)) { 156 return MakeMiniDebugInfoInternal<ElfTypes64>(isa, 157 features, 158 text_section_address, 159 text_section_size, 160 dex_section_address, 161 dex_section_size, 162 debug_info); 163 } else { 164 return MakeMiniDebugInfoInternal<ElfTypes32>(isa, 165 features, 166 text_section_address, 167 text_section_size, 168 dex_section_address, 169 dex_section_size, 170 debug_info); 171 } 172 } 173 174 std::vector<uint8_t> MakeElfFileForJIT( 175 InstructionSet isa, 176 const InstructionSetFeatures* features ATTRIBUTE_UNUSED, 177 bool mini_debug_info, 178 const MethodDebugInfo& method_info) { 179 using ElfTypes = ElfRuntimeTypes; 180 CHECK_EQ(sizeof(ElfTypes::Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa))); 181 CHECK_EQ(method_info.is_code_address_text_relative, false); 182 DebugInfo debug_info{}; 183 debug_info.compiled_methods = ArrayRef<const MethodDebugInfo>(&method_info, 1); 184 std::vector<uint8_t> buffer; 185 buffer.reserve(KB); 186 VectorOutputStream out("Debug ELF file", &buffer); 187 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); 188 // No program headers since the ELF file is not linked and has no allocated sections. 189 builder->Start(/* write_program_headers= */ false); 190 builder->GetText()->AllocateVirtualMemory(method_info.code_address, method_info.code_size); 191 if (mini_debug_info) { 192 // The compression is great help for multiple methods but it is not worth it for a 193 // single method due to the overheads so skip the compression here for performance. 194 WriteDebugSymbols(builder.get(), /* mini-debug-info= */ true, debug_info); 195 WriteCFISection(builder.get(), debug_info.compiled_methods); 196 } else { 197 WriteDebugInfo(builder.get(), debug_info); 198 } 199 builder->End(); 200 CHECK(builder->Good()); 201 // Verify the ELF file by reading it back using the trivial reader. 202 if (kIsDebugBuild) { 203 using Elf_Sym = typename ElfTypes::Sym; 204 size_t num_syms = 0; 205 size_t num_cies = 0; 206 size_t num_fdes = 0; 207 using Reader = ElfDebugReader<ElfTypes>; 208 Reader reader(buffer); 209 reader.VisitFunctionSymbols([&](Elf_Sym sym, const char*) { 210 DCHECK_EQ(sym.st_value, method_info.code_address + CompiledMethod::CodeDelta(isa)); 211 DCHECK_EQ(sym.st_size, method_info.code_size); 212 num_syms++; 213 }); 214 reader.VisitDebugFrame([&](const Reader::CIE* cie ATTRIBUTE_UNUSED) { 215 num_cies++; 216 }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) { 217 DCHECK_EQ(fde->sym_addr, method_info.code_address); 218 DCHECK_EQ(fde->sym_size, method_info.code_size); 219 num_fdes++; 220 }); 221 DCHECK_EQ(num_syms, 1u); 222 DCHECK_LE(num_cies, 1u); 223 DCHECK_LE(num_fdes, 1u); 224 } 225 return buffer; 226 } 227 228 // Combine several mini-debug-info ELF files into one, while filtering some symbols. 229 std::vector<uint8_t> PackElfFileForJIT( 230 InstructionSet isa, 231 const InstructionSetFeatures* features ATTRIBUTE_UNUSED, 232 std::vector<ArrayRef<const uint8_t>>& added_elf_files, 233 std::vector<const void*>& removed_symbols, 234 /*out*/ size_t* num_symbols) { 235 using ElfTypes = ElfRuntimeTypes; 236 using Elf_Addr = typename ElfTypes::Addr; 237 using Elf_Sym = typename ElfTypes::Sym; 238 CHECK_EQ(sizeof(Elf_Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa))); 239 auto is_removed_symbol = [&removed_symbols](Elf_Addr addr) { 240 const void* code_ptr = reinterpret_cast<const void*>(addr); 241 return std::binary_search(removed_symbols.begin(), removed_symbols.end(), code_ptr); 242 }; 243 uint64_t min_address = std::numeric_limits<uint64_t>::max(); 244 uint64_t max_address = 0; 245 246 // Produce the inner ELF file. 247 // It will contain the symbols (.symtab) and unwind information (.debug_frame). 248 std::vector<uint8_t> inner_elf_file; 249 { 250 inner_elf_file.reserve(1 * KB); // Approximate size of ELF file with a single symbol. 251 VectorOutputStream out("Mini-debug-info ELF file for JIT", &inner_elf_file); 252 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); 253 builder->Start(/*write_program_headers=*/ false); 254 auto* text = builder->GetText(); 255 auto* strtab = builder->GetStrTab(); 256 auto* symtab = builder->GetSymTab(); 257 auto* debug_frame = builder->GetDebugFrame(); 258 std::deque<Elf_Sym> symbols; 259 260 using Reader = ElfDebugReader<ElfTypes>; 261 std::deque<Reader> readers; 262 for (ArrayRef<const uint8_t> added_elf_file : added_elf_files) { 263 readers.emplace_back(added_elf_file); 264 } 265 266 // Write symbols names. All other data is buffered. 267 strtab->Start(); 268 strtab->Write(""); // strtab should start with empty string. 269 for (Reader& reader : readers) { 270 reader.VisitFunctionSymbols([&](Elf_Sym sym, const char* name) { 271 if (is_removed_symbol(sym.st_value)) { 272 return; 273 } 274 sym.st_name = strtab->Write(name); 275 symbols.push_back(sym); 276 min_address = std::min<uint64_t>(min_address, sym.st_value); 277 max_address = std::max<uint64_t>(max_address, sym.st_value + sym.st_size); 278 }); 279 } 280 strtab->End(); 281 282 // Create .text covering the code range. Needed for gdb to find the symbols. 283 if (max_address > min_address) { 284 text->AllocateVirtualMemory(min_address, max_address - min_address); 285 } 286 287 // Add the symbols. 288 *num_symbols = symbols.size(); 289 for (; !symbols.empty(); symbols.pop_front()) { 290 symtab->Add(symbols.front(), text); 291 } 292 symtab->WriteCachedSection(); 293 294 // Add the CFI/unwind section. 295 debug_frame->Start(); 296 // ART always produces the same CIE, so we copy the first one and ignore the rest. 297 bool copied_cie = false; 298 for (Reader& reader : readers) { 299 reader.VisitDebugFrame([&](const Reader::CIE* cie) { 300 if (!copied_cie) { 301 debug_frame->WriteFully(cie->data(), cie->size()); 302 copied_cie = true; 303 } 304 }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) { 305 DCHECK(copied_cie); 306 DCHECK_EQ(fde->cie_pointer, 0); 307 if (!is_removed_symbol(fde->sym_addr)) { 308 debug_frame->WriteFully(fde->data(), fde->size()); 309 } 310 }); 311 } 312 debug_frame->End(); 313 314 builder->End(); 315 CHECK(builder->Good()); 316 } 317 318 // Produce the outer ELF file. 319 // It contains only the inner ELF file compressed as .gnu_debugdata section. 320 // This extra wrapping is not necessary but the compression saves space. 321 std::vector<uint8_t> outer_elf_file; 322 { 323 std::vector<uint8_t> gnu_debugdata; 324 gnu_debugdata.reserve(inner_elf_file.size() / 4); 325 XzCompress(ArrayRef<const uint8_t>(inner_elf_file), &gnu_debugdata); 326 327 outer_elf_file.reserve(KB + gnu_debugdata.size()); 328 VectorOutputStream out("Mini-debug-info ELF file for JIT", &outer_elf_file); 329 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); 330 builder->Start(/*write_program_headers=*/ false); 331 if (max_address > min_address) { 332 builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address); 333 } 334 builder->WriteSection(".gnu_debugdata", &gnu_debugdata); 335 builder->End(); 336 CHECK(builder->Good()); 337 } 338 339 return outer_elf_file; 340 } 341 342 std::vector<uint8_t> WriteDebugElfFileForClasses( 343 InstructionSet isa, 344 const InstructionSetFeatures* features ATTRIBUTE_UNUSED, 345 const ArrayRef<mirror::Class*>& types) 346 REQUIRES_SHARED(Locks::mutator_lock_) { 347 using ElfTypes = ElfRuntimeTypes; 348 CHECK_EQ(sizeof(ElfTypes::Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa))); 349 std::vector<uint8_t> buffer; 350 buffer.reserve(KB); 351 VectorOutputStream out("Debug ELF file", &buffer); 352 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); 353 // No program headers since the ELF file is not linked and has no allocated sections. 354 builder->Start(/* write_program_headers= */ false); 355 ElfDebugInfoWriter<ElfTypes> info_writer(builder.get()); 356 info_writer.Start(); 357 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer); 358 cu_writer.Write(types); 359 info_writer.End(); 360 361 builder->End(); 362 CHECK(builder->Good()); 363 return buffer; 364 } 365 366 // Explicit instantiations 367 template void WriteDebugInfo<ElfTypes32>( 368 ElfBuilder<ElfTypes32>* builder, 369 const DebugInfo& debug_info); 370 template void WriteDebugInfo<ElfTypes64>( 371 ElfBuilder<ElfTypes64>* builder, 372 const DebugInfo& debug_info); 373 374 } // namespace debug 375 } // namespace art 376