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