blob: ca8cd68b33726584161f350142b2e36a6c9aa5e1 [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 Srbecky5e974a62016-01-22 14:25:03 +000019#include <algorithm>
David Srbecky626a1662015-04-12 13:12:26 +010020#include <unordered_set>
Vladimir Marko10c13562015-11-25 14:33:36 +000021#include <vector>
David Srbecky9b3607d2016-01-14 18:15:54 +000022#include <cstdio>
David Srbecky626a1662015-04-12 13:12:26 +010023
Andreas Gampee3d623e2015-05-01 16:11:04 -070024#include "base/casts.h"
David Srbecky04b05262015-11-09 18:05:48 +000025#include "base/stl_util.h"
David Srbecky9b3607d2016-01-14 18:15:54 +000026#include "linear_alloc.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010027#include "compiled_method.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010028#include "dex_file-inl.h"
David Srbecky5cc349f2015-12-18 15:04:48 +000029#include "driver/compiler_driver.h"
David Srbecky91cb54e2016-01-15 13:47:59 +000030#include "dwarf/expression.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010031#include "dwarf/headers.h"
Vladimir Marko10c13562015-11-25 14:33:36 +000032#include "dwarf/method_debug_info.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010033#include "dwarf/register.h"
David Srbecky6d8c8f02015-10-26 10:57:09 +000034#include "elf_builder.h"
David Srbecky5cc349f2015-12-18 15:04:48 +000035#include "linker/vector_output_stream.h"
Tamas Berghammer86e42782016-01-05 14:29:02 +000036#include "mirror/array.h"
37#include "mirror/class-inl.h"
38#include "mirror/class.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010039#include "oat_writer.h"
David Srbecky0fd295f2015-11-16 16:39:10 +000040#include "stack_map.h"
David Srbecky5cc349f2015-12-18 15:04:48 +000041#include "utils.h"
David Srbecky3b9d57a2015-04-10 00:22:14 +010042
David Srbecky5b1c2ca2016-01-25 17:32:41 +000043// liblzma.
44#include "XzEnc.h"
45#include "7zCrc.h"
46#include "XzCrc64.h"
47
David Srbecky3b9d57a2015-04-10 00:22:14 +010048namespace art {
49namespace dwarf {
50
David Srbeckye0febdf2015-12-17 20:53:07 +000051// The ARM specification defines three special mapping symbols
52// $a, $t and $d which mark ARM, Thumb and data ranges respectively.
53// These symbols can be used by tools, for example, to pretty
54// print instructions correctly. Objdump will use them if they
55// exist, but it will still work well without them.
56// However, these extra symbols take space, so let's just generate
57// one symbol which marks the whole .text section as code.
58constexpr bool kGenerateSingleArmMappingSymbol = true;
59
David Srbecky0fd295f2015-11-16 16:39:10 +000060static Reg GetDwarfCoreReg(InstructionSet isa, int machine_reg) {
61 switch (isa) {
62 case kArm:
63 case kThumb2:
64 return Reg::ArmCore(machine_reg);
65 case kArm64:
66 return Reg::Arm64Core(machine_reg);
67 case kX86:
68 return Reg::X86Core(machine_reg);
69 case kX86_64:
70 return Reg::X86_64Core(machine_reg);
71 case kMips:
72 return Reg::MipsCore(machine_reg);
73 case kMips64:
74 return Reg::Mips64Core(machine_reg);
75 default:
76 LOG(FATAL) << "Unknown instruction set: " << isa;
77 UNREACHABLE();
78 }
79}
80
81static Reg GetDwarfFpReg(InstructionSet isa, int machine_reg) {
82 switch (isa) {
83 case kArm:
84 case kThumb2:
85 return Reg::ArmFp(machine_reg);
86 case kArm64:
87 return Reg::Arm64Fp(machine_reg);
88 case kX86:
89 return Reg::X86Fp(machine_reg);
90 case kX86_64:
91 return Reg::X86_64Fp(machine_reg);
David Srbeckyba702002016-02-01 18:15:29 +000092 case kMips:
93 return Reg::MipsFp(machine_reg);
94 case kMips64:
95 return Reg::Mips64Fp(machine_reg);
David Srbecky0fd295f2015-11-16 16:39:10 +000096 default:
97 LOG(FATAL) << "Unknown instruction set: " << isa;
98 UNREACHABLE();
99 }
100}
101
David Srbecky6d8c8f02015-10-26 10:57:09 +0000102static void WriteCIE(InstructionSet isa,
103 CFIFormat format,
104 std::vector<uint8_t>* buffer) {
David Srbecky3b9d57a2015-04-10 00:22:14 +0100105 // Scratch registers should be marked as undefined. This tells the
106 // debugger that its value in the previous frame is not recoverable.
107 bool is64bit = Is64BitInstructionSet(isa);
108 switch (isa) {
109 case kArm:
110 case kThumb2: {
111 DebugFrameOpCodeWriter<> opcodes;
112 opcodes.DefCFA(Reg::ArmCore(13), 0); // R13(SP).
113 // core registers.
114 for (int reg = 0; reg < 13; reg++) {
115 if (reg < 4 || reg == 12) {
116 opcodes.Undefined(Reg::ArmCore(reg));
117 } else {
118 opcodes.SameValue(Reg::ArmCore(reg));
119 }
120 }
121 // fp registers.
122 for (int reg = 0; reg < 32; reg++) {
123 if (reg < 16) {
124 opcodes.Undefined(Reg::ArmFp(reg));
125 } else {
126 opcodes.SameValue(Reg::ArmFp(reg));
127 }
128 }
David Srbecky527c9c72015-04-17 21:14:10 +0100129 auto return_reg = Reg::ArmCore(14); // R14(LR).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000130 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100131 return;
132 }
133 case kArm64: {
134 DebugFrameOpCodeWriter<> opcodes;
135 opcodes.DefCFA(Reg::Arm64Core(31), 0); // R31(SP).
136 // core registers.
137 for (int reg = 0; reg < 30; reg++) {
138 if (reg < 8 || reg == 16 || reg == 17) {
139 opcodes.Undefined(Reg::Arm64Core(reg));
140 } else {
141 opcodes.SameValue(Reg::Arm64Core(reg));
142 }
143 }
144 // fp registers.
145 for (int reg = 0; reg < 32; reg++) {
146 if (reg < 8 || reg >= 16) {
147 opcodes.Undefined(Reg::Arm64Fp(reg));
148 } else {
149 opcodes.SameValue(Reg::Arm64Fp(reg));
150 }
151 }
David Srbecky527c9c72015-04-17 21:14:10 +0100152 auto return_reg = Reg::Arm64Core(30); // R30(LR).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000153 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100154 return;
155 }
156 case kMips:
157 case kMips64: {
158 DebugFrameOpCodeWriter<> opcodes;
159 opcodes.DefCFA(Reg::MipsCore(29), 0); // R29(SP).
160 // core registers.
161 for (int reg = 1; reg < 26; reg++) {
162 if (reg < 16 || reg == 24 || reg == 25) { // AT, V*, A*, T*.
163 opcodes.Undefined(Reg::MipsCore(reg));
164 } else {
165 opcodes.SameValue(Reg::MipsCore(reg));
166 }
167 }
David Srbeckyba702002016-02-01 18:15:29 +0000168 // fp registers.
169 for (int reg = 0; reg < 32; reg++) {
170 if (reg < 24) {
171 opcodes.Undefined(Reg::Mips64Fp(reg));
172 } else {
173 opcodes.SameValue(Reg::Mips64Fp(reg));
174 }
175 }
David Srbecky527c9c72015-04-17 21:14:10 +0100176 auto return_reg = Reg::MipsCore(31); // R31(RA).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000177 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100178 return;
179 }
180 case kX86: {
David Srbecky8a813f72015-04-20 16:43:52 +0100181 // FIXME: Add fp registers once libunwind adds support for them. Bug: 20491296
182 constexpr bool generate_opcodes_for_x86_fp = false;
David Srbecky3b9d57a2015-04-10 00:22:14 +0100183 DebugFrameOpCodeWriter<> opcodes;
184 opcodes.DefCFA(Reg::X86Core(4), 4); // R4(ESP).
185 opcodes.Offset(Reg::X86Core(8), -4); // R8(EIP).
186 // core registers.
187 for (int reg = 0; reg < 8; reg++) {
188 if (reg <= 3) {
189 opcodes.Undefined(Reg::X86Core(reg));
190 } else if (reg == 4) {
191 // Stack pointer.
192 } else {
193 opcodes.SameValue(Reg::X86Core(reg));
194 }
195 }
196 // fp registers.
David Srbecky8a813f72015-04-20 16:43:52 +0100197 if (generate_opcodes_for_x86_fp) {
198 for (int reg = 0; reg < 8; reg++) {
199 opcodes.Undefined(Reg::X86Fp(reg));
200 }
David Srbecky3b9d57a2015-04-10 00:22:14 +0100201 }
David Srbecky527c9c72015-04-17 21:14:10 +0100202 auto return_reg = Reg::X86Core(8); // R8(EIP).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000203 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100204 return;
205 }
206 case kX86_64: {
207 DebugFrameOpCodeWriter<> opcodes;
208 opcodes.DefCFA(Reg::X86_64Core(4), 8); // R4(RSP).
209 opcodes.Offset(Reg::X86_64Core(16), -8); // R16(RIP).
210 // core registers.
211 for (int reg = 0; reg < 16; reg++) {
212 if (reg == 4) {
213 // Stack pointer.
214 } else if (reg < 12 && reg != 3 && reg != 5) { // except EBX and EBP.
215 opcodes.Undefined(Reg::X86_64Core(reg));
216 } else {
217 opcodes.SameValue(Reg::X86_64Core(reg));
218 }
219 }
220 // fp registers.
221 for (int reg = 0; reg < 16; reg++) {
222 if (reg < 12) {
223 opcodes.Undefined(Reg::X86_64Fp(reg));
224 } else {
225 opcodes.SameValue(Reg::X86_64Fp(reg));
226 }
227 }
David Srbecky527c9c72015-04-17 21:14:10 +0100228 auto return_reg = Reg::X86_64Core(16); // R16(RIP).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000229 WriteCIE(is64bit, return_reg, opcodes, format, buffer);
David Srbecky3b9d57a2015-04-10 00:22:14 +0100230 return;
231 }
232 case kNone:
233 break;
234 }
Roland Levillain91d65e02016-01-19 15:59:16 +0000235 LOG(FATAL) << "Cannot write CIE frame for ISA " << isa;
David Srbecky3b9d57a2015-04-10 00:22:14 +0100236 UNREACHABLE();
237}
238
David Srbecky6d8c8f02015-10-26 10:57:09 +0000239template<typename ElfTypes>
240void WriteCFISection(ElfBuilder<ElfTypes>* builder,
Vladimir Marko10c13562015-11-25 14:33:36 +0000241 const ArrayRef<const MethodDebugInfo>& method_infos,
David Srbecky5e974a62016-01-22 14:25:03 +0000242 CFIFormat format,
243 bool write_oat_patches) {
David Srbeckye0febdf2015-12-17 20:53:07 +0000244 CHECK(format == DW_DEBUG_FRAME_FORMAT || format == DW_EH_FRAME_FORMAT);
David Srbecky6d8c8f02015-10-26 10:57:09 +0000245 typedef typename ElfTypes::Addr Elf_Addr;
246
Tamas Berghammer86e42782016-01-05 14:29:02 +0000247 if (method_infos.empty()) {
248 return;
249 }
250
David Srbecky6d8c8f02015-10-26 10:57:09 +0000251 std::vector<uint32_t> binary_search_table;
252 std::vector<uintptr_t> patch_locations;
253 if (format == DW_EH_FRAME_FORMAT) {
254 binary_search_table.reserve(2 * method_infos.size());
255 } else {
256 patch_locations.reserve(method_infos.size());
257 }
David Srbecky527c9c72015-04-17 21:14:10 +0100258
David Srbecky5e974a62016-01-22 14:25:03 +0000259 // The methods can be written any order.
260 // Let's therefore sort them in the lexicographical order of the opcodes.
261 // This has no effect on its own. However, if the final .debug_frame section is
262 // compressed it reduces the size since similar opcodes sequences are grouped.
263 std::vector<const MethodDebugInfo*> sorted_method_infos;
264 sorted_method_infos.reserve(method_infos.size());
265 for (size_t i = 0; i < method_infos.size(); i++) {
266 sorted_method_infos.push_back(&method_infos[i]);
267 }
268 std::sort(
269 sorted_method_infos.begin(),
270 sorted_method_infos.end(),
271 [](const MethodDebugInfo* lhs, const MethodDebugInfo* rhs) {
272 ArrayRef<const uint8_t> l = lhs->compiled_method_->GetCFIInfo();
273 ArrayRef<const uint8_t> r = rhs->compiled_method_->GetCFIInfo();
274 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
275 });
276
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100277 // Write .eh_frame/.debug_frame section.
David Srbeckye0febdf2015-12-17 20:53:07 +0000278 auto* cfi_section = (format == DW_DEBUG_FRAME_FORMAT
David Srbecky6d8c8f02015-10-26 10:57:09 +0000279 ? builder->GetDebugFrame()
280 : builder->GetEhFrame());
281 {
282 cfi_section->Start();
283 const bool is64bit = Is64BitInstructionSet(builder->GetIsa());
David Srbecky5cc349f2015-12-18 15:04:48 +0000284 const Elf_Addr text_address = builder->GetText()->Exists()
285 ? builder->GetText()->GetAddress()
286 : 0;
David Srbecky6d8c8f02015-10-26 10:57:09 +0000287 const Elf_Addr cfi_address = cfi_section->GetAddress();
288 const Elf_Addr cie_address = cfi_address;
289 Elf_Addr buffer_address = cfi_address;
290 std::vector<uint8_t> buffer; // Small temporary buffer.
291 WriteCIE(builder->GetIsa(), format, &buffer);
292 cfi_section->WriteFully(buffer.data(), buffer.size());
293 buffer_address += buffer.size();
294 buffer.clear();
David Srbecky5e974a62016-01-22 14:25:03 +0000295 for (const MethodDebugInfo* mi : sorted_method_infos) {
296 if (!mi->deduped_) { // Only one FDE per unique address.
297 ArrayRef<const uint8_t> opcodes = mi->compiled_method_->GetCFIInfo();
David Srbecky6d8c8f02015-10-26 10:57:09 +0000298 if (!opcodes.empty()) {
David Srbecky5e974a62016-01-22 14:25:03 +0000299 const Elf_Addr code_address = text_address + mi->low_pc_;
David Srbecky6d8c8f02015-10-26 10:57:09 +0000300 if (format == DW_EH_FRAME_FORMAT) {
301 binary_search_table.push_back(
302 dchecked_integral_cast<uint32_t>(code_address));
303 binary_search_table.push_back(
304 dchecked_integral_cast<uint32_t>(buffer_address));
305 }
306 WriteFDE(is64bit, cfi_address, cie_address,
David Srbecky5e974a62016-01-22 14:25:03 +0000307 code_address, mi->high_pc_ - mi->low_pc_,
David Srbecky6d8c8f02015-10-26 10:57:09 +0000308 opcodes, format, buffer_address, &buffer,
309 &patch_locations);
310 cfi_section->WriteFully(buffer.data(), buffer.size());
311 buffer_address += buffer.size();
312 buffer.clear();
313 }
David Srbecky6d73c9d2015-05-01 15:00:40 +0100314 }
David Srbecky8dc73242015-04-12 11:40:39 +0100315 }
David Srbecky6d8c8f02015-10-26 10:57:09 +0000316 cfi_section->End();
David Srbecky8dc73242015-04-12 11:40:39 +0100317 }
David Srbecky527c9c72015-04-17 21:14:10 +0100318
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100319 if (format == DW_EH_FRAME_FORMAT) {
David Srbecky6d8c8f02015-10-26 10:57:09 +0000320 auto* header_section = builder->GetEhFrameHdr();
321 header_section->Start();
322 uint32_t header_address = dchecked_integral_cast<int32_t>(header_section->GetAddress());
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100323 // Write .eh_frame_hdr section.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000324 std::vector<uint8_t> buffer;
325 Writer<> header(&buffer);
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100326 header.PushUint8(1); // Version.
327 // Encoding of .eh_frame pointer - libunwind does not honor datarel here,
328 // so we have to use pcrel which means relative to the pointer's location.
329 header.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
330 // Encoding of binary search table size.
331 header.PushUint8(DW_EH_PE_udata4);
332 // Encoding of binary search table addresses - libunwind supports only this
333 // specific combination, which means relative to the start of .eh_frame_hdr.
334 header.PushUint8(DW_EH_PE_datarel | DW_EH_PE_sdata4);
David Srbecky6d8c8f02015-10-26 10:57:09 +0000335 // .eh_frame pointer
336 header.PushInt32(cfi_section->GetAddress() - (header_address + 4u));
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100337 // Binary search table size (number of entries).
David Srbecky6d8c8f02015-10-26 10:57:09 +0000338 header.PushUint32(dchecked_integral_cast<uint32_t>(binary_search_table.size()/2));
339 header_section->WriteFully(buffer.data(), buffer.size());
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100340 // Binary search table.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000341 for (size_t i = 0; i < binary_search_table.size(); i++) {
342 // Make addresses section-relative since we know the header address now.
343 binary_search_table[i] -= header_address;
David Srbeckyad5fa8c2015-05-06 18:27:35 +0100344 }
David Srbecky6d8c8f02015-10-26 10:57:09 +0000345 header_section->WriteFully(binary_search_table.data(), binary_search_table.size());
346 header_section->End();
347 } else {
David Srbecky5e974a62016-01-22 14:25:03 +0000348 if (write_oat_patches) {
349 builder->WritePatches(".debug_frame.oat_patches",
350 ArrayRef<const uintptr_t>(patch_locations));
351 }
David Srbecky033d7452015-04-30 19:57:35 +0100352 }
David Srbecky8dc73242015-04-12 11:40:39 +0100353}
354
David Srbecky996ed0b2015-11-27 10:27:11 +0000355namespace {
356 struct CompilationUnit {
357 std::vector<const MethodDebugInfo*> methods_;
358 size_t debug_line_offset_ = 0;
David Srbecky5cc349f2015-12-18 15:04:48 +0000359 uintptr_t low_pc_ = std::numeric_limits<uintptr_t>::max();
360 uintptr_t high_pc_ = 0;
David Srbecky996ed0b2015-11-27 10:27:11 +0000361 };
362
David Srbeckyb06e28e2015-12-10 13:15:00 +0000363 typedef std::vector<DexFile::LocalInfo> LocalInfos;
David Srbecky996ed0b2015-11-27 10:27:11 +0000364
David Srbeckyb06e28e2015-12-10 13:15:00 +0000365 void LocalInfoCallback(void* ctx, const DexFile::LocalInfo& entry) {
366 static_cast<LocalInfos*>(ctx)->push_back(entry);
367 }
368
369 typedef std::vector<DexFile::PositionInfo> PositionInfos;
370
371 bool PositionInfoCallback(void* ctx, const DexFile::PositionInfo& entry) {
372 static_cast<PositionInfos*>(ctx)->push_back(entry);
373 return false;
374 }
David Srbecky996ed0b2015-11-27 10:27:11 +0000375
376 std::vector<const char*> GetParamNames(const MethodDebugInfo* mi) {
377 std::vector<const char*> names;
David Srbeckyb06e28e2015-12-10 13:15:00 +0000378 if (mi->code_item_ != nullptr) {
379 const uint8_t* stream = mi->dex_file_->GetDebugInfoStream(mi->code_item_);
380 if (stream != nullptr) {
381 DecodeUnsignedLeb128(&stream); // line.
382 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
383 for (uint32_t i = 0; i < parameters_size; ++i) {
384 uint32_t id = DecodeUnsignedLeb128P1(&stream);
385 names.push_back(mi->dex_file_->StringDataByIdx(id));
386 }
David Srbecky996ed0b2015-11-27 10:27:11 +0000387 }
388 }
389 return names;
390 }
391
392 struct VariableLocation {
393 uint32_t low_pc;
394 uint32_t high_pc;
395 DexRegisterLocation reg_lo; // May be None if the location is unknown.
396 DexRegisterLocation reg_hi; // Most significant bits of 64-bit value.
397 };
398
399 // Get the location of given dex register (e.g. stack or machine register).
400 // Note that the location might be different based on the current pc.
401 // The result will cover all ranges where the variable is in scope.
402 std::vector<VariableLocation> GetVariableLocations(const MethodDebugInfo* method_info,
403 uint16_t vreg,
404 bool is64bitValue,
405 uint32_t dex_pc_low,
406 uint32_t dex_pc_high) {
407 std::vector<VariableLocation> variable_locations;
408
409 // Get stack maps sorted by pc (they might not be sorted internally).
410 const CodeInfo code_info(method_info->compiled_method_->GetVmapTable().data());
411 const StackMapEncoding encoding = code_info.ExtractEncoding();
412 std::map<uint32_t, StackMap> stack_maps;
413 for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) {
414 StackMap stack_map = code_info.GetStackMapAt(s, encoding);
415 DCHECK(stack_map.IsValid());
416 const uint32_t low_pc = method_info->low_pc_ + stack_map.GetNativePcOffset(encoding);
417 DCHECK_LE(low_pc, method_info->high_pc_);
418 stack_maps.emplace(low_pc, stack_map);
419 }
420
421 // Create entries for the requested register based on stack map data.
422 for (auto it = stack_maps.begin(); it != stack_maps.end(); it++) {
423 const StackMap& stack_map = it->second;
424 const uint32_t low_pc = it->first;
425 auto next_it = it;
426 next_it++;
427 const uint32_t high_pc = next_it != stack_maps.end() ? next_it->first
428 : method_info->high_pc_;
429 DCHECK_LE(low_pc, high_pc);
430 if (low_pc == high_pc) {
431 continue; // Ignore if the address range is empty.
432 }
433
434 // Check that the stack map is in the requested range.
435 uint32_t dex_pc = stack_map.GetDexPc(encoding);
436 if (!(dex_pc_low <= dex_pc && dex_pc < dex_pc_high)) {
437 continue;
438 }
439
440 // Find the location of the dex register.
441 DexRegisterLocation reg_lo = DexRegisterLocation::None();
442 DexRegisterLocation reg_hi = DexRegisterLocation::None();
443 if (stack_map.HasDexRegisterMap(encoding)) {
444 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
445 stack_map, encoding, method_info->code_item_->registers_size_);
446 reg_lo = dex_register_map.GetDexRegisterLocation(
447 vreg, method_info->code_item_->registers_size_, code_info, encoding);
448 if (is64bitValue) {
449 reg_hi = dex_register_map.GetDexRegisterLocation(
450 vreg + 1, method_info->code_item_->registers_size_, code_info, encoding);
451 }
452 }
453
454 // Add location entry for this address range.
455 if (!variable_locations.empty() &&
456 variable_locations.back().reg_lo == reg_lo &&
457 variable_locations.back().reg_hi == reg_hi &&
458 variable_locations.back().high_pc == low_pc) {
459 // Merge with the previous entry (extend its range).
460 variable_locations.back().high_pc = high_pc;
461 } else {
462 variable_locations.push_back({low_pc, high_pc, reg_lo, reg_hi});
463 }
464 }
465
466 return variable_locations;
467 }
David Srbeckyf71b3ad2015-12-08 15:05:08 +0000468
469 bool IsFromOptimizingCompiler(const MethodDebugInfo* method_info) {
470 return method_info->compiled_method_->GetQuickCode().size() > 0 &&
471 method_info->compiled_method_->GetVmapTable().size() > 0 &&
472 method_info->compiled_method_->GetGcMap().size() == 0 &&
473 method_info->code_item_ != nullptr;
474 }
David Srbecky996ed0b2015-11-27 10:27:11 +0000475} // namespace
David Srbecky04b05262015-11-09 18:05:48 +0000476
477// Helper class to write .debug_info and its supporting sections.
David Srbecky6d8c8f02015-10-26 10:57:09 +0000478template<typename ElfTypes>
David Srbeckyb851b492015-11-11 20:19:38 +0000479class DebugInfoWriter {
David Srbecky6d8c8f02015-10-26 10:57:09 +0000480 typedef typename ElfTypes::Addr Elf_Addr;
David Srbecky3b9d57a2015-04-10 00:22:14 +0100481
David Srbecky04b05262015-11-09 18:05:48 +0000482 // Helper class to write one compilation unit.
483 // It holds helper methods and temporary state.
484 class CompilationUnitWriter {
485 public:
486 explicit CompilationUnitWriter(DebugInfoWriter* owner)
487 : owner_(owner),
David Srbecky24868a12016-01-29 18:59:56 +0000488 info_(Is64BitInstructionSet(owner_->builder_->GetIsa()), &owner->debug_abbrev_) {
David Srbecky04b05262015-11-09 18:05:48 +0000489 }
490
491 void Write(const CompilationUnit& compilation_unit) {
492 CHECK(!compilation_unit.methods_.empty());
David Srbecky5cc349f2015-12-18 15:04:48 +0000493 const Elf_Addr text_address = owner_->builder_->GetText()->Exists()
494 ? owner_->builder_->GetText()->GetAddress()
495 : 0;
496 const uintptr_t cu_size = compilation_unit.high_pc_ - compilation_unit.low_pc_;
David Srbecky04b05262015-11-09 18:05:48 +0000497
498 info_.StartTag(DW_TAG_compile_unit);
David Srbecky1c4aeb42016-02-01 15:37:32 +0000499 info_.WriteString(DW_AT_producer, "Android dex2oat");
David Srbecky04b05262015-11-09 18:05:48 +0000500 info_.WriteData1(DW_AT_language, DW_LANG_Java);
David Srbecky1c4aeb42016-02-01 15:37:32 +0000501 info_.WriteString(DW_AT_comp_dir, "$JAVA_SRC_ROOT");
David Srbecky04b05262015-11-09 18:05:48 +0000502 info_.WriteAddr(DW_AT_low_pc, text_address + compilation_unit.low_pc_);
David Srbecky5cc349f2015-12-18 15:04:48 +0000503 info_.WriteUdata(DW_AT_high_pc, dchecked_integral_cast<uint32_t>(cu_size));
David Srbecky0fd295f2015-11-16 16:39:10 +0000504 info_.WriteSecOffset(DW_AT_stmt_list, compilation_unit.debug_line_offset_);
David Srbecky04b05262015-11-09 18:05:48 +0000505
506 const char* last_dex_class_desc = nullptr;
507 for (auto mi : compilation_unit.methods_) {
508 const DexFile* dex = mi->dex_file_;
David Srbeckyb06e28e2015-12-10 13:15:00 +0000509 const DexFile::CodeItem* dex_code = mi->code_item_;
David Srbecky04b05262015-11-09 18:05:48 +0000510 const DexFile::MethodId& dex_method = dex->GetMethodId(mi->dex_method_index_);
511 const DexFile::ProtoId& dex_proto = dex->GetMethodPrototype(dex_method);
512 const DexFile::TypeList* dex_params = dex->GetProtoParameters(dex_proto);
513 const char* dex_class_desc = dex->GetMethodDeclaringClassDescriptor(dex_method);
David Srbecky996ed0b2015-11-27 10:27:11 +0000514 const bool is_static = (mi->access_flags_ & kAccStatic) != 0;
David Srbecky04b05262015-11-09 18:05:48 +0000515
516 // Enclose the method in correct class definition.
517 if (last_dex_class_desc != dex_class_desc) {
518 if (last_dex_class_desc != nullptr) {
David Srbecky7138d452016-01-29 15:02:44 +0000519 EndClassTag();
David Srbecky04b05262015-11-09 18:05:48 +0000520 }
Tamas Berghammer86e42782016-01-05 14:29:02 +0000521 // Write reference tag for the class we are about to declare.
522 size_t reference_tag_offset = info_.StartTag(DW_TAG_reference_type);
523 type_cache_.emplace(std::string(dex_class_desc), reference_tag_offset);
524 size_t type_attrib_offset = info_.size();
525 info_.WriteRef4(DW_AT_type, 0);
526 info_.EndTag();
527 // Declare the class that owns this method.
528 size_t class_offset = StartClassTag(dex_class_desc);
529 info_.UpdateUint32(type_attrib_offset, class_offset);
David Srbeckyfa5ec2b2016-01-29 15:13:19 +0000530 info_.WriteFlagPresent(DW_AT_declaration);
David Srbecky04b05262015-11-09 18:05:48 +0000531 // Check that each class is defined only once.
532 bool unique = owner_->defined_dex_classes_.insert(dex_class_desc).second;
533 CHECK(unique) << "Redefinition of " << dex_class_desc;
534 last_dex_class_desc = dex_class_desc;
535 }
536
David Srbecky04b05262015-11-09 18:05:48 +0000537 int start_depth = info_.Depth();
538 info_.StartTag(DW_TAG_subprogram);
539 WriteName(dex->GetMethodName(dex_method));
540 info_.WriteAddr(DW_AT_low_pc, text_address + mi->low_pc_);
David Srbecky5cc349f2015-12-18 15:04:48 +0000541 info_.WriteUdata(DW_AT_high_pc, dchecked_integral_cast<uint32_t>(mi->high_pc_-mi->low_pc_));
David Srbecky91cb54e2016-01-15 13:47:59 +0000542 std::vector<uint8_t> expr_buffer;
543 Expression expr(&expr_buffer);
544 expr.WriteOpCallFrameCfa();
545 info_.WriteExprLoc(DW_AT_frame_base, expr);
David Srbecky04b05262015-11-09 18:05:48 +0000546 WriteLazyType(dex->GetReturnTypeDescriptor(dex_proto));
David Srbeckyb06e28e2015-12-10 13:15:00 +0000547
548 // Write parameters. DecodeDebugLocalInfo returns them as well, but it does not
549 // guarantee order or uniqueness so it is safer to iterate over them manually.
550 // DecodeDebugLocalInfo might not also be available if there is no debug info.
551 std::vector<const char*> param_names = GetParamNames(mi);
552 uint32_t arg_reg = 0;
David Srbecky996ed0b2015-11-27 10:27:11 +0000553 if (!is_static) {
554 info_.StartTag(DW_TAG_formal_parameter);
555 WriteName("this");
David Srbeckyfa5ec2b2016-01-29 15:13:19 +0000556 info_.WriteFlagPresent(DW_AT_artificial);
David Srbecky996ed0b2015-11-27 10:27:11 +0000557 WriteLazyType(dex_class_desc);
David Srbeckyb06e28e2015-12-10 13:15:00 +0000558 if (dex_code != nullptr) {
559 // Write the stack location of the parameter.
560 const uint32_t vreg = dex_code->registers_size_ - dex_code->ins_size_ + arg_reg;
561 const bool is64bitValue = false;
562 WriteRegLocation(mi, vreg, is64bitValue, compilation_unit.low_pc_);
563 }
564 arg_reg++;
David Srbecky996ed0b2015-11-27 10:27:11 +0000565 info_.EndTag();
566 }
David Srbecky04b05262015-11-09 18:05:48 +0000567 if (dex_params != nullptr) {
568 for (uint32_t i = 0; i < dex_params->Size(); ++i) {
569 info_.StartTag(DW_TAG_formal_parameter);
570 // Parameter names may not be always available.
David Srbeckyb06e28e2015-12-10 13:15:00 +0000571 if (i < param_names.size()) {
David Srbecky04b05262015-11-09 18:05:48 +0000572 WriteName(param_names[i]);
573 }
David Srbecky0fd295f2015-11-16 16:39:10 +0000574 // Write the type.
575 const char* type_desc = dex->StringByTypeIdx(dex_params->GetTypeItem(i).type_idx_);
576 WriteLazyType(type_desc);
David Srbecky0fd295f2015-11-16 16:39:10 +0000577 const bool is64bitValue = type_desc[0] == 'D' || type_desc[0] == 'J';
David Srbeckyb06e28e2015-12-10 13:15:00 +0000578 if (dex_code != nullptr) {
579 // Write the stack location of the parameter.
580 const uint32_t vreg = dex_code->registers_size_ - dex_code->ins_size_ + arg_reg;
581 WriteRegLocation(mi, vreg, is64bitValue, compilation_unit.low_pc_);
582 }
583 arg_reg += is64bitValue ? 2 : 1;
David Srbecky04b05262015-11-09 18:05:48 +0000584 info_.EndTag();
585 }
David Srbeckyb06e28e2015-12-10 13:15:00 +0000586 if (dex_code != nullptr) {
587 DCHECK_EQ(arg_reg, dex_code->ins_size_);
David Srbecky0fd295f2015-11-16 16:39:10 +0000588 }
David Srbecky04b05262015-11-09 18:05:48 +0000589 }
David Srbeckyb06e28e2015-12-10 13:15:00 +0000590
591 // Write local variables.
592 LocalInfos local_infos;
593 if (dex->DecodeDebugLocalInfo(dex_code,
594 is_static,
595 mi->dex_method_index_,
596 LocalInfoCallback,
597 &local_infos)) {
598 for (const DexFile::LocalInfo& var : local_infos) {
599 if (var.reg_ < dex_code->registers_size_ - dex_code->ins_size_) {
600 info_.StartTag(DW_TAG_variable);
601 WriteName(var.name_);
602 WriteLazyType(var.descriptor_);
603 bool is64bitValue = var.descriptor_[0] == 'D' || var.descriptor_[0] == 'J';
604 WriteRegLocation(mi, var.reg_, is64bitValue, compilation_unit.low_pc_,
605 var.start_address_, var.end_address_);
606 info_.EndTag();
607 }
David Srbecky996ed0b2015-11-27 10:27:11 +0000608 }
609 }
David Srbeckyb06e28e2015-12-10 13:15:00 +0000610
David Srbecky04b05262015-11-09 18:05:48 +0000611 info_.EndTag();
612 CHECK_EQ(info_.Depth(), start_depth); // Balanced start/end.
613 }
614 if (last_dex_class_desc != nullptr) {
David Srbecky7138d452016-01-29 15:02:44 +0000615 EndClassTag();
David Srbecky04b05262015-11-09 18:05:48 +0000616 }
David Srbecky04b05262015-11-09 18:05:48 +0000617 FinishLazyTypes();
David Srbecky7138d452016-01-29 15:02:44 +0000618 CloseNamespacesAboveDepth(0);
David Srbecky04b05262015-11-09 18:05:48 +0000619 info_.EndTag(); // DW_TAG_compile_unit
David Srbecky7138d452016-01-29 15:02:44 +0000620 CHECK_EQ(info_.Depth(), 0);
David Srbecky04b05262015-11-09 18:05:48 +0000621 std::vector<uint8_t> buffer;
622 buffer.reserve(info_.data()->size() + KB);
623 const size_t offset = owner_->builder_->GetDebugInfo()->GetSize();
David Srbecky24868a12016-01-29 18:59:56 +0000624 // All compilation units share single table which is at the start of .debug_abbrev.
625 const size_t debug_abbrev_offset = 0;
David Srbecky04b05262015-11-09 18:05:48 +0000626 WriteDebugInfoCU(debug_abbrev_offset, info_, offset, &buffer, &owner_->debug_info_patches_);
627 owner_->builder_->GetDebugInfo()->WriteFully(buffer.data(), buffer.size());
628 }
629
Tamas Berghammer86e42782016-01-05 14:29:02 +0000630 void Write(const ArrayRef<mirror::Class*>& types) SHARED_REQUIRES(Locks::mutator_lock_) {
631 info_.StartTag(DW_TAG_compile_unit);
David Srbecky1c4aeb42016-02-01 15:37:32 +0000632 info_.WriteString(DW_AT_producer, "Android dex2oat");
Tamas Berghammer86e42782016-01-05 14:29:02 +0000633 info_.WriteData1(DW_AT_language, DW_LANG_Java);
634
David Srbeckyc7eecf92016-02-01 14:53:48 +0000635 // Base class references to be patched at the end.
636 std::map<size_t, mirror::Class*> base_class_references;
637
638 // Already written declarations or definitions.
639 std::map<mirror::Class*, size_t> class_declarations;
640
David Srbecky9b3607d2016-01-14 18:15:54 +0000641 std::vector<uint8_t> expr_buffer;
Tamas Berghammer86e42782016-01-05 14:29:02 +0000642 for (mirror::Class* type : types) {
643 if (type->IsPrimitive()) {
644 // For primitive types the definition and the declaration is the same.
645 if (type->GetPrimitiveType() != Primitive::kPrimVoid) {
646 WriteTypeDeclaration(type->GetDescriptor(nullptr));
647 }
648 } else if (type->IsArrayClass()) {
649 mirror::Class* element_type = type->GetComponentType();
650 uint32_t component_size = type->GetComponentSize();
651 uint32_t data_offset = mirror::Array::DataOffset(component_size).Uint32Value();
652 uint32_t length_offset = mirror::Array::LengthOffset().Uint32Value();
653
David Srbecky7138d452016-01-29 15:02:44 +0000654 CloseNamespacesAboveDepth(0); // Declare in root namespace.
Tamas Berghammer86e42782016-01-05 14:29:02 +0000655 info_.StartTag(DW_TAG_array_type);
656 std::string descriptor_string;
657 WriteLazyType(element_type->GetDescriptor(&descriptor_string));
David Srbecky9b3607d2016-01-14 18:15:54 +0000658 WriteLinkageName(type);
Tamas Berghammer86e42782016-01-05 14:29:02 +0000659 info_.WriteUdata(DW_AT_data_member_location, data_offset);
660 info_.StartTag(DW_TAG_subrange_type);
David Srbecky9b3607d2016-01-14 18:15:54 +0000661 Expression count_expr(&expr_buffer);
David Srbecky91cb54e2016-01-15 13:47:59 +0000662 count_expr.WriteOpPushObjectAddress();
663 count_expr.WriteOpPlusUconst(length_offset);
664 count_expr.WriteOpDerefSize(4); // Array length is always 32-bit wide.
665 info_.WriteExprLoc(DW_AT_count, count_expr);
Tamas Berghammer86e42782016-01-05 14:29:02 +0000666 info_.EndTag(); // DW_TAG_subrange_type.
667 info_.EndTag(); // DW_TAG_array_type.
David Srbecky9b3607d2016-01-14 18:15:54 +0000668 } else if (type->IsInterface()) {
669 // Skip. Variables cannot have an interface as a dynamic type.
670 // We do not expose the interface information to the debugger in any way.
Tamas Berghammer86e42782016-01-05 14:29:02 +0000671 } else {
672 std::string descriptor_string;
673 const char* desc = type->GetDescriptor(&descriptor_string);
David Srbeckyc7eecf92016-02-01 14:53:48 +0000674 size_t class_offset = StartClassTag(desc);
675 class_declarations.emplace(type, class_offset);
Tamas Berghammer86e42782016-01-05 14:29:02 +0000676
677 if (!type->IsVariableSize()) {
678 info_.WriteUdata(DW_AT_byte_size, type->GetObjectSize());
679 }
680
David Srbecky9b3607d2016-01-14 18:15:54 +0000681 WriteLinkageName(type);
682
683 if (type->IsObjectClass()) {
684 // Generate artificial member which is used to get the dynamic type of variable.
685 // The run-time value of this field will correspond to linkage name of some type.
686 // We need to do it only once in j.l.Object since all other types inherit it.
687 info_.StartTag(DW_TAG_member);
688 WriteName(".dynamic_type");
689 WriteLazyType(sizeof(uintptr_t) == 8 ? "J" : "I");
David Srbeckyfa5ec2b2016-01-29 15:13:19 +0000690 info_.WriteFlagPresent(DW_AT_artificial);
David Srbecky9b3607d2016-01-14 18:15:54 +0000691 // Create DWARF expression to get the value of the methods_ field.
692 Expression expr(&expr_buffer);
693 // The address of the object has been implicitly pushed on the stack.
694 // Dereference the klass_ field of Object (32-bit; possibly poisoned).
695 DCHECK_EQ(type->ClassOffset().Uint32Value(), 0u);
696 DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Class>), 4u);
697 expr.WriteOpDerefSize(4);
698 if (kPoisonHeapReferences) {
699 expr.WriteOpNeg();
700 // DWARF stack is pointer sized. Ensure that the high bits are clear.
701 expr.WriteOpConstu(0xFFFFFFFF);
702 expr.WriteOpAnd();
703 }
704 // Add offset to the methods_ field.
705 expr.WriteOpPlusUconst(mirror::Class::MethodsOffset().Uint32Value());
706 // Top of stack holds the location of the field now.
707 info_.WriteExprLoc(DW_AT_data_member_location, expr);
708 info_.EndTag(); // DW_TAG_member.
709 }
710
Tamas Berghammer86e42782016-01-05 14:29:02 +0000711 // Base class.
David Srbeckyc7eecf92016-02-01 14:53:48 +0000712 mirror::Class* base_class = type->GetSuperClass();
Tamas Berghammer86e42782016-01-05 14:29:02 +0000713 if (base_class != nullptr) {
714 info_.StartTag(DW_TAG_inheritance);
David Srbeckyc7eecf92016-02-01 14:53:48 +0000715 base_class_references.emplace(info_.size(), base_class);
716 info_.WriteRef4(DW_AT_type, 0);
Tamas Berghammer86e42782016-01-05 14:29:02 +0000717 info_.WriteUdata(DW_AT_data_member_location, 0);
718 info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_public);
719 info_.EndTag(); // DW_TAG_inheritance.
720 }
721
722 // Member variables.
723 for (uint32_t i = 0, count = type->NumInstanceFields(); i < count; ++i) {
724 ArtField* field = type->GetInstanceField(i);
725 info_.StartTag(DW_TAG_member);
726 WriteName(field->GetName());
727 WriteLazyType(field->GetTypeDescriptor());
728 info_.WriteUdata(DW_AT_data_member_location, field->GetOffset().Uint32Value());
729 uint32_t access_flags = field->GetAccessFlags();
730 if (access_flags & kAccPublic) {
731 info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_public);
732 } else if (access_flags & kAccProtected) {
733 info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_protected);
734 } else if (access_flags & kAccPrivate) {
735 info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_private);
736 }
737 info_.EndTag(); // DW_TAG_member.
738 }
739
Tamas Berghammer03c941f2016-01-15 13:39:57 +0000740 if (type->IsStringClass()) {
741 // Emit debug info about an artifical class member for java.lang.String which represents
742 // the first element of the data stored in a string instance. Consumers of the debug
743 // info will be able to read the content of java.lang.String based on the count (real
744 // field) and based on the location of this data member.
745 info_.StartTag(DW_TAG_member);
746 WriteName("value");
747 // We don't support fields with C like array types so we just say its type is java char.
748 WriteLazyType("C"); // char.
749 info_.WriteUdata(DW_AT_data_member_location,
750 mirror::String::ValueOffset().Uint32Value());
751 info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_private);
752 info_.EndTag(); // DW_TAG_member.
753 }
754
David Srbecky7138d452016-01-29 15:02:44 +0000755 EndClassTag();
Tamas Berghammer86e42782016-01-05 14:29:02 +0000756 }
757 }
758
David Srbeckyc7eecf92016-02-01 14:53:48 +0000759 // Write base class declarations.
760 for (const auto& base_class_reference : base_class_references) {
761 size_t reference_offset = base_class_reference.first;
762 mirror::Class* base_class = base_class_reference.second;
763 const auto& it = class_declarations.find(base_class);
764 if (it != class_declarations.end()) {
765 info_.UpdateUint32(reference_offset, it->second);
766 } else {
767 // Declare base class. We can not use the standard WriteLazyType
768 // since we want to avoid the DW_TAG_reference_tag wrapping.
769 std::string tmp_storage;
770 const char* base_class_desc = base_class->GetDescriptor(&tmp_storage);
771 size_t base_class_declaration_offset = StartClassTag(base_class_desc);
772 info_.WriteFlagPresent(DW_AT_declaration);
773 WriteLinkageName(base_class);
774 EndClassTag();
775 class_declarations.emplace(base_class, base_class_declaration_offset);
776 info_.UpdateUint32(reference_offset, base_class_declaration_offset);
777 }
778 }
779
Tamas Berghammer86e42782016-01-05 14:29:02 +0000780 FinishLazyTypes();
David Srbecky7138d452016-01-29 15:02:44 +0000781 CloseNamespacesAboveDepth(0);
Tamas Berghammer86e42782016-01-05 14:29:02 +0000782 info_.EndTag(); // DW_TAG_compile_unit.
David Srbecky7138d452016-01-29 15:02:44 +0000783 CHECK_EQ(info_.Depth(), 0);
Tamas Berghammer86e42782016-01-05 14:29:02 +0000784 std::vector<uint8_t> buffer;
785 buffer.reserve(info_.data()->size() + KB);
786 const size_t offset = owner_->builder_->GetDebugInfo()->GetSize();
David Srbecky24868a12016-01-29 18:59:56 +0000787 // All compilation units share single table which is at the start of .debug_abbrev.
788 const size_t debug_abbrev_offset = 0;
Tamas Berghammer86e42782016-01-05 14:29:02 +0000789 WriteDebugInfoCU(debug_abbrev_offset, info_, offset, &buffer, &owner_->debug_info_patches_);
790 owner_->builder_->GetDebugInfo()->WriteFully(buffer.data(), buffer.size());
791 }
792
David Srbecky9b3607d2016-01-14 18:15:54 +0000793 // Linkage name uniquely identifies type.
794 // It is used to determine the dynamic type of objects.
795 // We use the methods_ field of class since it is unique and it is not moved by the GC.
796 void WriteLinkageName(mirror::Class* type) SHARED_REQUIRES(Locks::mutator_lock_) {
797 auto* methods_ptr = type->GetMethodsPtr();
798 if (methods_ptr == nullptr) {
799 // Some types might have no methods. Allocate empty array instead.
800 LinearAlloc* allocator = Runtime::Current()->GetLinearAlloc();
801 void* storage = allocator->Alloc(Thread::Current(), sizeof(LengthPrefixedArray<ArtMethod>));
802 methods_ptr = new (storage) LengthPrefixedArray<ArtMethod>(0);
803 type->SetMethodsPtr(methods_ptr, 0, 0);
804 DCHECK(type->GetMethodsPtr() != nullptr);
805 }
806 char name[32];
807 snprintf(name, sizeof(name), "0x%" PRIXPTR, reinterpret_cast<uintptr_t>(methods_ptr));
808 info_.WriteString(DW_AT_linkage_name, name);
809 }
810
David Srbecky0fd295f2015-11-16 16:39:10 +0000811 // Write table into .debug_loc which describes location of dex register.
812 // The dex register might be valid only at some points and it might
813 // move between machine registers and stack.
David Srbecky996ed0b2015-11-27 10:27:11 +0000814 void WriteRegLocation(const MethodDebugInfo* method_info,
815 uint16_t vreg,
816 bool is64bitValue,
817 uint32_t compilation_unit_low_pc,
818 uint32_t dex_pc_low = 0,
819 uint32_t dex_pc_high = 0xFFFFFFFF) {
David Srbecky0fd295f2015-11-16 16:39:10 +0000820 using Kind = DexRegisterLocation::Kind;
David Srbeckyf71b3ad2015-12-08 15:05:08 +0000821 if (!IsFromOptimizingCompiler(method_info)) {
David Srbecky0fd295f2015-11-16 16:39:10 +0000822 return;
823 }
824
David Srbecky996ed0b2015-11-27 10:27:11 +0000825 Writer<> debug_loc(&owner_->debug_loc_);
826 Writer<> debug_ranges(&owner_->debug_ranges_);
827 info_.WriteSecOffset(DW_AT_location, debug_loc.size());
828 info_.WriteSecOffset(DW_AT_start_scope, debug_ranges.size());
David Srbecky0fd295f2015-11-16 16:39:10 +0000829
David Srbecky996ed0b2015-11-27 10:27:11 +0000830 std::vector<VariableLocation> variable_locations = GetVariableLocations(
831 method_info,
832 vreg,
833 is64bitValue,
834 dex_pc_low,
835 dex_pc_high);
836
837 // Write .debug_loc entries.
David Srbecky0fd295f2015-11-16 16:39:10 +0000838 const InstructionSet isa = owner_->builder_->GetIsa();
839 const bool is64bit = Is64BitInstructionSet(isa);
David Srbecky91cb54e2016-01-15 13:47:59 +0000840 std::vector<uint8_t> expr_buffer;
David Srbecky996ed0b2015-11-27 10:27:11 +0000841 for (const VariableLocation& variable_location : variable_locations) {
David Srbecky0fd295f2015-11-16 16:39:10 +0000842 // Translate dex register location to DWARF expression.
843 // Note that 64-bit value might be split to two distinct locations.
844 // (for example, two 32-bit machine registers, or even stack and register)
David Srbecky91cb54e2016-01-15 13:47:59 +0000845 Expression expr(&expr_buffer);
David Srbecky996ed0b2015-11-27 10:27:11 +0000846 DexRegisterLocation reg_lo = variable_location.reg_lo;
847 DexRegisterLocation reg_hi = variable_location.reg_hi;
David Srbecky0fd295f2015-11-16 16:39:10 +0000848 for (int piece = 0; piece < (is64bitValue ? 2 : 1); piece++) {
849 DexRegisterLocation reg_loc = (piece == 0 ? reg_lo : reg_hi);
850 const Kind kind = reg_loc.GetKind();
851 const int32_t value = reg_loc.GetValue();
852 if (kind == Kind::kInStack) {
853 const size_t frame_size = method_info->compiled_method_->GetFrameSizeInBytes();
David Srbecky0fd295f2015-11-16 16:39:10 +0000854 // The stack offset is relative to SP. Make it relative to CFA.
David Srbecky91cb54e2016-01-15 13:47:59 +0000855 expr.WriteOpFbreg(value - frame_size);
David Srbecky0fd295f2015-11-16 16:39:10 +0000856 if (piece == 0 && reg_hi.GetKind() == Kind::kInStack &&
857 reg_hi.GetValue() == value + 4) {
858 break; // the high word is correctly implied by the low word.
859 }
860 } else if (kind == Kind::kInRegister) {
David Srbecky91cb54e2016-01-15 13:47:59 +0000861 expr.WriteOpReg(GetDwarfCoreReg(isa, value).num());
David Srbecky0fd295f2015-11-16 16:39:10 +0000862 if (piece == 0 && reg_hi.GetKind() == Kind::kInRegisterHigh &&
863 reg_hi.GetValue() == value) {
864 break; // the high word is correctly implied by the low word.
865 }
866 } else if (kind == Kind::kInFpuRegister) {
867 if ((isa == kArm || isa == kThumb2) &&
868 piece == 0 && reg_hi.GetKind() == Kind::kInFpuRegister &&
869 reg_hi.GetValue() == value + 1 && value % 2 == 0) {
870 // Translate S register pair to D register (e.g. S4+S5 to D2).
David Srbecky91cb54e2016-01-15 13:47:59 +0000871 expr.WriteOpReg(Reg::ArmDp(value / 2).num());
David Srbecky0fd295f2015-11-16 16:39:10 +0000872 break;
873 }
David Srbecky91cb54e2016-01-15 13:47:59 +0000874 expr.WriteOpReg(GetDwarfFpReg(isa, value).num());
David Srbecky0fd295f2015-11-16 16:39:10 +0000875 if (piece == 0 && reg_hi.GetKind() == Kind::kInFpuRegisterHigh &&
876 reg_hi.GetValue() == reg_lo.GetValue()) {
877 break; // the high word is correctly implied by the low word.
878 }
879 } else if (kind == Kind::kConstant) {
David Srbecky91cb54e2016-01-15 13:47:59 +0000880 expr.WriteOpConsts(value);
881 expr.WriteOpStackValue();
David Srbecky0fd295f2015-11-16 16:39:10 +0000882 } else if (kind == Kind::kNone) {
883 break;
884 } else {
885 // kInStackLargeOffset and kConstantLargeValue are hidden by GetKind().
886 // kInRegisterHigh and kInFpuRegisterHigh should be handled by
887 // the special cases above and they should not occur alone.
888 LOG(ERROR) << "Unexpected register location kind: "
889 << DexRegisterLocation::PrettyDescriptor(kind);
890 break;
891 }
892 if (is64bitValue) {
893 // Write the marker which is needed by split 64-bit values.
894 // This code is skipped by the special cases.
David Srbecky91cb54e2016-01-15 13:47:59 +0000895 expr.WriteOpPiece(4);
David Srbecky0fd295f2015-11-16 16:39:10 +0000896 }
897 }
898
David Srbecky91cb54e2016-01-15 13:47:59 +0000899 if (expr.size() > 0) {
David Srbecky0fd295f2015-11-16 16:39:10 +0000900 if (is64bit) {
David Srbecky996ed0b2015-11-27 10:27:11 +0000901 debug_loc.PushUint64(variable_location.low_pc - compilation_unit_low_pc);
902 debug_loc.PushUint64(variable_location.high_pc - compilation_unit_low_pc);
David Srbecky0fd295f2015-11-16 16:39:10 +0000903 } else {
David Srbecky996ed0b2015-11-27 10:27:11 +0000904 debug_loc.PushUint32(variable_location.low_pc - compilation_unit_low_pc);
905 debug_loc.PushUint32(variable_location.high_pc - compilation_unit_low_pc);
David Srbecky0fd295f2015-11-16 16:39:10 +0000906 }
907 // Write the expression.
David Srbecky91cb54e2016-01-15 13:47:59 +0000908 debug_loc.PushUint16(expr.size());
909 debug_loc.PushData(expr.data());
David Srbecky0fd295f2015-11-16 16:39:10 +0000910 } else {
David Srbecky996ed0b2015-11-27 10:27:11 +0000911 // Do not generate .debug_loc if the location is not known.
David Srbecky0fd295f2015-11-16 16:39:10 +0000912 }
913 }
914 // Write end-of-list entry.
915 if (is64bit) {
David Srbecky996ed0b2015-11-27 10:27:11 +0000916 debug_loc.PushUint64(0);
917 debug_loc.PushUint64(0);
David Srbecky0fd295f2015-11-16 16:39:10 +0000918 } else {
David Srbecky996ed0b2015-11-27 10:27:11 +0000919 debug_loc.PushUint32(0);
920 debug_loc.PushUint32(0);
921 }
922
923 // Write .debug_ranges entries.
924 // This includes ranges where the variable is in scope but the location is not known.
925 for (size_t i = 0; i < variable_locations.size(); i++) {
926 uint32_t low_pc = variable_locations[i].low_pc;
927 uint32_t high_pc = variable_locations[i].high_pc;
928 while (i + 1 < variable_locations.size() && variable_locations[i+1].low_pc == high_pc) {
929 // Merge address range with the next entry.
930 high_pc = variable_locations[++i].high_pc;
931 }
932 if (is64bit) {
933 debug_ranges.PushUint64(low_pc - compilation_unit_low_pc);
934 debug_ranges.PushUint64(high_pc - compilation_unit_low_pc);
935 } else {
936 debug_ranges.PushUint32(low_pc - compilation_unit_low_pc);
937 debug_ranges.PushUint32(high_pc - compilation_unit_low_pc);
938 }
939 }
940 // Write end-of-list entry.
941 if (is64bit) {
942 debug_ranges.PushUint64(0);
943 debug_ranges.PushUint64(0);
944 } else {
945 debug_ranges.PushUint32(0);
946 debug_ranges.PushUint32(0);
David Srbecky0fd295f2015-11-16 16:39:10 +0000947 }
948 }
949
David Srbecky04b05262015-11-09 18:05:48 +0000950 // Some types are difficult to define as we go since they need
951 // to be enclosed in the right set of namespaces. Therefore we
952 // just define all types lazily at the end of compilation unit.
953 void WriteLazyType(const char* type_descriptor) {
David Srbeckyb06e28e2015-12-10 13:15:00 +0000954 if (type_descriptor != nullptr && type_descriptor[0] != 'V') {
Tamas Berghammer86e42782016-01-05 14:29:02 +0000955 lazy_types_.emplace(std::string(type_descriptor), info_.size());
David Srbecky04b05262015-11-09 18:05:48 +0000956 info_.WriteRef4(DW_AT_type, 0);
957 }
958 }
959
960 void FinishLazyTypes() {
961 for (const auto& lazy_type : lazy_types_) {
Tamas Berghammer86e42782016-01-05 14:29:02 +0000962 info_.UpdateUint32(lazy_type.second, WriteTypeDeclaration(lazy_type.first));
David Srbecky04b05262015-11-09 18:05:48 +0000963 }
964 lazy_types_.clear();
965 }
966
967 private:
968 void WriteName(const char* name) {
David Srbeckyb06e28e2015-12-10 13:15:00 +0000969 if (name != nullptr) {
David Srbecky1c4aeb42016-02-01 15:37:32 +0000970 info_.WriteString(DW_AT_name, name);
David Srbeckyb06e28e2015-12-10 13:15:00 +0000971 }
David Srbecky04b05262015-11-09 18:05:48 +0000972 }
973
974 // Convert dex type descriptor to DWARF.
975 // Returns offset in the compilation unit.
Tamas Berghammer86e42782016-01-05 14:29:02 +0000976 size_t WriteTypeDeclaration(const std::string& desc) {
977 DCHECK(!desc.empty());
David Srbecky04b05262015-11-09 18:05:48 +0000978 const auto& it = type_cache_.find(desc);
979 if (it != type_cache_.end()) {
980 return it->second;
981 }
982
983 size_t offset;
Tamas Berghammer86e42782016-01-05 14:29:02 +0000984 if (desc[0] == 'L') {
David Srbecky04b05262015-11-09 18:05:48 +0000985 // Class type. For example: Lpackage/name;
Tamas Berghammer86e42782016-01-05 14:29:02 +0000986 size_t class_offset = StartClassTag(desc.c_str());
David Srbeckyfa5ec2b2016-01-29 15:13:19 +0000987 info_.WriteFlagPresent(DW_AT_declaration);
David Srbecky7138d452016-01-29 15:02:44 +0000988 EndClassTag();
Tamas Berghammer86e42782016-01-05 14:29:02 +0000989 // Reference to the class type.
990 offset = info_.StartTag(DW_TAG_reference_type);
991 info_.WriteRef(DW_AT_type, class_offset);
992 info_.EndTag();
993 } else if (desc[0] == '[') {
David Srbecky04b05262015-11-09 18:05:48 +0000994 // Array type.
Tamas Berghammer86e42782016-01-05 14:29:02 +0000995 size_t element_type = WriteTypeDeclaration(desc.substr(1));
David Srbecky7138d452016-01-29 15:02:44 +0000996 CloseNamespacesAboveDepth(0); // Declare in root namespace.
Tamas Berghammer86e42782016-01-05 14:29:02 +0000997 size_t array_type = info_.StartTag(DW_TAG_array_type);
David Srbeckyfa5ec2b2016-01-29 15:13:19 +0000998 info_.WriteFlagPresent(DW_AT_declaration);
David Srbecky04b05262015-11-09 18:05:48 +0000999 info_.WriteRef(DW_AT_type, element_type);
1000 info_.EndTag();
Tamas Berghammer86e42782016-01-05 14:29:02 +00001001 offset = info_.StartTag(DW_TAG_reference_type);
1002 info_.WriteRef4(DW_AT_type, array_type);
1003 info_.EndTag();
David Srbecky04b05262015-11-09 18:05:48 +00001004 } else {
1005 // Primitive types.
Tamas Berghammer03c941f2016-01-15 13:39:57 +00001006 DCHECK_EQ(desc.size(), 1u);
1007
David Srbecky04b05262015-11-09 18:05:48 +00001008 const char* name;
David Srbecky0fd295f2015-11-16 16:39:10 +00001009 uint32_t encoding;
1010 uint32_t byte_size;
Tamas Berghammer86e42782016-01-05 14:29:02 +00001011 switch (desc[0]) {
David Srbecky0fd295f2015-11-16 16:39:10 +00001012 case 'B':
1013 name = "byte";
1014 encoding = DW_ATE_signed;
1015 byte_size = 1;
1016 break;
1017 case 'C':
1018 name = "char";
1019 encoding = DW_ATE_UTF;
1020 byte_size = 2;
1021 break;
1022 case 'D':
1023 name = "double";
1024 encoding = DW_ATE_float;
1025 byte_size = 8;
1026 break;
1027 case 'F':
1028 name = "float";
1029 encoding = DW_ATE_float;
1030 byte_size = 4;
1031 break;
1032 case 'I':
1033 name = "int";
1034 encoding = DW_ATE_signed;
1035 byte_size = 4;
1036 break;
1037 case 'J':
1038 name = "long";
1039 encoding = DW_ATE_signed;
1040 byte_size = 8;
1041 break;
1042 case 'S':
1043 name = "short";
1044 encoding = DW_ATE_signed;
1045 byte_size = 2;
1046 break;
1047 case 'Z':
1048 name = "boolean";
1049 encoding = DW_ATE_boolean;
1050 byte_size = 1;
1051 break;
1052 case 'V':
1053 LOG(FATAL) << "Void type should not be encoded";
1054 UNREACHABLE();
David Srbecky04b05262015-11-09 18:05:48 +00001055 default:
Tamas Berghammer86e42782016-01-05 14:29:02 +00001056 LOG(FATAL) << "Unknown dex type descriptor: \"" << desc << "\"";
David Srbecky04b05262015-11-09 18:05:48 +00001057 UNREACHABLE();
1058 }
David Srbecky7138d452016-01-29 15:02:44 +00001059 CloseNamespacesAboveDepth(0); // Declare in root namespace.
David Srbecky04b05262015-11-09 18:05:48 +00001060 offset = info_.StartTag(DW_TAG_base_type);
1061 WriteName(name);
David Srbecky0fd295f2015-11-16 16:39:10 +00001062 info_.WriteData1(DW_AT_encoding, encoding);
1063 info_.WriteData1(DW_AT_byte_size, byte_size);
David Srbecky04b05262015-11-09 18:05:48 +00001064 info_.EndTag();
1065 }
1066
1067 type_cache_.emplace(desc, offset);
1068 return offset;
1069 }
1070
1071 // Start DW_TAG_class_type tag nested in DW_TAG_namespace tags.
1072 // Returns offset of the class tag in the compilation unit.
1073 size_t StartClassTag(const char* desc) {
David Srbecky7138d452016-01-29 15:02:44 +00001074 std::string name = SetNamespaceForClass(desc);
David Srbecky04b05262015-11-09 18:05:48 +00001075 size_t offset = info_.StartTag(DW_TAG_class_type);
David Srbecky7138d452016-01-29 15:02:44 +00001076 WriteName(name.c_str());
David Srbecky04b05262015-11-09 18:05:48 +00001077 return offset;
1078 }
1079
David Srbecky7138d452016-01-29 15:02:44 +00001080 void EndClassTag() {
David Srbecky04b05262015-11-09 18:05:48 +00001081 info_.EndTag();
David Srbecky7138d452016-01-29 15:02:44 +00001082 }
1083
1084 // Set the current namespace nesting to one required by the given class.
1085 // Returns the class name with namespaces, 'L', and ';' stripped.
1086 std::string SetNamespaceForClass(const char* desc) {
1087 DCHECK(desc != nullptr && desc[0] == 'L');
1088 desc++; // Skip the initial 'L'.
1089 size_t depth = 0;
1090 for (const char* end; (end = strchr(desc, '/')) != nullptr; desc = end + 1, ++depth) {
1091 // Check whether the name at this depth is already what we need.
1092 if (depth < current_namespace_.size()) {
1093 const std::string& name = current_namespace_[depth];
1094 if (name.compare(0, name.size(), desc, end - desc) == 0) {
1095 continue;
1096 }
1097 }
1098 // Otherwise we need to open a new namespace tag at this depth.
1099 CloseNamespacesAboveDepth(depth);
1100 info_.StartTag(DW_TAG_namespace);
1101 std::string name(desc, end - desc);
1102 WriteName(name.c_str());
1103 current_namespace_.push_back(std::move(name));
1104 }
1105 CloseNamespacesAboveDepth(depth);
1106 return std::string(desc, strchr(desc, ';') - desc);
1107 }
1108
1109 // Close namespace tags to reach the given nesting depth.
1110 void CloseNamespacesAboveDepth(size_t depth) {
1111 DCHECK_LE(depth, current_namespace_.size());
1112 while (current_namespace_.size() > depth) {
David Srbecky04b05262015-11-09 18:05:48 +00001113 info_.EndTag();
David Srbecky7138d452016-01-29 15:02:44 +00001114 current_namespace_.pop_back();
David Srbecky04b05262015-11-09 18:05:48 +00001115 }
1116 }
1117
1118 // For access to the ELF sections.
1119 DebugInfoWriter<ElfTypes>* owner_;
David Srbecky04b05262015-11-09 18:05:48 +00001120 // Temporary buffer to create and store the entries.
1121 DebugInfoEntryWriter<> info_;
1122 // Cache of already translated type descriptors.
Tamas Berghammer86e42782016-01-05 14:29:02 +00001123 std::map<std::string, size_t> type_cache_; // type_desc -> definition_offset.
David Srbecky04b05262015-11-09 18:05:48 +00001124 // 32-bit references which need to be resolved to a type later.
Tamas Berghammer86e42782016-01-05 14:29:02 +00001125 // Given type may be used multiple times. Therefore we need a multimap.
1126 std::multimap<std::string, size_t> lazy_types_; // type_desc -> patch_offset.
David Srbecky7138d452016-01-29 15:02:44 +00001127 // The current set of open namespace tags which are active and not closed yet.
1128 std::vector<std::string> current_namespace_;
David Srbecky04b05262015-11-09 18:05:48 +00001129 };
1130
David Srbeckyb851b492015-11-11 20:19:38 +00001131 public:
David Srbecky24868a12016-01-29 18:59:56 +00001132 explicit DebugInfoWriter(ElfBuilder<ElfTypes>* builder)
1133 : builder_(builder),
1134 debug_abbrev_(&debug_abbrev_buffer_) {
David Srbecky626a1662015-04-12 13:12:26 +01001135 }
1136
David Srbeckyb851b492015-11-11 20:19:38 +00001137 void Start() {
1138 builder_->GetDebugInfo()->Start();
David Srbecky799b8c42015-04-14 01:57:43 +01001139 }
1140
David Srbecky04b05262015-11-09 18:05:48 +00001141 void WriteCompilationUnit(const CompilationUnit& compilation_unit) {
1142 CompilationUnitWriter writer(this);
1143 writer.Write(compilation_unit);
David Srbeckyb851b492015-11-11 20:19:38 +00001144 }
David Srbecky3b9d57a2015-04-10 00:22:14 +01001145
Tamas Berghammer86e42782016-01-05 14:29:02 +00001146 void WriteTypes(const ArrayRef<mirror::Class*>& types) SHARED_REQUIRES(Locks::mutator_lock_) {
1147 CompilationUnitWriter writer(this);
1148 writer.Write(types);
1149 }
1150
David Srbecky579942f2016-01-28 20:01:28 +00001151 void End(bool write_oat_patches) {
David Srbeckyb851b492015-11-11 20:19:38 +00001152 builder_->GetDebugInfo()->End();
David Srbecky579942f2016-01-28 20:01:28 +00001153 if (write_oat_patches) {
1154 builder_->WritePatches(".debug_info.oat_patches",
1155 ArrayRef<const uintptr_t>(debug_info_patches_));
1156 }
David Srbecky24868a12016-01-29 18:59:56 +00001157 builder_->WriteSection(".debug_abbrev", &debug_abbrev_buffer_);
David Srbecky579942f2016-01-28 20:01:28 +00001158 if (!debug_loc_.empty()) {
1159 builder_->WriteSection(".debug_loc", &debug_loc_);
1160 }
1161 if (!debug_ranges_.empty()) {
1162 builder_->WriteSection(".debug_ranges", &debug_ranges_);
1163 }
David Srbeckyb851b492015-11-11 20:19:38 +00001164 }
1165
1166 private:
1167 ElfBuilder<ElfTypes>* builder_;
1168 std::vector<uintptr_t> debug_info_patches_;
David Srbecky24868a12016-01-29 18:59:56 +00001169 std::vector<uint8_t> debug_abbrev_buffer_;
1170 DebugAbbrevWriter<> debug_abbrev_;
David Srbecky0fd295f2015-11-16 16:39:10 +00001171 std::vector<uint8_t> debug_loc_;
David Srbecky996ed0b2015-11-27 10:27:11 +00001172 std::vector<uint8_t> debug_ranges_;
David Srbecky04b05262015-11-09 18:05:48 +00001173
1174 std::unordered_set<const char*> defined_dex_classes_; // For CHECKs only.
David Srbeckyb851b492015-11-11 20:19:38 +00001175};
1176
1177template<typename ElfTypes>
1178class DebugLineWriter {
1179 typedef typename ElfTypes::Addr Elf_Addr;
1180
1181 public:
1182 explicit DebugLineWriter(ElfBuilder<ElfTypes>* builder) : builder_(builder) {
1183 }
1184
1185 void Start() {
1186 builder_->GetDebugLine()->Start();
1187 }
1188
1189 // Write line table for given set of methods.
1190 // Returns the number of bytes written.
David Srbecky04b05262015-11-09 18:05:48 +00001191 size_t WriteCompilationUnit(CompilationUnit& compilation_unit) {
David Srbeckyb851b492015-11-11 20:19:38 +00001192 const bool is64bit = Is64BitInstructionSet(builder_->GetIsa());
David Srbecky5cc349f2015-12-18 15:04:48 +00001193 const Elf_Addr text_address = builder_->GetText()->Exists()
1194 ? builder_->GetText()->GetAddress()
1195 : 0;
David Srbecky04b05262015-11-09 18:05:48 +00001196
1197 compilation_unit.debug_line_offset_ = builder_->GetDebugLine()->GetSize();
David Srbeckyb851b492015-11-11 20:19:38 +00001198
David Srbecky799b8c42015-04-14 01:57:43 +01001199 std::vector<FileEntry> files;
1200 std::unordered_map<std::string, size_t> files_map;
1201 std::vector<std::string> directories;
1202 std::unordered_map<std::string, size_t> directories_map;
1203 int code_factor_bits_ = 0;
1204 int dwarf_isa = -1;
David Srbeckyb851b492015-11-11 20:19:38 +00001205 switch (builder_->GetIsa()) {
David Srbecky799b8c42015-04-14 01:57:43 +01001206 case kArm: // arm actually means thumb2.
1207 case kThumb2:
1208 code_factor_bits_ = 1; // 16-bit instuctions
1209 dwarf_isa = 1; // DW_ISA_ARM_thumb.
1210 break;
1211 case kArm64:
1212 case kMips:
1213 case kMips64:
1214 code_factor_bits_ = 2; // 32-bit instructions
1215 break;
1216 case kNone:
1217 case kX86:
1218 case kX86_64:
1219 break;
1220 }
David Srbecky297ed222015-04-15 01:18:12 +01001221 DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits_);
Vladimir Marko10c13562015-11-25 14:33:36 +00001222 for (const MethodDebugInfo* mi : compilation_unit.methods_) {
David Srbecky04b05262015-11-09 18:05:48 +00001223 // Ignore function if we have already generated line table for the same address.
1224 // It would confuse the debugger and the DWARF specification forbids it.
1225 if (mi->deduped_) {
1226 continue;
1227 }
1228
David Srbeckyf71b3ad2015-12-08 15:05:08 +00001229 ArrayRef<const SrcMapElem> src_mapping_table;
1230 std::vector<SrcMapElem> src_mapping_table_from_stack_maps;
1231 if (IsFromOptimizingCompiler(mi)) {
1232 // Use stack maps to create mapping table from pc to dex.
1233 const CodeInfo code_info(mi->compiled_method_->GetVmapTable().data());
1234 const StackMapEncoding encoding = code_info.ExtractEncoding();
1235 for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) {
1236 StackMap stack_map = code_info.GetStackMapAt(s, encoding);
1237 DCHECK(stack_map.IsValid());
David Srbecky4f50ee22016-01-25 17:00:24 +00001238 // Emit only locations where we have local-variable information.
1239 // In particular, skip mappings inside the prologue.
1240 if (stack_map.HasDexRegisterMap(encoding)) {
1241 const uint32_t pc = stack_map.GetNativePcOffset(encoding);
1242 const int32_t dex = stack_map.GetDexPc(encoding);
1243 src_mapping_table_from_stack_maps.push_back({pc, dex});
1244 }
David Srbeckyf71b3ad2015-12-08 15:05:08 +00001245 }
1246 std::sort(src_mapping_table_from_stack_maps.begin(),
1247 src_mapping_table_from_stack_maps.end());
1248 src_mapping_table = ArrayRef<const SrcMapElem>(src_mapping_table_from_stack_maps);
1249 } else {
1250 // Use the mapping table provided by the quick compiler.
1251 src_mapping_table = mi->compiled_method_->GetSrcMappingTable();
1252 }
1253
1254 if (src_mapping_table.empty()) {
1255 continue;
1256 }
1257
David Srbecky6d8c8f02015-10-26 10:57:09 +00001258 Elf_Addr method_address = text_address + mi->low_pc_;
1259
David Srbeckyb06e28e2015-12-10 13:15:00 +00001260 PositionInfos position_infos;
David Srbecky799b8c42015-04-14 01:57:43 +01001261 const DexFile* dex = mi->dex_file_;
David Srbeckyb06e28e2015-12-10 13:15:00 +00001262 if (!dex->DecodeDebugPositionInfo(mi->code_item_, PositionInfoCallback, &position_infos)) {
1263 continue;
David Srbecky3b9d57a2015-04-10 00:22:14 +01001264 }
1265
David Srbeckyb06e28e2015-12-10 13:15:00 +00001266 if (position_infos.empty()) {
David Srbeckyf71b3ad2015-12-08 15:05:08 +00001267 continue;
1268 }
1269
1270 opcodes.SetAddress(method_address);
1271 if (dwarf_isa != -1) {
1272 opcodes.SetISA(dwarf_isa);
1273 }
1274
David Srbecky799b8c42015-04-14 01:57:43 +01001275 // Get and deduplicate directory and filename.
1276 int file_index = 0; // 0 - primary source file of the compilation.
1277 auto& dex_class_def = dex->GetClassDef(mi->class_def_index_);
1278 const char* source_file = dex->GetSourceFile(dex_class_def);
1279 if (source_file != nullptr) {
1280 std::string file_name(source_file);
1281 size_t file_name_slash = file_name.find_last_of('/');
1282 std::string class_name(dex->GetClassDescriptor(dex_class_def));
1283 size_t class_name_slash = class_name.find_last_of('/');
1284 std::string full_path(file_name);
David Srbecky3b9d57a2015-04-10 00:22:14 +01001285
David Srbecky799b8c42015-04-14 01:57:43 +01001286 // Guess directory from package name.
1287 int directory_index = 0; // 0 - current directory of the compilation.
1288 if (file_name_slash == std::string::npos && // Just filename.
1289 class_name.front() == 'L' && // Type descriptor for a class.
1290 class_name_slash != std::string::npos) { // Has package name.
1291 std::string package_name = class_name.substr(1, class_name_slash - 1);
1292 auto it = directories_map.find(package_name);
1293 if (it == directories_map.end()) {
1294 directory_index = 1 + directories.size();
1295 directories_map.emplace(package_name, directory_index);
1296 directories.push_back(package_name);
1297 } else {
1298 directory_index = it->second;
1299 }
1300 full_path = package_name + "/" + file_name;
1301 }
1302
1303 // Add file entry.
1304 auto it2 = files_map.find(full_path);
1305 if (it2 == files_map.end()) {
1306 file_index = 1 + files.size();
1307 files_map.emplace(full_path, file_index);
1308 files.push_back(FileEntry {
1309 file_name,
1310 directory_index,
1311 0, // Modification time - NA.
1312 0, // File size - NA.
1313 });
1314 } else {
1315 file_index = it2->second;
1316 }
1317 }
1318 opcodes.SetFile(file_index);
1319
1320 // Generate mapping opcodes from PC to Java lines.
David Srbeckyb06e28e2015-12-10 13:15:00 +00001321 if (file_index != 0) {
David Srbecky799b8c42015-04-14 01:57:43 +01001322 bool first = true;
David Srbeckyf71b3ad2015-12-08 15:05:08 +00001323 for (SrcMapElem pc2dex : src_mapping_table) {
David Srbecky799b8c42015-04-14 01:57:43 +01001324 uint32_t pc = pc2dex.from_;
1325 int dex_pc = pc2dex.to_;
David Srbeckyb06e28e2015-12-10 13:15:00 +00001326 // Find mapping with address with is greater than our dex pc; then go back one step.
1327 auto ub = std::upper_bound(position_infos.begin(), position_infos.end(), dex_pc,
1328 [](uint32_t address, const DexFile::PositionInfo& entry) {
1329 return address < entry.address_;
1330 });
1331 if (ub != position_infos.begin()) {
1332 int line = (--ub)->line_;
David Srbecky799b8c42015-04-14 01:57:43 +01001333 if (first) {
1334 first = false;
1335 if (pc > 0) {
1336 // Assume that any preceding code is prologue.
David Srbeckyb06e28e2015-12-10 13:15:00 +00001337 int first_line = position_infos.front().line_;
David Srbecky799b8c42015-04-14 01:57:43 +01001338 // Prologue is not a sensible place for a breakpoint.
1339 opcodes.NegateStmt();
David Srbecky6d8c8f02015-10-26 10:57:09 +00001340 opcodes.AddRow(method_address, first_line);
David Srbecky799b8c42015-04-14 01:57:43 +01001341 opcodes.NegateStmt();
1342 opcodes.SetPrologueEnd();
1343 }
David Srbecky6d8c8f02015-10-26 10:57:09 +00001344 opcodes.AddRow(method_address + pc, line);
David Srbecky799b8c42015-04-14 01:57:43 +01001345 } else if (line != opcodes.CurrentLine()) {
David Srbecky6d8c8f02015-10-26 10:57:09 +00001346 opcodes.AddRow(method_address + pc, line);
David Srbecky3b9d57a2015-04-10 00:22:14 +01001347 }
David Srbecky3b9d57a2015-04-10 00:22:14 +01001348 }
1349 }
David Srbecky799b8c42015-04-14 01:57:43 +01001350 } else {
1351 // line 0 - instruction cannot be attributed to any source line.
David Srbecky6d8c8f02015-10-26 10:57:09 +00001352 opcodes.AddRow(method_address, 0);
David Srbecky3b9d57a2015-04-10 00:22:14 +01001353 }
David Srbeckyf71b3ad2015-12-08 15:05:08 +00001354
1355 opcodes.AdvancePC(text_address + mi->high_pc_);
1356 opcodes.EndSequence();
David Srbecky3b9d57a2015-04-10 00:22:14 +01001357 }
David Srbeckyb851b492015-11-11 20:19:38 +00001358 std::vector<uint8_t> buffer;
1359 buffer.reserve(opcodes.data()->size() + KB);
1360 size_t offset = builder_->GetDebugLine()->GetSize();
1361 WriteDebugLineTable(directories, files, opcodes, offset, &buffer, &debug_line_patches);
1362 builder_->GetDebugLine()->WriteFully(buffer.data(), buffer.size());
1363 return buffer.size();
David Srbecky3b9d57a2015-04-10 00:22:14 +01001364 }
David Srbeckyb851b492015-11-11 20:19:38 +00001365
David Srbecky579942f2016-01-28 20:01:28 +00001366 void End(bool write_oat_patches) {
David Srbeckyb851b492015-11-11 20:19:38 +00001367 builder_->GetDebugLine()->End();
David Srbecky579942f2016-01-28 20:01:28 +00001368 if (write_oat_patches) {
1369 builder_->WritePatches(".debug_line.oat_patches",
1370 ArrayRef<const uintptr_t>(debug_line_patches));
1371 }
David Srbeckyb851b492015-11-11 20:19:38 +00001372 }
1373
1374 private:
1375 ElfBuilder<ElfTypes>* builder_;
1376 std::vector<uintptr_t> debug_line_patches;
1377};
1378
1379template<typename ElfTypes>
Tamas Berghammer86e42782016-01-05 14:29:02 +00001380static void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
David Srbecky579942f2016-01-28 20:01:28 +00001381 const ArrayRef<const MethodDebugInfo>& method_infos,
1382 bool write_oat_patches) {
David Srbeckyb851b492015-11-11 20:19:38 +00001383 // Group the methods into compilation units based on source file.
1384 std::vector<CompilationUnit> compilation_units;
1385 const char* last_source_file = nullptr;
Vladimir Marko10c13562015-11-25 14:33:36 +00001386 for (const MethodDebugInfo& mi : method_infos) {
David Srbecky04b05262015-11-09 18:05:48 +00001387 auto& dex_class_def = mi.dex_file_->GetClassDef(mi.class_def_index_);
1388 const char* source_file = mi.dex_file_->GetSourceFile(dex_class_def);
1389 if (compilation_units.empty() || source_file != last_source_file) {
1390 compilation_units.push_back(CompilationUnit());
David Srbeckyb851b492015-11-11 20:19:38 +00001391 }
David Srbecky04b05262015-11-09 18:05:48 +00001392 CompilationUnit& cu = compilation_units.back();
1393 cu.methods_.push_back(&mi);
1394 cu.low_pc_ = std::min(cu.low_pc_, mi.low_pc_);
1395 cu.high_pc_ = std::max(cu.high_pc_, mi.high_pc_);
1396 last_source_file = source_file;
David Srbeckyb851b492015-11-11 20:19:38 +00001397 }
1398
1399 // Write .debug_line section.
Tamas Berghammer86e42782016-01-05 14:29:02 +00001400 if (!compilation_units.empty()) {
David Srbeckyb851b492015-11-11 20:19:38 +00001401 DebugLineWriter<ElfTypes> line_writer(builder);
1402 line_writer.Start();
David Srbeckyb851b492015-11-11 20:19:38 +00001403 for (auto& compilation_unit : compilation_units) {
David Srbecky04b05262015-11-09 18:05:48 +00001404 line_writer.WriteCompilationUnit(compilation_unit);
David Srbeckyb851b492015-11-11 20:19:38 +00001405 }
David Srbecky579942f2016-01-28 20:01:28 +00001406 line_writer.End(write_oat_patches);
David Srbeckyb851b492015-11-11 20:19:38 +00001407 }
1408
1409 // Write .debug_info section.
Tamas Berghammerfffbee42016-01-15 13:09:34 +00001410 if (!compilation_units.empty()) {
David Srbeckyb851b492015-11-11 20:19:38 +00001411 DebugInfoWriter<ElfTypes> info_writer(builder);
1412 info_writer.Start();
1413 for (const auto& compilation_unit : compilation_units) {
David Srbecky04b05262015-11-09 18:05:48 +00001414 info_writer.WriteCompilationUnit(compilation_unit);
David Srbeckyb851b492015-11-11 20:19:38 +00001415 }
David Srbecky579942f2016-01-28 20:01:28 +00001416 info_writer.End(write_oat_patches);
David Srbeckyb851b492015-11-11 20:19:38 +00001417 }
David Srbecky3b9d57a2015-04-10 00:22:14 +01001418}
1419
David Srbeckye0febdf2015-12-17 20:53:07 +00001420template <typename ElfTypes>
David Srbecky52886112016-01-22 13:56:47 +00001421static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
1422 const ArrayRef<const MethodDebugInfo>& method_infos,
1423 bool with_signature) {
David Srbeckye0febdf2015-12-17 20:53:07 +00001424 bool generated_mapping_symbol = false;
1425 auto* strtab = builder->GetStrTab();
1426 auto* symtab = builder->GetSymTab();
1427
1428 if (method_infos.empty()) {
1429 return;
1430 }
1431
1432 // Find all addresses (low_pc) which contain deduped methods.
1433 // The first instance of method is not marked deduped_, but the rest is.
1434 std::unordered_set<uint32_t> deduped_addresses;
1435 for (const MethodDebugInfo& info : method_infos) {
1436 if (info.deduped_) {
1437 deduped_addresses.insert(info.low_pc_);
1438 }
1439 }
1440
1441 strtab->Start();
1442 strtab->Write(""); // strtab should start with empty string.
David Srbecky52886112016-01-22 13:56:47 +00001443 std::string last_name;
1444 size_t last_name_offset = 0;
David Srbeckye0febdf2015-12-17 20:53:07 +00001445 for (const MethodDebugInfo& info : method_infos) {
1446 if (info.deduped_) {
1447 continue; // Add symbol only for the first instance.
1448 }
David Srbecky52886112016-01-22 13:56:47 +00001449 std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, with_signature);
David Srbeckye0febdf2015-12-17 20:53:07 +00001450 if (deduped_addresses.find(info.low_pc_) != deduped_addresses.end()) {
1451 name += " [DEDUPED]";
1452 }
David Srbecky52886112016-01-22 13:56:47 +00001453 // If we write method names without signature, we might see the same name multiple times.
1454 size_t name_offset = (name == last_name ? last_name_offset : strtab->Write(name));
David Srbeckye0febdf2015-12-17 20:53:07 +00001455
David Srbecky5cc349f2015-12-18 15:04:48 +00001456 const auto* text = builder->GetText()->Exists() ? builder->GetText() : nullptr;
1457 const bool is_relative = (text != nullptr);
David Srbeckye0febdf2015-12-17 20:53:07 +00001458 uint32_t low_pc = info.low_pc_;
1459 // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
1460 low_pc += info.compiled_method_->CodeDelta();
David Srbecky52886112016-01-22 13:56:47 +00001461 symtab->Add(name_offset,
1462 text,
1463 low_pc,
1464 is_relative,
1465 info.high_pc_ - info.low_pc_,
1466 STB_GLOBAL,
1467 STT_FUNC);
David Srbeckye0febdf2015-12-17 20:53:07 +00001468
1469 // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
1470 // instructions, so that disassembler tools can correctly disassemble.
1471 // Note that even if we generate just a single mapping symbol, ARM's Streamline
1472 // requires it to match function symbol. Just address 0 does not work.
1473 if (info.compiled_method_->GetInstructionSet() == kThumb2) {
1474 if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) {
David Srbecky5cc349f2015-12-18 15:04:48 +00001475 symtab->Add(strtab->Write("$t"), text, info.low_pc_ & ~1,
1476 is_relative, 0, STB_LOCAL, STT_NOTYPE);
David Srbeckye0febdf2015-12-17 20:53:07 +00001477 generated_mapping_symbol = true;
1478 }
1479 }
David Srbecky52886112016-01-22 13:56:47 +00001480
1481 last_name = std::move(name);
1482 last_name_offset = name_offset;
David Srbeckye0febdf2015-12-17 20:53:07 +00001483 }
1484 strtab->End();
1485
1486 // Symbols are buffered and written after names (because they are smaller).
1487 // We could also do two passes in this function to avoid the buffering.
1488 symtab->Start();
1489 symtab->Write();
1490 symtab->End();
1491}
1492
1493template <typename ElfTypes>
1494void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
1495 const ArrayRef<const MethodDebugInfo>& method_infos,
David Srbecky579942f2016-01-28 20:01:28 +00001496 CFIFormat cfi_format,
1497 bool write_oat_patches) {
Tamas Berghammer86e42782016-01-05 14:29:02 +00001498 // Add methods to .symtab.
David Srbecky52886112016-01-22 13:56:47 +00001499 WriteDebugSymbols(builder, method_infos, true /* with_signature */);
Tamas Berghammer86e42782016-01-05 14:29:02 +00001500 // Generate CFI (stack unwinding information).
David Srbecky579942f2016-01-28 20:01:28 +00001501 WriteCFISection(builder, method_infos, cfi_format, write_oat_patches);
Tamas Berghammer86e42782016-01-05 14:29:02 +00001502 // Write DWARF .debug_* sections.
David Srbecky579942f2016-01-28 20:01:28 +00001503 WriteDebugSections(builder, method_infos, write_oat_patches);
David Srbeckye0febdf2015-12-17 20:53:07 +00001504}
1505
David Srbecky5b1c2ca2016-01-25 17:32:41 +00001506static void XzCompress(const std::vector<uint8_t>* src, std::vector<uint8_t>* dst) {
1507 // Configure the compression library.
1508 CrcGenerateTable();
1509 Crc64GenerateTable();
1510 CLzma2EncProps lzma2Props;
1511 Lzma2EncProps_Init(&lzma2Props);
1512 lzma2Props.lzmaProps.level = 1; // Fast compression.
1513 Lzma2EncProps_Normalize(&lzma2Props);
1514 CXzProps props;
1515 XzProps_Init(&props);
1516 props.lzma2Props = &lzma2Props;
1517 // Implement the required interface for communication (written in C so no virtual methods).
1518 struct XzCallbacks : public ISeqInStream, public ISeqOutStream, public ICompressProgress {
1519 static SRes ReadImpl(void* p, void* buf, size_t* size) {
1520 auto* ctx = static_cast<XzCallbacks*>(reinterpret_cast<ISeqInStream*>(p));
1521 *size = std::min(*size, ctx->src_->size() - ctx->src_pos_);
1522 memcpy(buf, ctx->src_->data() + ctx->src_pos_, *size);
1523 ctx->src_pos_ += *size;
1524 return SZ_OK;
1525 }
1526 static size_t WriteImpl(void* p, const void* buf, size_t size) {
1527 auto* ctx = static_cast<XzCallbacks*>(reinterpret_cast<ISeqOutStream*>(p));
1528 const uint8_t* buffer = reinterpret_cast<const uint8_t*>(buf);
1529 ctx->dst_->insert(ctx->dst_->end(), buffer, buffer + size);
1530 return size;
1531 }
1532 static SRes ProgressImpl(void* , UInt64, UInt64) {
1533 return SZ_OK;
1534 }
1535 size_t src_pos_;
1536 const std::vector<uint8_t>* src_;
1537 std::vector<uint8_t>* dst_;
1538 };
1539 XzCallbacks callbacks;
1540 callbacks.Read = XzCallbacks::ReadImpl;
1541 callbacks.Write = XzCallbacks::WriteImpl;
1542 callbacks.Progress = XzCallbacks::ProgressImpl;
1543 callbacks.src_pos_ = 0;
1544 callbacks.src_ = src;
1545 callbacks.dst_ = dst;
1546 // Compress.
1547 SRes res = Xz_Encode(&callbacks, &callbacks, &props, &callbacks);
1548 CHECK_EQ(res, SZ_OK);
1549}
1550
1551template <typename ElfTypes>
1552void WriteMiniDebugInfo(ElfBuilder<ElfTypes>* parent_builder,
1553 const ArrayRef<const MethodDebugInfo>& method_infos) {
1554 const InstructionSet isa = parent_builder->GetIsa();
1555 std::vector<uint8_t> buffer;
1556 buffer.reserve(KB);
1557 VectorOutputStream out("Mini-debug-info ELF file", &buffer);
1558 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
1559 builder->Start();
1560 // Write .rodata and .text as NOBITS sections.
1561 // This allows tools to detect virtual address relocation of the parent ELF file.
1562 builder->SetVirtualAddress(parent_builder->GetRoData()->GetAddress());
1563 builder->GetRoData()->WriteNoBitsSection(parent_builder->GetRoData()->GetSize());
1564 builder->SetVirtualAddress(parent_builder->GetText()->GetAddress());
1565 builder->GetText()->WriteNoBitsSection(parent_builder->GetText()->GetSize());
David Srbecky52886112016-01-22 13:56:47 +00001566 WriteDebugSymbols(builder.get(), method_infos, false /* with_signature */);
David Srbecky5e974a62016-01-22 14:25:03 +00001567 WriteCFISection(builder.get(), method_infos, DW_DEBUG_FRAME_FORMAT, false /* write_oat_paches */);
David Srbecky5b1c2ca2016-01-25 17:32:41 +00001568 builder->End();
1569 CHECK(builder->Good());
1570 std::vector<uint8_t> compressed_buffer;
1571 compressed_buffer.reserve(buffer.size() / 4);
1572 XzCompress(&buffer, &compressed_buffer);
1573 parent_builder->WriteSection(".gnu_debugdata", &compressed_buffer);
1574}
1575
David Srbecky5cc349f2015-12-18 15:04:48 +00001576template <typename ElfTypes>
Tamas Berghammer86e42782016-01-05 14:29:02 +00001577static ArrayRef<const uint8_t> WriteDebugElfFileForMethodInternal(
David Srbecky5cc349f2015-12-18 15:04:48 +00001578 const dwarf::MethodDebugInfo& method_info) {
1579 const InstructionSet isa = method_info.compiled_method_->GetInstructionSet();
1580 std::vector<uint8_t> buffer;
1581 buffer.reserve(KB);
1582 VectorOutputStream out("Debug ELF file", &buffer);
1583 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
David Srbecky579942f2016-01-28 20:01:28 +00001584 // No program headers since the ELF file is not linked and has no allocated sections.
1585 builder->Start(false /* write_program_headers */);
David Srbecky5cc349f2015-12-18 15:04:48 +00001586 WriteDebugInfo(builder.get(),
1587 ArrayRef<const MethodDebugInfo>(&method_info, 1),
David Srbecky579942f2016-01-28 20:01:28 +00001588 DW_DEBUG_FRAME_FORMAT,
1589 false /* write_oat_patches */);
David Srbecky5cc349f2015-12-18 15:04:48 +00001590 builder->End();
1591 CHECK(builder->Good());
1592 // Make a copy of the buffer. We want to shrink it anyway.
1593 uint8_t* result = new uint8_t[buffer.size()];
1594 CHECK(result != nullptr);
1595 memcpy(result, buffer.data(), buffer.size());
1596 return ArrayRef<const uint8_t>(result, buffer.size());
1597}
1598
Tamas Berghammer86e42782016-01-05 14:29:02 +00001599ArrayRef<const uint8_t> WriteDebugElfFileForMethod(const dwarf::MethodDebugInfo& method_info) {
David Srbecky5cc349f2015-12-18 15:04:48 +00001600 const InstructionSet isa = method_info.compiled_method_->GetInstructionSet();
1601 if (Is64BitInstructionSet(isa)) {
Tamas Berghammer86e42782016-01-05 14:29:02 +00001602 return WriteDebugElfFileForMethodInternal<ElfTypes64>(method_info);
David Srbecky5cc349f2015-12-18 15:04:48 +00001603 } else {
Tamas Berghammer86e42782016-01-05 14:29:02 +00001604 return WriteDebugElfFileForMethodInternal<ElfTypes32>(method_info);
1605 }
1606}
1607
1608template <typename ElfTypes>
Tamas Berghammerfffbee42016-01-15 13:09:34 +00001609static ArrayRef<const uint8_t> WriteDebugElfFileForClassesInternal(
1610 const InstructionSet isa, const ArrayRef<mirror::Class*>& types)
Tamas Berghammer86e42782016-01-05 14:29:02 +00001611 SHARED_REQUIRES(Locks::mutator_lock_) {
1612 std::vector<uint8_t> buffer;
1613 buffer.reserve(KB);
1614 VectorOutputStream out("Debug ELF file", &buffer);
1615 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
David Srbecky579942f2016-01-28 20:01:28 +00001616 // No program headers since the ELF file is not linked and has no allocated sections.
1617 builder->Start(false /* write_program_headers */);
Tamas Berghammer86e42782016-01-05 14:29:02 +00001618 DebugInfoWriter<ElfTypes> info_writer(builder.get());
1619 info_writer.Start();
Tamas Berghammerfffbee42016-01-15 13:09:34 +00001620 info_writer.WriteTypes(types);
David Srbecky579942f2016-01-28 20:01:28 +00001621 info_writer.End(false /* write_oat_patches */);
Tamas Berghammer86e42782016-01-05 14:29:02 +00001622
1623 builder->End();
1624 CHECK(builder->Good());
1625 // Make a copy of the buffer. We want to shrink it anyway.
1626 uint8_t* result = new uint8_t[buffer.size()];
1627 CHECK(result != nullptr);
1628 memcpy(result, buffer.data(), buffer.size());
1629 return ArrayRef<const uint8_t>(result, buffer.size());
1630}
1631
Tamas Berghammerfffbee42016-01-15 13:09:34 +00001632ArrayRef<const uint8_t> WriteDebugElfFileForClasses(const InstructionSet isa,
1633 const ArrayRef<mirror::Class*>& types) {
Tamas Berghammer86e42782016-01-05 14:29:02 +00001634 if (Is64BitInstructionSet(isa)) {
Tamas Berghammerfffbee42016-01-15 13:09:34 +00001635 return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, types);
Tamas Berghammer86e42782016-01-05 14:29:02 +00001636 } else {
Tamas Berghammerfffbee42016-01-15 13:09:34 +00001637 return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, types);
David Srbecky5cc349f2015-12-18 15:04:48 +00001638 }
1639}
1640
David Srbecky6d8c8f02015-10-26 10:57:09 +00001641// Explicit instantiations
David Srbeckye0febdf2015-12-17 20:53:07 +00001642template void WriteDebugInfo<ElfTypes32>(
David Srbecky6d8c8f02015-10-26 10:57:09 +00001643 ElfBuilder<ElfTypes32>* builder,
Vladimir Marko10c13562015-11-25 14:33:36 +00001644 const ArrayRef<const MethodDebugInfo>& method_infos,
David Srbecky579942f2016-01-28 20:01:28 +00001645 CFIFormat cfi_format,
1646 bool write_oat_patches);
David Srbeckye0febdf2015-12-17 20:53:07 +00001647template void WriteDebugInfo<ElfTypes64>(
David Srbecky6d8c8f02015-10-26 10:57:09 +00001648 ElfBuilder<ElfTypes64>* builder,
Vladimir Marko10c13562015-11-25 14:33:36 +00001649 const ArrayRef<const MethodDebugInfo>& method_infos,
David Srbecky579942f2016-01-28 20:01:28 +00001650 CFIFormat cfi_format,
1651 bool write_oat_patches);
David Srbecky5b1c2ca2016-01-25 17:32:41 +00001652template void WriteMiniDebugInfo<ElfTypes32>(
1653 ElfBuilder<ElfTypes32>* builder,
1654 const ArrayRef<const MethodDebugInfo>& method_infos);
1655template void WriteMiniDebugInfo<ElfTypes64>(
1656 ElfBuilder<ElfTypes64>* builder,
1657 const ArrayRef<const MethodDebugInfo>& method_infos);
David Srbecky6d8c8f02015-10-26 10:57:09 +00001658
David Srbecky3b9d57a2015-04-10 00:22:14 +01001659} // namespace dwarf
1660} // namespace art