blob: 2756af18226ee7b68ab060e35c99de3e2bd0ee81 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2012 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_quick.h"
18
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070019#include <unordered_map>
20
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include "base/logging.h"
22#include "base/unix_file/fd_file.h"
Brian Carlstromc6dfdac2013-08-26 18:57:31 -070023#include "buffered_output_stream.h"
Vladimir Marko20f85592015-03-19 10:07:02 +000024#include "compiled_method.h"
David Srbecky0df9e1f2015-04-07 19:02:58 +010025#include "dex_file-inl.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070026#include "driver/compiler_driver.h"
Vladimir Marko20f85592015-03-19 10:07:02 +000027#include "driver/compiler_options.h"
Alex Light3470ab42014-06-18 10:35:45 -070028#include "dwarf.h"
David Srbecky6f715892015-03-30 14:21:42 +010029#include "dwarf/debug_frame_writer.h"
30#include "dwarf/debug_line_writer.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070031#include "elf_builder.h"
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070032#include "elf_file.h"
Nicolas Geoffray50cfe742014-02-19 13:27:42 +000033#include "elf_utils.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070034#include "file_output_stream.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070035#include "globals.h"
Andreas Gampe79273802014-08-05 20:21:05 -070036#include "leb128.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070037#include "oat.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070038#include "oat_writer.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070039#include "utils.h"
40
41namespace art {
42
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070043static void PushByte(std::vector<uint8_t>* buf, int data) {
44 buf->push_back(data & 0xff);
45}
46
47static uint32_t PushStr(std::vector<uint8_t>* buf, const char* str, const char* def = nullptr) {
48 if (str == nullptr) {
49 str = def;
50 }
51
52 uint32_t offset = buf->size();
53 for (size_t i = 0; str[i] != '\0'; ++i) {
54 buf->push_back(str[i]);
55 }
56 buf->push_back('\0');
57 return offset;
58}
59
60static uint32_t PushStr(std::vector<uint8_t>* buf, const std::string &str) {
61 uint32_t offset = buf->size();
62 buf->insert(buf->end(), str.begin(), str.end());
63 buf->push_back('\0');
64 return offset;
65}
66
Andreas Gampe79273802014-08-05 20:21:05 -070067static void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) {
68 (*buf)[offset+0] = data;
69 (*buf)[offset+1] = data >> 8;
70 (*buf)[offset+2] = data >> 16;
71 (*buf)[offset+3] = data >> 24;
72}
73
Andreas Gampe79273802014-08-05 20:21:05 -070074static void PushHalf(std::vector<uint8_t>* buf, int data) {
75 buf->push_back(data & 0xff);
76 buf->push_back((data >> 8) & 0xff);
77}
78
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000079template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
80 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
81 typename Elf_Phdr, typename Elf_Shdr>
82bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000083 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Create(File* elf_file,
Brian Carlstromb12f3472014-06-11 14:54:46 -070084 OatWriter* oat_writer,
85 const std::vector<const DexFile*>& dex_files,
86 const std::string& android_root,
87 bool is_host,
88 const CompilerDriver& driver) {
89 ElfWriterQuick elf_writer(driver, elf_file);
90 return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
91}
92
David Srbecky1109fb32015-04-07 20:21:06 +010093void WriteCIE(dwarf::DebugFrameWriter<>* cfi, InstructionSet isa) {
94 // Scratch registers should be marked as undefined. This tells the
95 // debugger that its value in the previous frame is not recoverable.
96 switch (isa) {
97 case kArm:
98 case kThumb2: {
99 dwarf::DebugFrameOpCodeWriter<> opcodes;
100 opcodes.DefCFA(dwarf::Reg::ArmCore(13), 0); // R13(SP).
101 // core registers.
102 for (int reg = 0; reg < 13; reg++) {
103 if (reg < 4 || reg == 12) {
104 opcodes.Undefined(dwarf::Reg::ArmCore(reg));
105 } else {
106 opcodes.SameValue(dwarf::Reg::ArmCore(reg));
107 }
108 }
109 // fp registers.
110 for (int reg = 0; reg < 32; reg++) {
111 if (reg < 16) {
112 opcodes.Undefined(dwarf::Reg::ArmFp(reg));
113 } else {
114 opcodes.SameValue(dwarf::Reg::ArmFp(reg));
115 }
116 }
117 auto return_address_reg = dwarf::Reg::ArmCore(14); // R14(LR).
118 cfi->WriteCIE(return_address_reg, opcodes);
119 return;
120 }
121 case kArm64: {
122 dwarf::DebugFrameOpCodeWriter<> opcodes;
123 opcodes.DefCFA(dwarf::Reg::Arm64Core(31), 0); // R31(SP).
124 // core registers.
125 for (int reg = 0; reg < 30; reg++) {
126 if (reg < 8 || reg == 16 || reg == 17) {
127 opcodes.Undefined(dwarf::Reg::Arm64Core(reg));
128 } else {
129 opcodes.SameValue(dwarf::Reg::Arm64Core(reg));
130 }
131 }
132 // fp registers.
133 for (int reg = 0; reg < 32; reg++) {
134 if (reg < 8 || reg >= 16) {
135 opcodes.Undefined(dwarf::Reg::Arm64Fp(reg));
136 } else {
137 opcodes.SameValue(dwarf::Reg::Arm64Fp(reg));
138 }
139 }
140 auto return_address_reg = dwarf::Reg::Arm64Core(30); // R30(LR).
141 cfi->WriteCIE(return_address_reg, opcodes);
142 return;
143 }
144 case kMips:
145 case kMips64: {
146 dwarf::DebugFrameOpCodeWriter<> opcodes;
147 opcodes.DefCFA(dwarf::Reg::MipsCore(29), 0); // R29(SP).
148 // core registers.
149 for (int reg = 1; reg < 26; reg++) {
150 if (reg < 16 || reg == 24 || reg == 25) { // AT, V*, A*, T*.
151 opcodes.Undefined(dwarf::Reg::MipsCore(reg));
152 } else {
153 opcodes.SameValue(dwarf::Reg::MipsCore(reg));
154 }
155 }
156 auto return_address_reg = dwarf::Reg::MipsCore(31); // R31(RA).
157 cfi->WriteCIE(return_address_reg, opcodes);
158 return;
159 }
160 case kX86: {
161 dwarf::DebugFrameOpCodeWriter<> opcodes;
162 opcodes.DefCFA(dwarf::Reg::X86Core(4), 4); // R4(ESP).
163 opcodes.Offset(dwarf::Reg::X86Core(8), -4); // R8(EIP).
164 // core registers.
165 for (int reg = 0; reg < 8; reg++) {
166 if (reg <= 3) {
167 opcodes.Undefined(dwarf::Reg::X86Core(reg));
168 } else if (reg == 4) {
169 // Stack pointer.
170 } else {
171 opcodes.SameValue(dwarf::Reg::X86Core(reg));
172 }
173 }
174 // fp registers.
175 for (int reg = 0; reg < 8; reg++) {
176 opcodes.Undefined(dwarf::Reg::X86Fp(reg));
177 }
178 auto return_address_reg = dwarf::Reg::X86Core(8); // R8(EIP).
179 cfi->WriteCIE(return_address_reg, opcodes);
180 return;
181 }
182 case kX86_64: {
183 dwarf::DebugFrameOpCodeWriter<> opcodes;
184 opcodes.DefCFA(dwarf::Reg::X86_64Core(4), 8); // R4(RSP).
185 opcodes.Offset(dwarf::Reg::X86_64Core(16), -8); // R16(RIP).
186 // core registers.
187 for (int reg = 0; reg < 16; reg++) {
188 if (reg == 4) {
189 // Stack pointer.
190 } else if (reg < 12 && reg != 3 && reg != 5) { // except EBX and EBP.
191 opcodes.Undefined(dwarf::Reg::X86_64Core(reg));
192 } else {
193 opcodes.SameValue(dwarf::Reg::X86_64Core(reg));
194 }
195 }
196 // fp registers.
197 for (int reg = 0; reg < 16; reg++) {
198 if (reg < 12) {
199 opcodes.Undefined(dwarf::Reg::X86_64Fp(reg));
200 } else {
201 opcodes.SameValue(dwarf::Reg::X86_64Fp(reg));
202 }
203 }
204 auto return_address_reg = dwarf::Reg::X86_64Core(16); // R16(RIP).
205 cfi->WriteCIE(return_address_reg, opcodes);
206 return;
207 }
208 case kNone:
209 break;
210 }
211 LOG(FATAL) << "Can not write CIE frame for ISA " << isa;
212 UNREACHABLE();
213}
214
Ian Rogers0279ebb2014-10-08 17:27:48 -0700215class OatWriterWrapper FINAL : public CodeOutput {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700216 public:
217 explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {}
218
Vladimir Markof4da6752014-08-01 19:04:18 +0100219 void SetCodeOffset(size_t offset) {
220 oat_writer_->SetOatDataOffset(offset);
221 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700222 bool Write(OutputStream* out) OVERRIDE {
223 return oat_writer_->Write(out);
224 }
225 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700226 OatWriter* const oat_writer_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700227};
228
229template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
230 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
231 typename Elf_Phdr, typename Elf_Shdr>
232static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
233 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
234 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
235 OatWriter* oat_writer);
236
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000237template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
238 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
239 typename Elf_Phdr, typename Elf_Shdr>
240bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
241 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Write(OatWriter* oat_writer,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700242 const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED,
243 const std::string& android_root_unused ATTRIBUTE_UNUSED,
244 bool is_host_unused ATTRIBUTE_UNUSED) {
Andreas Gampe79273802014-08-05 20:21:05 -0700245 constexpr bool debug = false;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700246 const OatHeader& oat_header = oat_writer->GetOatHeader();
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000247 Elf_Word oat_data_size = oat_header.GetExecutableOffset();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700248 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
Vladimir Marko5c42c292015-02-25 12:02:49 +0000249 uint32_t oat_bss_size = oat_writer->GetBssSize();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700250
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700251 OatWriterWrapper wrapper(oat_writer);
252
253 std::unique_ptr<ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
254 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> > builder(
255 new ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
256 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>(
257 &wrapper,
258 elf_file_,
259 compiler_driver_->GetInstructionSet(),
260 0,
261 oat_data_size,
262 oat_data_size,
263 oat_exec_size,
Vladimir Marko5c42c292015-02-25 12:02:49 +0000264 RoundUp(oat_data_size + oat_exec_size, kPageSize),
265 oat_bss_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700266 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
267 debug));
Alex Light78382fa2014-06-06 15:45:32 -0700268
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700269 if (!builder->Init()) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700270 return false;
271 }
272
Andreas Gampe79273802014-08-05 20:21:05 -0700273 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700274 WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700275 }
276
Alex Light53cb16b2014-06-12 11:26:29 -0700277 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700278 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches(
279 ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, sizeof(uintptr_t), sizeof(uintptr_t));
Vladimir Markof4da6752014-08-01 19:04:18 +0100280 const std::vector<uintptr_t>& locations = oat_writer->GetAbsolutePatchLocations();
281 const uint8_t* begin = reinterpret_cast<const uint8_t*>(&locations[0]);
282 const uint8_t* end = begin + locations.size() * sizeof(locations[0]);
283 oat_patches.GetBuffer()->assign(begin, end);
284 if (debug) {
285 LOG(INFO) << "Prepared .oat_patches for " << locations.size() << " patches.";
286 }
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700287 builder->RegisterRawSection(oat_patches);
Alex Light53cb16b2014-06-12 11:26:29 -0700288 }
289
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700290 return builder->Write();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700291}
Mark Mendellae9fd932014-02-10 16:14:35 -0800292
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700293/*
294 * @brief Generate the DWARF debug_info and debug_abbrev sections
295 * @param oat_writer The Oat file Writer.
296 * @param dbg_info Compilation unit information.
297 * @param dbg_abbrev Abbreviations used to generate dbg_info.
298 * @param dbg_str Debug strings.
299 */
300static void FillInCFIInformation(OatWriter* oat_writer,
301 std::vector<uint8_t>* dbg_info,
302 std::vector<uint8_t>* dbg_abbrev,
303 std::vector<uint8_t>* dbg_str,
304 std::vector<uint8_t>* dbg_line,
305 uint32_t text_section_offset) {
David Srbecky6f715892015-03-30 14:21:42 +0100306 const std::vector<OatWriter::DebugInfo>& method_infos = oat_writer->GetCFIMethodInfo();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700307
308 uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
309
David Srbecky6f715892015-03-30 14:21:42 +0100310 constexpr bool use_64bit_addresses = false;
311
Mark Mendellae9fd932014-02-10 16:14:35 -0800312 // Create the debug_abbrev section with boilerplate information.
313 // We only care about low_pc and high_pc right now for the compilation
314 // unit and methods.
315
316 // Tag 1: Compilation unit: DW_TAG_compile_unit.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700317 PushByte(dbg_abbrev, 1);
David Srbecky6f715892015-03-30 14:21:42 +0100318 PushByte(dbg_abbrev, dwarf::DW_TAG_compile_unit);
Mark Mendellae9fd932014-02-10 16:14:35 -0800319
320 // There are children (the methods).
David Srbecky6f715892015-03-30 14:21:42 +0100321 PushByte(dbg_abbrev, dwarf::DW_CHILDREN_yes);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700322
323 // DW_AT_producer DW_FORM_data1.
324 // REVIEW: we can get rid of dbg_str section if
325 // DW_FORM_string (immediate string) was used everywhere instead of
326 // DW_FORM_strp (ref to string from .debug_str section).
327 // DW_FORM_strp makes sense only if we reuse the strings.
David Srbecky6f715892015-03-30 14:21:42 +0100328 PushByte(dbg_abbrev, dwarf::DW_AT_producer);
329 PushByte(dbg_abbrev, dwarf::DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800330
331 // DW_LANG_Java DW_FORM_data1.
David Srbecky6f715892015-03-30 14:21:42 +0100332 PushByte(dbg_abbrev, dwarf::DW_AT_language);
333 PushByte(dbg_abbrev, dwarf::DW_FORM_data1);
Mark Mendellae9fd932014-02-10 16:14:35 -0800334
335 // DW_AT_low_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100336 PushByte(dbg_abbrev, dwarf::DW_AT_low_pc);
337 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800338
339 // DW_AT_high_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100340 PushByte(dbg_abbrev, dwarf::DW_AT_high_pc);
341 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700342
343 if (dbg_line != nullptr) {
344 // DW_AT_stmt_list DW_FORM_sec_offset.
David Srbecky6f715892015-03-30 14:21:42 +0100345 PushByte(dbg_abbrev, dwarf::DW_AT_stmt_list);
346 PushByte(dbg_abbrev, dwarf::DW_FORM_data4);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700347 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800348
349 // End of DW_TAG_compile_unit.
David Srbecky6f715892015-03-30 14:21:42 +0100350 PushByte(dbg_abbrev, 0); // DW_AT.
351 PushByte(dbg_abbrev, 0); // DW_FORM.
Mark Mendellae9fd932014-02-10 16:14:35 -0800352
353 // Tag 2: Compilation unit: DW_TAG_subprogram.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700354 PushByte(dbg_abbrev, 2);
David Srbecky6f715892015-03-30 14:21:42 +0100355 PushByte(dbg_abbrev, dwarf::DW_TAG_subprogram);
Mark Mendellae9fd932014-02-10 16:14:35 -0800356
357 // There are no children.
David Srbecky6f715892015-03-30 14:21:42 +0100358 PushByte(dbg_abbrev, dwarf::DW_CHILDREN_no);
Mark Mendellae9fd932014-02-10 16:14:35 -0800359
360 // Name of the method.
David Srbecky6f715892015-03-30 14:21:42 +0100361 PushByte(dbg_abbrev, dwarf::DW_AT_name);
362 PushByte(dbg_abbrev, dwarf::DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800363
364 // DW_AT_low_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100365 PushByte(dbg_abbrev, dwarf::DW_AT_low_pc);
366 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800367
368 // DW_AT_high_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100369 PushByte(dbg_abbrev, dwarf::DW_AT_high_pc);
370 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800371
372 // End of DW_TAG_subprogram.
David Srbecky6f715892015-03-30 14:21:42 +0100373 PushByte(dbg_abbrev, 0); // DW_AT.
374 PushByte(dbg_abbrev, 0); // DW_FORM.
375
376 // End of abbrevs for compilation unit
377 PushByte(dbg_abbrev, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800378
379 // Start the debug_info section with the header information
380 // 'unit_length' will be filled in later.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700381 int cunit_length = dbg_info->size();
Vladimir Marko80b96d12015-02-19 15:50:28 +0000382 Push32(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800383
384 // 'version' - 3.
385 PushHalf(dbg_info, 3);
386
387 // Offset into .debug_abbrev section (always 0).
Vladimir Marko80b96d12015-02-19 15:50:28 +0000388 Push32(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800389
David Srbecky6f715892015-03-30 14:21:42 +0100390 // Address size: 4 or 8.
391 PushByte(dbg_info, use_64bit_addresses ? 8 : 4);
Mark Mendellae9fd932014-02-10 16:14:35 -0800392
393 // Start the description for the compilation unit.
394 // This uses tag 1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700395 PushByte(dbg_info, 1);
396
397 // The producer is Android dex2oat.
Vladimir Marko80b96d12015-02-19 15:50:28 +0000398 Push32(dbg_info, producer_str_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800399
400 // The language is Java.
David Srbecky6f715892015-03-30 14:21:42 +0100401 PushByte(dbg_info, dwarf::DW_LANG_Java);
Mark Mendellae9fd932014-02-10 16:14:35 -0800402
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700403 // low_pc and high_pc.
David Srbecky6f715892015-03-30 14:21:42 +0100404 uint32_t cunit_low_pc = static_cast<uint32_t>(-1);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700405 uint32_t cunit_high_pc = 0;
David Srbecky6f715892015-03-30 14:21:42 +0100406 for (auto method_info : method_infos) {
407 cunit_low_pc = std::min(cunit_low_pc, method_info.low_pc_);
408 cunit_high_pc = std::max(cunit_high_pc, method_info.high_pc_);
409 }
410 Push32(dbg_info, cunit_low_pc + text_section_offset);
411 Push32(dbg_info, cunit_high_pc + text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800412
David Srbecky6f715892015-03-30 14:21:42 +0100413 if (dbg_line != nullptr) {
414 // Line number table offset.
415 Push32(dbg_info, dbg_line->size());
416 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800417
David Srbecky6f715892015-03-30 14:21:42 +0100418 for (auto method_info : method_infos) {
David Srbecky0df9e1f2015-04-07 19:02:58 +0100419 std::string method_name = PrettyMethod(method_info.dex_method_index_,
420 *method_info.dex_file_, true);
421 if (method_info.deduped_) {
422 // TODO We should place the DEDUPED tag on the first instance of a deduplicated symbol
423 // so that it will show up in a debuggerd crash report.
424 method_name += " [ DEDUPED ]";
425 }
426
David Srbecky6f715892015-03-30 14:21:42 +0100427 // Start a new TAG: subroutine (2).
428 PushByte(dbg_info, 2);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700429
David Srbecky6f715892015-03-30 14:21:42 +0100430 // Enter name, low_pc, high_pc.
David Srbecky0df9e1f2015-04-07 19:02:58 +0100431 Push32(dbg_info, PushStr(dbg_str, method_name));
David Srbecky6f715892015-03-30 14:21:42 +0100432 Push32(dbg_info, method_info.low_pc_ + text_section_offset);
433 Push32(dbg_info, method_info.high_pc_ + text_section_offset);
434 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700435
David Srbecky6f715892015-03-30 14:21:42 +0100436 if (dbg_line != nullptr) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700437 // TODO: in gdb info functions <regexp> - reports Java functions, but
438 // source file is <unknown> because .debug_line is formed as one
439 // compilation unit. To fix this it is possible to generate
440 // a separate compilation unit for every distinct Java source.
441 // Each of the these compilation units can have several non-adjacent
442 // method ranges.
443
David Srbecky6f715892015-03-30 14:21:42 +0100444 std::vector<dwarf::DebugLineWriter<>::FileEntry> files;
445 std::unordered_map<std::string, size_t> files_map;
446 std::vector<std::string> directories;
447 std::unordered_map<std::string, size_t> directories_map;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700448
David Srbecky6f715892015-03-30 14:21:42 +0100449 int code_factor_bits_ = 0;
450 int isa = -1;
451 switch (oat_writer->GetOatHeader().GetInstructionSet()) {
David Srbecky189ae822015-04-04 10:15:17 +0100452 case kArm: // arm actually means thumb2.
David Srbecky6f715892015-03-30 14:21:42 +0100453 case kThumb2:
454 code_factor_bits_ = 1; // 16-bit instuctions
455 isa = 1; // DW_ISA_ARM_thumb.
456 break;
David Srbecky6f715892015-03-30 14:21:42 +0100457 case kArm64:
458 case kMips:
459 case kMips64:
460 code_factor_bits_ = 2; // 32-bit instructions
461 break;
462 case kNone:
463 case kX86:
464 case kX86_64:
465 break;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700466 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700467
David Srbecky6f715892015-03-30 14:21:42 +0100468 dwarf::DebugLineOpCodeWriter<> opcodes(use_64bit_addresses, code_factor_bits_);
469 opcodes.SetAddress(text_section_offset + cunit_low_pc);
470 if (isa != -1) {
471 opcodes.SetISA(isa);
472 }
David Srbecky0df9e1f2015-04-07 19:02:58 +0100473 for (const OatWriter::DebugInfo& mi : method_infos) {
David Srbecky6f715892015-03-30 14:21:42 +0100474 // Addresses in the line table should be unique and increasing.
David Srbecky0df9e1f2015-04-07 19:02:58 +0100475 if (mi.deduped_) {
David Srbecky6f715892015-03-30 14:21:42 +0100476 continue;
477 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700478
David Srbecky0df9e1f2015-04-07 19:02:58 +0100479 struct DebugInfoCallbacks {
480 static bool NewPosition(void* ctx, uint32_t address, uint32_t line) {
481 auto* context = reinterpret_cast<DebugInfoCallbacks*>(ctx);
482 context->dex2line_.push_back({address, static_cast<int32_t>(line)});
483 return false;
484 }
485 DefaultSrcMap dex2line_;
486 } debug_info_callbacks;
487
488 const DexFile* dex = mi.dex_file_;
489 if (mi.code_item_ != nullptr) {
490 dex->DecodeDebugInfo(mi.code_item_,
491 (mi.access_flags_ & kAccStatic) != 0,
492 mi.dex_method_index_,
493 DebugInfoCallbacks::NewPosition,
494 nullptr,
495 &debug_info_callbacks);
496 }
497
498
David Srbecky6f715892015-03-30 14:21:42 +0100499 // Get and deduplicate directory and filename.
500 int file_index = 0; // 0 - primary source file of the compilation.
David Srbecky0df9e1f2015-04-07 19:02:58 +0100501 auto& dex_class_def = dex->GetClassDef(mi.class_def_index_);
502 const char* source_file = dex->GetSourceFile(dex_class_def);
503 if (source_file != nullptr) {
504 std::string file_name(source_file);
David Srbecky6f715892015-03-30 14:21:42 +0100505 size_t file_name_slash = file_name.find_last_of('/');
David Srbecky0df9e1f2015-04-07 19:02:58 +0100506 std::string class_name(dex->GetClassDescriptor(dex_class_def));
David Srbecky6f715892015-03-30 14:21:42 +0100507 size_t class_name_slash = class_name.find_last_of('/');
508 std::string full_path(file_name);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700509
David Srbecky6f715892015-03-30 14:21:42 +0100510 // Guess directory from package name.
511 int directory_index = 0; // 0 - current directory of the compilation.
512 if (file_name_slash == std::string::npos && // Just filename.
513 class_name.front() == 'L' && // Type descriptor for a class.
514 class_name_slash != std::string::npos) { // Has package name.
515 std::string package_name = class_name.substr(1, class_name_slash - 1);
516 auto it = directories_map.find(package_name);
517 if (it == directories_map.end()) {
518 directory_index = 1 + directories.size();
519 directories_map.emplace(package_name, directory_index);
520 directories.push_back(package_name);
521 } else {
522 directory_index = it->second;
523 }
524 full_path = package_name + "/" + file_name;
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700525 }
David Srbecky6f715892015-03-30 14:21:42 +0100526
527 // Add file entry.
528 auto it2 = files_map.find(full_path);
529 if (it2 == files_map.end()) {
530 file_index = 1 + files.size();
531 files_map.emplace(full_path, file_index);
532 files.push_back(dwarf::DebugLineWriter<>::FileEntry {
533 file_name,
534 directory_index,
535 0, // Modification time - NA.
536 0, // File size - NA.
537 });
538 } else {
539 file_index = it2->second;
540 }
541 }
542 opcodes.SetFile(file_index);
543
544 // Generate mapping opcodes from PC to Java lines.
David Srbecky0df9e1f2015-04-07 19:02:58 +0100545 const DefaultSrcMap& dex2line_map = debug_info_callbacks.dex2line_;
546 uint32_t low_pc = text_section_offset + mi.low_pc_;
David Srbecky6f715892015-03-30 14:21:42 +0100547 if (file_index != 0 && !dex2line_map.empty()) {
548 bool first = true;
David Srbecky0df9e1f2015-04-07 19:02:58 +0100549 for (SrcMapElem pc2dex : mi.compiled_method_->GetSrcMappingTable()) {
David Srbecky6f715892015-03-30 14:21:42 +0100550 uint32_t pc = pc2dex.from_;
David Srbecky0df9e1f2015-04-07 19:02:58 +0100551 int dex_pc = pc2dex.to_;
552 auto dex2line = dex2line_map.Find(static_cast<uint32_t>(dex_pc));
David Srbecky6f715892015-03-30 14:21:42 +0100553 if (dex2line.first) {
554 int line = dex2line.second;
555 if (first) {
556 first = false;
557 if (pc > 0) {
558 // Assume that any preceding code is prologue.
559 int first_line = dex2line_map.front().to_;
560 // Prologue is not a sensible place for a breakpoint.
561 opcodes.NegateStmt();
562 opcodes.AddRow(low_pc, first_line);
563 opcodes.NegateStmt();
564 opcodes.SetPrologueEnd();
565 }
566 opcodes.AddRow(low_pc + pc, line);
567 } else if (line != opcodes.CurrentLine()) {
568 opcodes.AddRow(low_pc + pc, line);
569 }
570 }
571 }
572 } else {
573 // line 0 - instruction cannot be attributed to any source line.
574 opcodes.AddRow(low_pc, 0);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700575 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800576 }
577
David Srbecky6f715892015-03-30 14:21:42 +0100578 opcodes.AdvancePC(text_section_offset + cunit_high_pc);
579 opcodes.EndSequence();
Mark Mendellae9fd932014-02-10 16:14:35 -0800580
David Srbecky6f715892015-03-30 14:21:42 +0100581 dwarf::DebugLineWriter<> dbg_line_writer(dbg_line);
582 dbg_line_writer.WriteTable(directories, files, opcodes);
Mark Mendellae9fd932014-02-10 16:14:35 -0800583 }
584
David Srbecky6f715892015-03-30 14:21:42 +0100585 // One byte terminator.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700586 PushByte(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800587
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700588 // We have now walked all the methods. Fill in lengths.
589 UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700590}
591
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700592template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
593 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
594 typename Elf_Phdr, typename Elf_Shdr>
Andreas Gampe86830382014-12-12 21:41:29 -0800595// Do not inline to avoid Clang stack frame problems. b/18738594
596NO_INLINE
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700597static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
598 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
599 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
600 OatWriter* oat_writer) {
David Srbecky1109fb32015-04-07 20:21:06 +0100601 std::vector<uint8_t> cfi_data;
602 bool is_64bit = Is64BitInstructionSet(compiler_driver->GetInstructionSet());
603 dwarf::DebugFrameWriter<> cfi(&cfi_data, is_64bit);
604 WriteCIE(&cfi, compiler_driver->GetInstructionSet());
605
Ian Rogers0279ebb2014-10-08 17:27:48 -0700606 Elf_Addr text_section_address = builder->GetTextBuilder().GetSection()->sh_addr;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700607
608 // Iterate over the compiled methods.
609 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700610 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* symtab =
611 builder->GetSymtabBuilder();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700612 for (auto it = method_info.begin(); it != method_info.end(); ++it) {
David Srbecky0df9e1f2015-04-07 19:02:58 +0100613 std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true);
614 if (it->deduped_) {
615 // TODO We should place the DEDUPED tag on the first instance of a deduplicated symbol
616 // so that it will show up in a debuggerd crash report.
617 name += " [ DEDUPED ]";
618 }
619
David Srbecky6f715892015-03-30 14:21:42 +0100620 uint32_t low_pc = it->low_pc_;
621 // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
622 low_pc += it->compiled_method_->CodeDelta();
David Srbecky0df9e1f2015-04-07 19:02:58 +0100623 symtab->AddSymbol(name, &builder->GetTextBuilder(), low_pc,
David Srbecky6f715892015-03-30 14:21:42 +0100624 true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700625
Ningsheng Jianf9734552014-10-27 14:56:34 +0800626 // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
627 // instructions, so that disassembler tools can correctly disassemble.
628 if (it->compiled_method_->GetInstructionSet() == kThumb2) {
629 symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true,
630 0, STB_LOCAL, STT_NOTYPE);
631 }
David Srbecky1109fb32015-04-07 20:21:06 +0100632
633 // Include FDE for compiled method, if possible.
634 DCHECK(it->compiled_method_ != nullptr);
635 const SwapVector<uint8_t>* unwind_opcodes = it->compiled_method_->GetCFIInfo();
636 if (unwind_opcodes != nullptr) {
637 // TUNING: The headers take a lot of space. Can we have 1 FDE per file?
638 // TUNING: Some tools support compressed DWARF sections (.zdebug_*).
639 cfi.WriteFDE(text_section_address + it->low_pc_, it->high_pc_ - it->low_pc_,
640 unwind_opcodes->data(), unwind_opcodes->size());
641 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700642 }
643
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700644 bool hasLineInfo = false;
645 for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
David Srbecky0df9e1f2015-04-07 19:02:58 +0100646 if (dbg_info.code_item_ != nullptr &&
647 dbg_info.dex_file_->GetDebugInfoStream(dbg_info.code_item_) != nullptr &&
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700648 !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
649 hasLineInfo = true;
650 break;
651 }
652 }
653
David Srbecky1109fb32015-04-07 20:21:06 +0100654 if (!method_info.empty() &&
David Srbeckyc6b4dd82015-04-07 20:32:43 +0100655 compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700656 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_info(".debug_info",
657 SHT_PROGBITS,
658 0, nullptr, 0, 1, 0);
659 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_abbrev(".debug_abbrev",
660 SHT_PROGBITS,
661 0, nullptr, 0, 1, 0);
662 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_str(".debug_str",
663 SHT_PROGBITS,
664 0, nullptr, 0, 1, 0);
665 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_line(".debug_line",
666 SHT_PROGBITS,
667 0, nullptr, 0, 1, 0);
668
669 FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
670 debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
671 hasLineInfo ? debug_line.GetBuffer() : nullptr,
672 text_section_address);
673
674 builder->RegisterRawSection(debug_info);
675 builder->RegisterRawSection(debug_abbrev);
676
David Srbecky1109fb32015-04-07 20:21:06 +0100677 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> eh_frame(".eh_frame",
678 SHT_PROGBITS,
679 SHF_ALLOC,
680 nullptr, 0, 4, 0);
681 eh_frame.SetBuffer(std::move(cfi_data));
682 builder->RegisterRawSection(eh_frame);
683
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700684 if (hasLineInfo) {
685 builder->RegisterRawSection(debug_line);
686 }
687
688 builder->RegisterRawSection(debug_str);
689 }
690}
691
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000692// Explicit instantiations
693template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
694 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>;
695template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
696 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>;
697
Brian Carlstrom7940e442013-07-12 13:46:57 -0700698} // namespace art