blob: 5e2a8bf50ea70527d8703ec07b186ea972629e6d [file] [log] [blame]
David Srbecky3b9d57a2015-04-10 00:22:14 +01001/*
2 * Copyright (C) 2015 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_writer_debug.h"
18
David Srbecky626a1662015-04-12 13:12:26 +010019#include <unordered_set>
20
Andreas Gampee3d623e2015-05-01 16:11:04 -070021#include "base/casts.h"
David Srbecky04b05262015-11-09 18:05:48 +000022#include "base/stl_util.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010023#include "compiled_method.h"
24#include "driver/compiler_driver.h"
25#include "dex_file-inl.h"
David Srbecky04b05262015-11-09 18:05:48 +000026#include "dwarf/dedup_vector.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010027#include "dwarf/headers.h"
28#include "dwarf/register.h"
David Srbecky6d8c8f02015-10-26 10:57:09 +000029#include "elf_builder.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010030#include "oat_writer.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010031#include "utils.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010032
33namespace art {
34namespace dwarf {
35
David Srbecky6d8c8f02015-10-26 10:57:09 +000036static void WriteCIE(InstructionSet isa,
37 CFIFormat format,
38 std::vector<uint8_t>* buffer) {
David Srbecky3b9d57a2015-04-10 00:22:14 +010039 // Scratch registers should be marked as undefined. This tells the
40 // debugger that its value in the previous frame is not recoverable.
41 bool is64bit = Is64BitInstructionSet(isa);
42 switch (isa) {
43 case kArm:
44 case kThumb2: {
45 DebugFrameOpCodeWriter<> opcodes;
46 opcodes.DefCFA(Reg::ArmCore(13), 0); // R13(SP).
47 // core registers.
48 for (int reg = 0; reg < 13; reg++) {
49 if (reg < 4 || reg == 12) {
50 opcodes.Undefined(Reg::ArmCore(reg));
51 } else {
52 opcodes.SameValue(Reg::ArmCore(reg));
53 }
54 }
55 // fp registers.
56 for (int reg = 0; reg < 32; reg++) {
57 if (reg < 16) {
58 opcodes.Undefined(Reg::ArmFp(reg));
59 } else {
60 opcodes.SameValue(Reg::ArmFp(reg));
61 }
62 }
David Srbecky527c9c72015-04-17 21:14:10 +010063 auto return_reg = Reg::ArmCore(14); // R14(LR).
David Srbecky6d8c8f02015-10-26 10:57:09 +000064 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +010065 return;
66 }
67 case kArm64: {
68 DebugFrameOpCodeWriter<> opcodes;
69 opcodes.DefCFA(Reg::Arm64Core(31), 0); // R31(SP).
70 // core registers.
71 for (int reg = 0; reg < 30; reg++) {
72 if (reg < 8 || reg == 16 || reg == 17) {
73 opcodes.Undefined(Reg::Arm64Core(reg));
74 } else {
75 opcodes.SameValue(Reg::Arm64Core(reg));
76 }
77 }
78 // fp registers.
79 for (int reg = 0; reg < 32; reg++) {
80 if (reg < 8 || reg >= 16) {
81 opcodes.Undefined(Reg::Arm64Fp(reg));
82 } else {
83 opcodes.SameValue(Reg::Arm64Fp(reg));
84 }
85 }
David Srbecky527c9c72015-04-17 21:14:10 +010086 auto return_reg = Reg::Arm64Core(30); // R30(LR).
David Srbecky6d8c8f02015-10-26 10:57:09 +000087 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +010088 return;
89 }
90 case kMips:
91 case kMips64: {
92 DebugFrameOpCodeWriter<> opcodes;
93 opcodes.DefCFA(Reg::MipsCore(29), 0); // R29(SP).
94 // core registers.
95 for (int reg = 1; reg < 26; reg++) {
96 if (reg < 16 || reg == 24 || reg == 25) { // AT, V*, A*, T*.
97 opcodes.Undefined(Reg::MipsCore(reg));
98 } else {
99 opcodes.SameValue(Reg::MipsCore(reg));
100 }
101 }
David Srbecky527c9c72015-04-17 21:14:10 +0100102 auto return_reg = Reg::MipsCore(31); // R31(RA).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000103 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100104 return;
105 }
106 case kX86: {
David Srbecky8a813f72015-04-20 16:43:52 +0100107 // FIXME: Add fp registers once libunwind adds support for them. Bug: 20491296
108 constexpr bool generate_opcodes_for_x86_fp = false;
David Srbecky3b9d57a2015-04-10 00:22:14 +0100109 DebugFrameOpCodeWriter<> opcodes;
110 opcodes.DefCFA(Reg::X86Core(4), 4); // R4(ESP).
111 opcodes.Offset(Reg::X86Core(8), -4); // R8(EIP).
112 // core registers.
113 for (int reg = 0; reg < 8; reg++) {
114 if (reg <= 3) {
115 opcodes.Undefined(Reg::X86Core(reg));
116 } else if (reg == 4) {
117 // Stack pointer.
118 } else {
119 opcodes.SameValue(Reg::X86Core(reg));
120 }
121 }
122 // fp registers.
David Srbecky8a813f72015-04-20 16:43:52 +0100123 if (generate_opcodes_for_x86_fp) {
124 for (int reg = 0; reg < 8; reg++) {
125 opcodes.Undefined(Reg::X86Fp(reg));
126 }
David Srbecky3b9d57a2015-04-10 00:22:14 +0100127 }
David Srbecky527c9c72015-04-17 21:14:10 +0100128 auto return_reg = Reg::X86Core(8); // R8(EIP).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000129 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100130 return;
131 }
132 case kX86_64: {
133 DebugFrameOpCodeWriter<> opcodes;
134 opcodes.DefCFA(Reg::X86_64Core(4), 8); // R4(RSP).
135 opcodes.Offset(Reg::X86_64Core(16), -8); // R16(RIP).
136 // core registers.
137 for (int reg = 0; reg < 16; reg++) {
138 if (reg == 4) {
139 // Stack pointer.
140 } else if (reg < 12 && reg != 3 && reg != 5) { // except EBX and EBP.
141 opcodes.Undefined(Reg::X86_64Core(reg));
142 } else {
143 opcodes.SameValue(Reg::X86_64Core(reg));
144 }
145 }
146 // fp registers.
147 for (int reg = 0; reg < 16; reg++) {
148 if (reg < 12) {
149 opcodes.Undefined(Reg::X86_64Fp(reg));
150 } else {
151 opcodes.SameValue(Reg::X86_64Fp(reg));
152 }
153 }
David Srbecky527c9c72015-04-17 21:14:10 +0100154 auto return_reg = Reg::X86_64Core(16); // R16(RIP).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000155 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100156 return;
157 }
158 case kNone:
159 break;
160 }
161 LOG(FATAL) << "Can not write CIE frame for ISA " << isa;
162 UNREACHABLE();
163}
164
David Srbecky6d8c8f02015-10-26 10:57:09 +0000165template<typename ElfTypes>
166void WriteCFISection(ElfBuilder<ElfTypes>* builder,
167 const std::vector<OatWriter::DebugInfo>& method_infos,
168 CFIFormat format) {
169 CHECK(format == dwarf::DW_DEBUG_FRAME_FORMAT ||
170 format == dwarf::DW_EH_FRAME_FORMAT);
171 typedef typename ElfTypes::Addr Elf_Addr;
172
173 std::vector<uint32_t> binary_search_table;
174 std::vector<uintptr_t> patch_locations;
175 if (format == DW_EH_FRAME_FORMAT) {
176 binary_search_table.reserve(2 * method_infos.size());
177 } else {
178 patch_locations.reserve(method_infos.size());
179 }
David Srbecky527c9c72015-04-17 21:14:10 +0100180
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100181 // Write .eh_frame/.debug_frame section.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000182 auto* cfi_section = (format == dwarf::DW_DEBUG_FRAME_FORMAT
183 ? builder->GetDebugFrame()
184 : builder->GetEhFrame());
185 {
186 cfi_section->Start();
187 const bool is64bit = Is64BitInstructionSet(builder->GetIsa());
188 const Elf_Addr text_address = builder->GetText()->GetAddress();
189 const Elf_Addr cfi_address = cfi_section->GetAddress();
190 const Elf_Addr cie_address = cfi_address;
191 Elf_Addr buffer_address = cfi_address;
192 std::vector<uint8_t> buffer; // Small temporary buffer.
193 WriteCIE(builder->GetIsa(), format, &buffer);
194 cfi_section->WriteFully(buffer.data(), buffer.size());
195 buffer_address += buffer.size();
196 buffer.clear();
197 for (const OatWriter::DebugInfo& mi : method_infos) {
198 if (!mi.deduped_) { // Only one FDE per unique address.
199 ArrayRef<const uint8_t> opcodes = mi.compiled_method_->GetCFIInfo();
200 if (!opcodes.empty()) {
201 const Elf_Addr code_address = text_address + mi.low_pc_;
202 if (format == DW_EH_FRAME_FORMAT) {
203 binary_search_table.push_back(
204 dchecked_integral_cast<uint32_t>(code_address));
205 binary_search_table.push_back(
206 dchecked_integral_cast<uint32_t>(buffer_address));
207 }
208 WriteFDE(is64bit, cfi_address, cie_address,
209 code_address, mi.high_pc_ - mi.low_pc_,
210 opcodes, format, buffer_address, &buffer,
211 &patch_locations);
212 cfi_section->WriteFully(buffer.data(), buffer.size());
213 buffer_address += buffer.size();
214 buffer.clear();
215 }
David Srbecky6d73c9d2015-05-01 15:00:40 +0100216 }
David Srbecky8dc73242015-04-12 11:40:39 +0100217 }
David Srbecky6d8c8f02015-10-26 10:57:09 +0000218 cfi_section->End();
David Srbecky8dc73242015-04-12 11:40:39 +0100219 }
David Srbecky527c9c72015-04-17 21:14:10 +0100220
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100221 if (format == DW_EH_FRAME_FORMAT) {
David Srbecky6d8c8f02015-10-26 10:57:09 +0000222 auto* header_section = builder->GetEhFrameHdr();
223 header_section->Start();
224 uint32_t header_address = dchecked_integral_cast<int32_t>(header_section->GetAddress());
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100225 // Write .eh_frame_hdr section.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000226 std::vector<uint8_t> buffer;
227 Writer<> header(&buffer);
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100228 header.PushUint8(1); // Version.
229 // Encoding of .eh_frame pointer - libunwind does not honor datarel here,
230 // so we have to use pcrel which means relative to the pointer's location.
231 header.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
232 // Encoding of binary search table size.
233 header.PushUint8(DW_EH_PE_udata4);
234 // Encoding of binary search table addresses - libunwind supports only this
235 // specific combination, which means relative to the start of .eh_frame_hdr.
236 header.PushUint8(DW_EH_PE_datarel | DW_EH_PE_sdata4);
David Srbecky6d8c8f02015-10-26 10:57:09 +0000237 // .eh_frame pointer
238 header.PushInt32(cfi_section->GetAddress() - (header_address + 4u));
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100239 // Binary search table size (number of entries).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000240 header.PushUint32(dchecked_integral_cast<uint32_t>(binary_search_table.size()/2));
241 header_section->WriteFully(buffer.data(), buffer.size());
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100242 // Binary search table.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000243 for (size_t i = 0; i < binary_search_table.size(); i++) {
244 // Make addresses section-relative since we know the header address now.
245 binary_search_table[i] -= header_address;
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100246 }
David Srbecky6d8c8f02015-10-26 10:57:09 +0000247 header_section->WriteFully(binary_search_table.data(), binary_search_table.size());
248 header_section->End();
249 } else {
250 builder->WritePatches(".debug_frame.oat_patches", &patch_locations);
David Srbecky033d7452015-04-30 19:57:35 +0100251 }
David Srbecky8dc73242015-04-12 11:40:39 +0100252}
253
David Srbecky04b05262015-11-09 18:05:48 +0000254struct CompilationUnit {
255 std::vector<const OatWriter::DebugInfo*> methods_;
256 size_t debug_line_offset_ = 0;
257 uint32_t low_pc_ = 0xFFFFFFFFU;
258 uint32_t high_pc_ = 0;
259};
260
261// Helper class to write .debug_info and its supporting sections.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000262template<typename ElfTypes>
David Srbeckyb851b492015-11-11 20:19:38 +0000263class DebugInfoWriter {
David Srbecky6d8c8f02015-10-26 10:57:09 +0000264 typedef typename ElfTypes::Addr Elf_Addr;
David Srbecky3b9d57a2015-04-10 00:22:14 +0100265
David Srbecky04b05262015-11-09 18:05:48 +0000266 // Helper class to write one compilation unit.
267 // It holds helper methods and temporary state.
268 class CompilationUnitWriter {
269 public:
270 explicit CompilationUnitWriter(DebugInfoWriter* owner)
271 : owner_(owner),
272 info_(Is64BitInstructionSet(owner_->builder_->GetIsa()), &debug_abbrev_) {
273 }
274
275 void Write(const CompilationUnit& compilation_unit) {
276 CHECK(!compilation_unit.methods_.empty());
277 const Elf_Addr text_address = owner_->builder_->GetText()->GetAddress();
278
279 info_.StartTag(DW_TAG_compile_unit);
280 info_.WriteStrp(DW_AT_producer, owner_->WriteString("Android dex2oat"));
281 info_.WriteData1(DW_AT_language, DW_LANG_Java);
282 info_.WriteAddr(DW_AT_low_pc, text_address + compilation_unit.low_pc_);
283 info_.WriteAddr(DW_AT_high_pc, text_address + compilation_unit.high_pc_);
284 info_.WriteData4(DW_AT_stmt_list, compilation_unit.debug_line_offset_);
285
286 const char* last_dex_class_desc = nullptr;
287 for (auto mi : compilation_unit.methods_) {
288 const DexFile* dex = mi->dex_file_;
289 const DexFile::MethodId& dex_method = dex->GetMethodId(mi->dex_method_index_);
290 const DexFile::ProtoId& dex_proto = dex->GetMethodPrototype(dex_method);
291 const DexFile::TypeList* dex_params = dex->GetProtoParameters(dex_proto);
292 const char* dex_class_desc = dex->GetMethodDeclaringClassDescriptor(dex_method);
293
294 // Enclose the method in correct class definition.
295 if (last_dex_class_desc != dex_class_desc) {
296 if (last_dex_class_desc != nullptr) {
297 EndClassTag(last_dex_class_desc);
298 }
299 size_t offset = StartClassTag(dex_class_desc);
300 type_cache_.emplace(dex_class_desc, offset);
301 // Check that each class is defined only once.
302 bool unique = owner_->defined_dex_classes_.insert(dex_class_desc).second;
303 CHECK(unique) << "Redefinition of " << dex_class_desc;
304 last_dex_class_desc = dex_class_desc;
305 }
306
307 std::vector<const char*> param_names;
308 if (mi->code_item_ != nullptr) {
309 const uint8_t* stream = dex->GetDebugInfoStream(mi->code_item_);
310 if (stream != nullptr) {
311 DecodeUnsignedLeb128(&stream); // line.
312 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
313 for (uint32_t i = 0; i < parameters_size; ++i) {
314 uint32_t id = DecodeUnsignedLeb128P1(&stream);
315 param_names.push_back(mi->dex_file_->StringDataByIdx(id));
316 }
317 }
318 }
319
320 int start_depth = info_.Depth();
321 info_.StartTag(DW_TAG_subprogram);
322 WriteName(dex->GetMethodName(dex_method));
323 info_.WriteAddr(DW_AT_low_pc, text_address + mi->low_pc_);
324 info_.WriteAddr(DW_AT_high_pc, text_address + mi->high_pc_);
325 WriteLazyType(dex->GetReturnTypeDescriptor(dex_proto));
326 if (dex_params != nullptr) {
327 for (uint32_t i = 0; i < dex_params->Size(); ++i) {
328 info_.StartTag(DW_TAG_formal_parameter);
329 // Parameter names may not be always available.
330 if (i < param_names.size() && param_names[i] != nullptr) {
331 WriteName(param_names[i]);
332 }
333 WriteLazyType(dex->StringByTypeIdx(dex_params->GetTypeItem(i).type_idx_));
334 info_.EndTag();
335 }
336 }
337 info_.EndTag();
338 CHECK_EQ(info_.Depth(), start_depth); // Balanced start/end.
339 }
340 if (last_dex_class_desc != nullptr) {
341 EndClassTag(last_dex_class_desc);
342 }
343 CHECK_EQ(info_.Depth(), 1);
344 FinishLazyTypes();
345 info_.EndTag(); // DW_TAG_compile_unit
346 std::vector<uint8_t> buffer;
347 buffer.reserve(info_.data()->size() + KB);
348 const size_t offset = owner_->builder_->GetDebugInfo()->GetSize();
349 const size_t debug_abbrev_offset =
350 owner_->debug_abbrev_.Insert(debug_abbrev_.data(), debug_abbrev_.size());
351 WriteDebugInfoCU(debug_abbrev_offset, info_, offset, &buffer, &owner_->debug_info_patches_);
352 owner_->builder_->GetDebugInfo()->WriteFully(buffer.data(), buffer.size());
353 }
354
355 // Some types are difficult to define as we go since they need
356 // to be enclosed in the right set of namespaces. Therefore we
357 // just define all types lazily at the end of compilation unit.
358 void WriteLazyType(const char* type_descriptor) {
359 DCHECK(type_descriptor != nullptr);
360 if (type_descriptor[0] != 'V') {
361 lazy_types_.emplace(type_descriptor, info_.size());
362 info_.WriteRef4(DW_AT_type, 0);
363 }
364 }
365
366 void FinishLazyTypes() {
367 for (const auto& lazy_type : lazy_types_) {
368 info_.UpdateUint32(lazy_type.second, WriteType(lazy_type.first));
369 }
370 lazy_types_.clear();
371 }
372
373 private:
374 void WriteName(const char* name) {
375 info_.WriteStrp(DW_AT_name, owner_->WriteString(name));
376 }
377
378 // Convert dex type descriptor to DWARF.
379 // Returns offset in the compilation unit.
380 size_t WriteType(const char* desc) {
381 const auto& it = type_cache_.find(desc);
382 if (it != type_cache_.end()) {
383 return it->second;
384 }
385
386 size_t offset;
387 if (*desc == 'L') {
388 // Class type. For example: Lpackage/name;
389 offset = StartClassTag(desc);
390 info_.WriteFlag(DW_AT_declaration, true);
391 EndClassTag(desc);
392 } else if (*desc == '[') {
393 // Array type.
394 size_t element_type = WriteType(desc + 1);
395 offset = info_.StartTag(DW_TAG_array_type);
396 info_.WriteRef(DW_AT_type, element_type);
397 info_.EndTag();
398 } else {
399 // Primitive types.
400 const char* name;
401 switch (*desc) {
402 case 'B': name = "byte"; break;
403 case 'C': name = "char"; break;
404 case 'D': name = "double"; break;
405 case 'F': name = "float"; break;
406 case 'I': name = "int"; break;
407 case 'J': name = "long"; break;
408 case 'S': name = "short"; break;
409 case 'Z': name = "boolean"; break;
410 case 'V': name = "void"; break;
411 default:
412 LOG(FATAL) << "Unknown dex type descriptor: " << desc;
413 UNREACHABLE();
414 }
415 offset = info_.StartTag(DW_TAG_base_type);
416 WriteName(name);
417 info_.EndTag();
418 }
419
420 type_cache_.emplace(desc, offset);
421 return offset;
422 }
423
424 // Start DW_TAG_class_type tag nested in DW_TAG_namespace tags.
425 // Returns offset of the class tag in the compilation unit.
426 size_t StartClassTag(const char* desc) {
427 DCHECK(desc != nullptr && desc[0] == 'L');
428 // Enclose the type in namespace tags.
429 const char* end;
430 for (desc = desc + 1; (end = strchr(desc, '/')) != nullptr; desc = end + 1) {
431 info_.StartTag(DW_TAG_namespace);
432 WriteName(std::string(desc, end - desc).c_str());
433 }
434 // Start the class tag.
435 size_t offset = info_.StartTag(DW_TAG_class_type);
436 end = strchr(desc, ';');
437 CHECK(end != nullptr);
438 WriteName(std::string(desc, end - desc).c_str());
439 return offset;
440 }
441
442 void EndClassTag(const char* desc) {
443 DCHECK(desc != nullptr && desc[0] == 'L');
444 // End the class tag.
445 info_.EndTag();
446 // Close namespace tags.
447 const char* end;
448 for (desc = desc + 1; (end = strchr(desc, '/')) != nullptr; desc = end + 1) {
449 info_.EndTag();
450 }
451 }
452
453 // For access to the ELF sections.
454 DebugInfoWriter<ElfTypes>* owner_;
455 // Debug abbrevs for this compilation unit only.
456 std::vector<uint8_t> debug_abbrev_;
457 // Temporary buffer to create and store the entries.
458 DebugInfoEntryWriter<> info_;
459 // Cache of already translated type descriptors.
460 std::map<const char*, size_t, CStringLess> type_cache_; // type_desc -> definition_offset.
461 // 32-bit references which need to be resolved to a type later.
462 std::multimap<const char*, size_t, CStringLess> lazy_types_; // type_desc -> patch_offset.
463 };
464
David Srbeckyb851b492015-11-11 20:19:38 +0000465 public:
466 explicit DebugInfoWriter(ElfBuilder<ElfTypes>* builder) : builder_(builder) {
David Srbecky626a1662015-04-12 13:12:26 +0100467 }
468
David Srbeckyb851b492015-11-11 20:19:38 +0000469 void Start() {
470 builder_->GetDebugInfo()->Start();
David Srbecky799b8c42015-04-14 01:57:43 +0100471 }
472
David Srbecky04b05262015-11-09 18:05:48 +0000473 void WriteCompilationUnit(const CompilationUnit& compilation_unit) {
474 CompilationUnitWriter writer(this);
475 writer.Write(compilation_unit);
David Srbeckyb851b492015-11-11 20:19:38 +0000476 }
David Srbecky3b9d57a2015-04-10 00:22:14 +0100477
David Srbeckyb851b492015-11-11 20:19:38 +0000478 void End() {
479 builder_->GetDebugInfo()->End();
480 builder_->WritePatches(".debug_info.oat_patches", &debug_info_patches_);
David Srbecky04b05262015-11-09 18:05:48 +0000481 builder_->WriteSection(".debug_abbrev", &debug_abbrev_.Data());
482 builder_->WriteSection(".debug_str", &debug_str_.Data());
David Srbeckyb851b492015-11-11 20:19:38 +0000483 }
484
485 private:
David Srbecky04b05262015-11-09 18:05:48 +0000486 size_t WriteString(const char* str) {
487 return debug_str_.Insert(reinterpret_cast<const uint8_t*>(str), strlen(str) + 1);
488 }
489
David Srbeckyb851b492015-11-11 20:19:38 +0000490 ElfBuilder<ElfTypes>* builder_;
491 std::vector<uintptr_t> debug_info_patches_;
David Srbecky04b05262015-11-09 18:05:48 +0000492 DedupVector debug_abbrev_;
493 DedupVector debug_str_;
494
495 std::unordered_set<const char*> defined_dex_classes_; // For CHECKs only.
David Srbeckyb851b492015-11-11 20:19:38 +0000496};
497
498template<typename ElfTypes>
499class DebugLineWriter {
500 typedef typename ElfTypes::Addr Elf_Addr;
501
502 public:
503 explicit DebugLineWriter(ElfBuilder<ElfTypes>* builder) : builder_(builder) {
504 }
505
506 void Start() {
507 builder_->GetDebugLine()->Start();
508 }
509
510 // Write line table for given set of methods.
511 // Returns the number of bytes written.
David Srbecky04b05262015-11-09 18:05:48 +0000512 size_t WriteCompilationUnit(CompilationUnit& compilation_unit) {
David Srbeckyb851b492015-11-11 20:19:38 +0000513 const bool is64bit = Is64BitInstructionSet(builder_->GetIsa());
514 const Elf_Addr text_address = builder_->GetText()->GetAddress();
David Srbecky04b05262015-11-09 18:05:48 +0000515
516 compilation_unit.debug_line_offset_ = builder_->GetDebugLine()->GetSize();
David Srbeckyb851b492015-11-11 20:19:38 +0000517
David Srbecky799b8c42015-04-14 01:57:43 +0100518 std::vector<FileEntry> files;
519 std::unordered_map<std::string, size_t> files_map;
520 std::vector<std::string> directories;
521 std::unordered_map<std::string, size_t> directories_map;
522 int code_factor_bits_ = 0;
523 int dwarf_isa = -1;
David Srbeckyb851b492015-11-11 20:19:38 +0000524 switch (builder_->GetIsa()) {
David Srbecky799b8c42015-04-14 01:57:43 +0100525 case kArm: // arm actually means thumb2.
526 case kThumb2:
527 code_factor_bits_ = 1; // 16-bit instuctions
528 dwarf_isa = 1; // DW_ISA_ARM_thumb.
529 break;
530 case kArm64:
531 case kMips:
532 case kMips64:
533 code_factor_bits_ = 2; // 32-bit instructions
534 break;
535 case kNone:
536 case kX86:
537 case kX86_64:
538 break;
539 }
David Srbecky297ed222015-04-15 01:18:12 +0100540 DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits_);
David Srbecky04b05262015-11-09 18:05:48 +0000541 opcodes.SetAddress(text_address + compilation_unit.low_pc_);
David Srbecky799b8c42015-04-14 01:57:43 +0100542 if (dwarf_isa != -1) {
543 opcodes.SetISA(dwarf_isa);
544 }
David Srbecky04b05262015-11-09 18:05:48 +0000545 for (const OatWriter::DebugInfo* mi : compilation_unit.methods_) {
546 // Ignore function if we have already generated line table for the same address.
547 // It would confuse the debugger and the DWARF specification forbids it.
548 if (mi->deduped_) {
549 continue;
550 }
551
David Srbecky799b8c42015-04-14 01:57:43 +0100552 struct DebugInfoCallbacks {
553 static bool NewPosition(void* ctx, uint32_t address, uint32_t line) {
554 auto* context = reinterpret_cast<DebugInfoCallbacks*>(ctx);
555 context->dex2line_.push_back({address, static_cast<int32_t>(line)});
556 return false;
David Srbecky3b9d57a2015-04-10 00:22:14 +0100557 }
David Srbecky799b8c42015-04-14 01:57:43 +0100558 DefaultSrcMap dex2line_;
559 } debug_info_callbacks;
560
David Srbecky6d8c8f02015-10-26 10:57:09 +0000561 Elf_Addr method_address = text_address + mi->low_pc_;
562
David Srbecky799b8c42015-04-14 01:57:43 +0100563 const DexFile* dex = mi->dex_file_;
564 if (mi->code_item_ != nullptr) {
565 dex->DecodeDebugInfo(mi->code_item_,
566 (mi->access_flags_ & kAccStatic) != 0,
567 mi->dex_method_index_,
568 DebugInfoCallbacks::NewPosition,
569 nullptr,
570 &debug_info_callbacks);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100571 }
572
David Srbecky799b8c42015-04-14 01:57:43 +0100573 // Get and deduplicate directory and filename.
574 int file_index = 0; // 0 - primary source file of the compilation.
575 auto& dex_class_def = dex->GetClassDef(mi->class_def_index_);
576 const char* source_file = dex->GetSourceFile(dex_class_def);
577 if (source_file != nullptr) {
578 std::string file_name(source_file);
579 size_t file_name_slash = file_name.find_last_of('/');
580 std::string class_name(dex->GetClassDescriptor(dex_class_def));
581 size_t class_name_slash = class_name.find_last_of('/');
582 std::string full_path(file_name);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100583
David Srbecky799b8c42015-04-14 01:57:43 +0100584 // Guess directory from package name.
585 int directory_index = 0; // 0 - current directory of the compilation.
586 if (file_name_slash == std::string::npos && // Just filename.
587 class_name.front() == 'L' && // Type descriptor for a class.
588 class_name_slash != std::string::npos) { // Has package name.
589 std::string package_name = class_name.substr(1, class_name_slash - 1);
590 auto it = directories_map.find(package_name);
591 if (it == directories_map.end()) {
592 directory_index = 1 + directories.size();
593 directories_map.emplace(package_name, directory_index);
594 directories.push_back(package_name);
595 } else {
596 directory_index = it->second;
597 }
598 full_path = package_name + "/" + file_name;
599 }
600
601 // Add file entry.
602 auto it2 = files_map.find(full_path);
603 if (it2 == files_map.end()) {
604 file_index = 1 + files.size();
605 files_map.emplace(full_path, file_index);
606 files.push_back(FileEntry {
607 file_name,
608 directory_index,
609 0, // Modification time - NA.
610 0, // File size - NA.
611 });
612 } else {
613 file_index = it2->second;
614 }
615 }
616 opcodes.SetFile(file_index);
617
618 // Generate mapping opcodes from PC to Java lines.
619 const DefaultSrcMap& dex2line_map = debug_info_callbacks.dex2line_;
David Srbecky799b8c42015-04-14 01:57:43 +0100620 if (file_index != 0 && !dex2line_map.empty()) {
621 bool first = true;
622 for (SrcMapElem pc2dex : mi->compiled_method_->GetSrcMappingTable()) {
623 uint32_t pc = pc2dex.from_;
624 int dex_pc = pc2dex.to_;
625 auto dex2line = dex2line_map.Find(static_cast<uint32_t>(dex_pc));
626 if (dex2line.first) {
627 int line = dex2line.second;
628 if (first) {
629 first = false;
630 if (pc > 0) {
631 // Assume that any preceding code is prologue.
632 int first_line = dex2line_map.front().to_;
633 // Prologue is not a sensible place for a breakpoint.
634 opcodes.NegateStmt();
David Srbecky6d8c8f02015-10-26 10:57:09 +0000635 opcodes.AddRow(method_address, first_line);
David Srbecky799b8c42015-04-14 01:57:43 +0100636 opcodes.NegateStmt();
637 opcodes.SetPrologueEnd();
638 }
David Srbecky6d8c8f02015-10-26 10:57:09 +0000639 opcodes.AddRow(method_address + pc, line);
David Srbecky799b8c42015-04-14 01:57:43 +0100640 } else if (line != opcodes.CurrentLine()) {
David Srbecky6d8c8f02015-10-26 10:57:09 +0000641 opcodes.AddRow(method_address + pc, line);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100642 }
David Srbecky3b9d57a2015-04-10 00:22:14 +0100643 }
644 }
David Srbecky799b8c42015-04-14 01:57:43 +0100645 } else {
646 // line 0 - instruction cannot be attributed to any source line.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000647 opcodes.AddRow(method_address, 0);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100648 }
David Srbecky3b9d57a2015-04-10 00:22:14 +0100649 }
David Srbecky04b05262015-11-09 18:05:48 +0000650 opcodes.AdvancePC(text_address + compilation_unit.high_pc_);
David Srbecky799b8c42015-04-14 01:57:43 +0100651 opcodes.EndSequence();
David Srbeckyb851b492015-11-11 20:19:38 +0000652 std::vector<uint8_t> buffer;
653 buffer.reserve(opcodes.data()->size() + KB);
654 size_t offset = builder_->GetDebugLine()->GetSize();
655 WriteDebugLineTable(directories, files, opcodes, offset, &buffer, &debug_line_patches);
656 builder_->GetDebugLine()->WriteFully(buffer.data(), buffer.size());
657 return buffer.size();
David Srbecky3b9d57a2015-04-10 00:22:14 +0100658 }
David Srbeckyb851b492015-11-11 20:19:38 +0000659
660 void End() {
661 builder_->GetDebugLine()->End();
662 builder_->WritePatches(".debug_line.oat_patches", &debug_line_patches);
663 }
664
665 private:
666 ElfBuilder<ElfTypes>* builder_;
667 std::vector<uintptr_t> debug_line_patches;
668};
669
670template<typename ElfTypes>
671void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
672 const std::vector<OatWriter::DebugInfo>& method_infos) {
David Srbeckyb851b492015-11-11 20:19:38 +0000673 // Group the methods into compilation units based on source file.
674 std::vector<CompilationUnit> compilation_units;
675 const char* last_source_file = nullptr;
676 for (const OatWriter::DebugInfo& mi : method_infos) {
David Srbecky04b05262015-11-09 18:05:48 +0000677 auto& dex_class_def = mi.dex_file_->GetClassDef(mi.class_def_index_);
678 const char* source_file = mi.dex_file_->GetSourceFile(dex_class_def);
679 if (compilation_units.empty() || source_file != last_source_file) {
680 compilation_units.push_back(CompilationUnit());
David Srbeckyb851b492015-11-11 20:19:38 +0000681 }
David Srbecky04b05262015-11-09 18:05:48 +0000682 CompilationUnit& cu = compilation_units.back();
683 cu.methods_.push_back(&mi);
684 cu.low_pc_ = std::min(cu.low_pc_, mi.low_pc_);
685 cu.high_pc_ = std::max(cu.high_pc_, mi.high_pc_);
686 last_source_file = source_file;
David Srbeckyb851b492015-11-11 20:19:38 +0000687 }
688
689 // Write .debug_line section.
690 {
691 DebugLineWriter<ElfTypes> line_writer(builder);
692 line_writer.Start();
David Srbeckyb851b492015-11-11 20:19:38 +0000693 for (auto& compilation_unit : compilation_units) {
David Srbecky04b05262015-11-09 18:05:48 +0000694 line_writer.WriteCompilationUnit(compilation_unit);
David Srbeckyb851b492015-11-11 20:19:38 +0000695 }
696 line_writer.End();
697 }
698
699 // Write .debug_info section.
700 {
701 DebugInfoWriter<ElfTypes> info_writer(builder);
702 info_writer.Start();
703 for (const auto& compilation_unit : compilation_units) {
David Srbecky04b05262015-11-09 18:05:48 +0000704 info_writer.WriteCompilationUnit(compilation_unit);
David Srbeckyb851b492015-11-11 20:19:38 +0000705 }
706 info_writer.End();
707 }
David Srbecky3b9d57a2015-04-10 00:22:14 +0100708}
709
David Srbecky6d8c8f02015-10-26 10:57:09 +0000710// Explicit instantiations
711template void WriteCFISection<ElfTypes32>(
712 ElfBuilder<ElfTypes32>* builder,
713 const std::vector<OatWriter::DebugInfo>& method_infos,
714 CFIFormat format);
715template void WriteCFISection<ElfTypes64>(
716 ElfBuilder<ElfTypes64>* builder,
717 const std::vector<OatWriter::DebugInfo>& method_infos,
718 CFIFormat format);
719template void WriteDebugSections<ElfTypes32>(
720 ElfBuilder<ElfTypes32>* builder,
721 const std::vector<OatWriter::DebugInfo>& method_infos);
722template void WriteDebugSections<ElfTypes64>(
723 ElfBuilder<ElfTypes64>* builder,
724 const std::vector<OatWriter::DebugInfo>& method_infos);
725
David Srbecky3b9d57a2015-04-10 00:22:14 +0100726} // namespace dwarf
727} // namespace art