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 <vector> 20 #include <unordered_map> 21 22 #include "base/array_ref.h" 23 #include "debug/dwarf/dwarf_constants.h" 24 #include "debug/elf_compilation_unit.h" 25 #include "debug/elf_debug_frame_writer.h" 26 #include "debug/elf_debug_info_writer.h" 27 #include "debug/elf_debug_line_writer.h" 28 #include "debug/elf_debug_loc_writer.h" 29 #include "debug/elf_gnu_debugdata_writer.h" 30 #include "debug/elf_symtab_writer.h" 31 #include "debug/method_debug_info.h" 32 #include "linker/elf_builder.h" 33 #include "linker/vector_output_stream.h" 34 #include "oat.h" 35 36 namespace art { 37 namespace debug { 38 39 template <typename ElfTypes> 40 void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder, 41 const DebugInfo& debug_info, 42 dwarf::CFIFormat cfi_format, 43 bool write_oat_patches) { 44 // Write .strtab and .symtab. 45 WriteDebugSymbols(builder, false /* mini-debug-info */, debug_info); 46 47 // Write .debug_frame. 48 WriteCFISection(builder, debug_info.compiled_methods, cfi_format, write_oat_patches); 49 50 // Group the methods into compilation units based on class. 51 std::unordered_map<const DexFile::ClassDef*, ElfCompilationUnit> class_to_compilation_unit; 52 for (const MethodDebugInfo& mi : debug_info.compiled_methods) { 53 if (mi.dex_file != nullptr) { 54 auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index); 55 ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def]; 56 cu.methods.push_back(&mi); 57 // All methods must have the same addressing mode otherwise the min/max below does not work. 58 DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative); 59 cu.is_code_address_text_relative = mi.is_code_address_text_relative; 60 cu.code_address = std::min(cu.code_address, mi.code_address); 61 cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size); 62 } 63 } 64 65 // Sort compilation units to make the compiler output deterministic. 66 std::vector<ElfCompilationUnit> compilation_units; 67 compilation_units.reserve(class_to_compilation_unit.size()); 68 for (auto& it : class_to_compilation_unit) { 69 // The .debug_line section requires the methods to be sorted by code address. 70 std::stable_sort(it.second.methods.begin(), 71 it.second.methods.end(), 72 [](const MethodDebugInfo* a, const MethodDebugInfo* b) { 73 return a->code_address < b->code_address; 74 }); 75 compilation_units.push_back(std::move(it.second)); 76 } 77 std::sort(compilation_units.begin(), 78 compilation_units.end(), 79 [](ElfCompilationUnit& a, ElfCompilationUnit& b) { 80 // Sort by index of the first method within the method_infos array. 81 // This assumes that the order of method_infos is deterministic. 82 // Code address is not good for sorting due to possible duplicates. 83 return a.methods.front() < b.methods.front(); 84 }); 85 86 // Write .debug_line section. 87 if (!compilation_units.empty()) { 88 ElfDebugLineWriter<ElfTypes> line_writer(builder); 89 line_writer.Start(); 90 for (auto& compilation_unit : compilation_units) { 91 line_writer.WriteCompilationUnit(compilation_unit); 92 } 93 line_writer.End(write_oat_patches); 94 } 95 96 // Write .debug_info section. 97 if (!compilation_units.empty()) { 98 ElfDebugInfoWriter<ElfTypes> info_writer(builder); 99 info_writer.Start(); 100 for (const auto& compilation_unit : compilation_units) { 101 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer); 102 cu_writer.Write(compilation_unit); 103 } 104 info_writer.End(write_oat_patches); 105 } 106 } 107 108 std::vector<uint8_t> MakeMiniDebugInfo( 109 InstructionSet isa, 110 const InstructionSetFeatures* features, 111 uint64_t text_section_address, 112 size_t text_section_size, 113 uint64_t dex_section_address, 114 size_t dex_section_size, 115 const DebugInfo& debug_info) { 116 if (Is64BitInstructionSet(isa)) { 117 return MakeMiniDebugInfoInternal<ElfTypes64>(isa, 118 features, 119 text_section_address, 120 text_section_size, 121 dex_section_address, 122 dex_section_size, 123 debug_info); 124 } else { 125 return MakeMiniDebugInfoInternal<ElfTypes32>(isa, 126 features, 127 text_section_address, 128 text_section_size, 129 dex_section_address, 130 dex_section_size, 131 debug_info); 132 } 133 } 134 135 template <typename ElfTypes> 136 static std::vector<uint8_t> MakeElfFileForJITInternal( 137 InstructionSet isa, 138 const InstructionSetFeatures* features, 139 bool mini_debug_info, 140 ArrayRef<const MethodDebugInfo> method_infos) { 141 CHECK_GT(method_infos.size(), 0u); 142 uint64_t min_address = std::numeric_limits<uint64_t>::max(); 143 uint64_t max_address = 0; 144 for (const MethodDebugInfo& mi : method_infos) { 145 CHECK_EQ(mi.is_code_address_text_relative, false); 146 min_address = std::min(min_address, mi.code_address); 147 max_address = std::max(max_address, mi.code_address + mi.code_size); 148 } 149 DebugInfo debug_info{}; 150 debug_info.compiled_methods = method_infos; 151 std::vector<uint8_t> buffer; 152 buffer.reserve(KB); 153 linker::VectorOutputStream out("Debug ELF file", &buffer); 154 std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder( 155 new linker::ElfBuilder<ElfTypes>(isa, features, &out)); 156 // No program headers since the ELF file is not linked and has no allocated sections. 157 builder->Start(false /* write_program_headers */); 158 if (mini_debug_info) { 159 if (method_infos.size() > 1) { 160 std::vector<uint8_t> mdi = MakeMiniDebugInfo(isa, 161 features, 162 min_address, 163 max_address - min_address, 164 /* dex_section_address */ 0, 165 /* dex_section_size */ 0, 166 debug_info); 167 builder->WriteSection(".gnu_debugdata", &mdi); 168 } else { 169 // The compression is great help for multiple methods but it is not worth it for a 170 // single method due to the overheads so skip the compression here for performance. 171 builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address); 172 WriteDebugSymbols(builder.get(), true /* mini-debug-info */, debug_info); 173 WriteCFISection(builder.get(), 174 debug_info.compiled_methods, 175 dwarf::DW_DEBUG_FRAME_FORMAT, 176 false /* write_oat_paches */); 177 } 178 } else { 179 builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address); 180 WriteDebugInfo(builder.get(), 181 debug_info, 182 dwarf::DW_DEBUG_FRAME_FORMAT, 183 false /* write_oat_patches */); 184 } 185 builder->End(); 186 CHECK(builder->Good()); 187 return buffer; 188 } 189 190 std::vector<uint8_t> MakeElfFileForJIT( 191 InstructionSet isa, 192 const InstructionSetFeatures* features, 193 bool mini_debug_info, 194 ArrayRef<const MethodDebugInfo> method_infos) { 195 if (Is64BitInstructionSet(isa)) { 196 return MakeElfFileForJITInternal<ElfTypes64>(isa, features, mini_debug_info, method_infos); 197 } else { 198 return MakeElfFileForJITInternal<ElfTypes32>(isa, features, mini_debug_info, method_infos); 199 } 200 } 201 202 template <typename ElfTypes> 203 static std::vector<uint8_t> WriteDebugElfFileForClassesInternal( 204 InstructionSet isa, 205 const InstructionSetFeatures* features, 206 const ArrayRef<mirror::Class*>& types) 207 REQUIRES_SHARED(Locks::mutator_lock_) { 208 std::vector<uint8_t> buffer; 209 buffer.reserve(KB); 210 linker::VectorOutputStream out("Debug ELF file", &buffer); 211 std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder( 212 new linker::ElfBuilder<ElfTypes>(isa, features, &out)); 213 // No program headers since the ELF file is not linked and has no allocated sections. 214 builder->Start(false /* write_program_headers */); 215 ElfDebugInfoWriter<ElfTypes> info_writer(builder.get()); 216 info_writer.Start(); 217 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer); 218 cu_writer.Write(types); 219 info_writer.End(false /* write_oat_patches */); 220 221 builder->End(); 222 CHECK(builder->Good()); 223 return buffer; 224 } 225 226 std::vector<uint8_t> WriteDebugElfFileForClasses(InstructionSet isa, 227 const InstructionSetFeatures* features, 228 const ArrayRef<mirror::Class*>& types) { 229 if (Is64BitInstructionSet(isa)) { 230 return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, features, types); 231 } else { 232 return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, features, types); 233 } 234 } 235 236 // Explicit instantiations 237 template void WriteDebugInfo<ElfTypes32>( 238 linker::ElfBuilder<ElfTypes32>* builder, 239 const DebugInfo& debug_info, 240 dwarf::CFIFormat cfi_format, 241 bool write_oat_patches); 242 template void WriteDebugInfo<ElfTypes64>( 243 linker::ElfBuilder<ElfTypes64>* builder, 244 const DebugInfo& debug_info, 245 dwarf::CFIFormat cfi_format, 246 bool write_oat_patches); 247 248 } // namespace debug 249 } // namespace art 250