blob: c75d8f877da8fd4c96a8cb628badfba5104e2115 [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"
Brian Carlstrom7940e442013-07-12 13:46:57 -070024#include "driver/compiler_driver.h"
Alex Light3470ab42014-06-18 10:35:45 -070025#include "dwarf.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070026#include "elf_builder.h"
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070027#include "elf_file.h"
Nicolas Geoffray50cfe742014-02-19 13:27:42 +000028#include "elf_utils.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070029#include "file_output_stream.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070030#include "globals.h"
Andreas Gampe79273802014-08-05 20:21:05 -070031#include "leb128.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070032#include "oat.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070033#include "oat_writer.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070034#include "utils.h"
35
36namespace art {
37
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070038static void PushByte(std::vector<uint8_t>* buf, int data) {
39 buf->push_back(data & 0xff);
40}
41
42static uint32_t PushStr(std::vector<uint8_t>* buf, const char* str, const char* def = nullptr) {
43 if (str == nullptr) {
44 str = def;
45 }
46
47 uint32_t offset = buf->size();
48 for (size_t i = 0; str[i] != '\0'; ++i) {
49 buf->push_back(str[i]);
50 }
51 buf->push_back('\0');
52 return offset;
53}
54
55static uint32_t PushStr(std::vector<uint8_t>* buf, const std::string &str) {
56 uint32_t offset = buf->size();
57 buf->insert(buf->end(), str.begin(), str.end());
58 buf->push_back('\0');
59 return offset;
60}
61
Andreas Gampe79273802014-08-05 20:21:05 -070062static void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) {
63 (*buf)[offset+0] = data;
64 (*buf)[offset+1] = data >> 8;
65 (*buf)[offset+2] = data >> 16;
66 (*buf)[offset+3] = data >> 24;
67}
68
Andreas Gampe79273802014-08-05 20:21:05 -070069static void PushHalf(std::vector<uint8_t>* buf, int data) {
70 buf->push_back(data & 0xff);
71 buf->push_back((data >> 8) & 0xff);
72}
73
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000074template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
75 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
76 typename Elf_Phdr, typename Elf_Shdr>
77bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000078 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Create(File* elf_file,
Brian Carlstromb12f3472014-06-11 14:54:46 -070079 OatWriter* oat_writer,
80 const std::vector<const DexFile*>& dex_files,
81 const std::string& android_root,
82 bool is_host,
83 const CompilerDriver& driver) {
84 ElfWriterQuick elf_writer(driver, elf_file);
85 return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
86}
87
Andreas Gampe79273802014-08-05 20:21:05 -070088std::vector<uint8_t>* ConstructCIEFrameX86(bool is_x86_64) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070089 std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>;
Andreas Gampe79273802014-08-05 20:21:05 -070090
91 // Length (will be filled in later in this routine).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070092 if (is_x86_64) {
93 PushWord(cfi_info, 0xffffffff); // Indicates 64bit
94 PushWord(cfi_info, 0);
95 PushWord(cfi_info, 0);
96 } else {
97 PushWord(cfi_info, 0);
98 }
Andreas Gampe79273802014-08-05 20:21:05 -070099
100 // CIE id: always 0.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700101 if (is_x86_64) {
102 PushWord(cfi_info, 0);
103 PushWord(cfi_info, 0);
104 } else {
105 PushWord(cfi_info, 0);
106 }
Andreas Gampe79273802014-08-05 20:21:05 -0700107
108 // Version: always 1.
109 cfi_info->push_back(0x01);
110
111 // Augmentation: 'zR\0'
112 cfi_info->push_back(0x7a);
113 cfi_info->push_back(0x52);
114 cfi_info->push_back(0x0);
115
116 // Code alignment: 1.
117 EncodeUnsignedLeb128(1, cfi_info);
118
119 // Data alignment.
120 if (is_x86_64) {
121 EncodeSignedLeb128(-8, cfi_info);
122 } else {
123 EncodeSignedLeb128(-4, cfi_info);
124 }
125
126 // Return address register.
127 if (is_x86_64) {
128 // R16(RIP)
129 cfi_info->push_back(0x10);
130 } else {
131 // R8(EIP)
132 cfi_info->push_back(0x08);
133 }
134
135 // Augmentation length: 1.
136 cfi_info->push_back(1);
137
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700138 // Augmentation data.
139 if (is_x86_64) {
140 // 0x04 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
141 cfi_info->push_back(0x04);
142 } else {
143 // 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
144 cfi_info->push_back(0x03);
145 }
Andreas Gampe79273802014-08-05 20:21:05 -0700146
147 // Initial instructions.
148 if (is_x86_64) {
149 // DW_CFA_def_cfa R7(RSP) 8.
150 cfi_info->push_back(0x0c);
151 cfi_info->push_back(0x07);
152 cfi_info->push_back(0x08);
153
154 // DW_CFA_offset R16(RIP) 1 (* -8).
155 cfi_info->push_back(0x90);
156 cfi_info->push_back(0x01);
157 } else {
158 // DW_CFA_def_cfa R4(ESP) 4.
159 cfi_info->push_back(0x0c);
160 cfi_info->push_back(0x04);
161 cfi_info->push_back(0x04);
162
163 // DW_CFA_offset R8(EIP) 1 (* -4).
164 cfi_info->push_back(0x88);
165 cfi_info->push_back(0x01);
166 }
167
168 // Padding to a multiple of 4
169 while ((cfi_info->size() & 3) != 0) {
170 // DW_CFA_nop is encoded as 0.
171 cfi_info->push_back(0);
172 }
173
174 // Set the length of the CIE inside the generated bytes.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700175 if (is_x86_64) {
176 uint32_t length = cfi_info->size() - 12;
177 UpdateWord(cfi_info, 4, length);
178 } else {
179 uint32_t length = cfi_info->size() - 4;
180 UpdateWord(cfi_info, 0, length);
181 }
Andreas Gampe79273802014-08-05 20:21:05 -0700182 return cfi_info;
183}
184
185std::vector<uint8_t>* ConstructCIEFrame(InstructionSet isa) {
186 switch (isa) {
187 case kX86:
188 return ConstructCIEFrameX86(false);
189 case kX86_64:
190 return ConstructCIEFrameX86(true);
191
192 default:
193 // Not implemented.
194 return nullptr;
195 }
196}
197
Ian Rogers0279ebb2014-10-08 17:27:48 -0700198class OatWriterWrapper FINAL : public CodeOutput {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700199 public:
200 explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {}
201
Vladimir Markof4da6752014-08-01 19:04:18 +0100202 void SetCodeOffset(size_t offset) {
203 oat_writer_->SetOatDataOffset(offset);
204 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700205 bool Write(OutputStream* out) OVERRIDE {
206 return oat_writer_->Write(out);
207 }
208 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700209 OatWriter* const oat_writer_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700210};
211
212template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
213 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
214 typename Elf_Phdr, typename Elf_Shdr>
215static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
216 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
217 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
218 OatWriter* oat_writer);
219
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000220template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
221 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
222 typename Elf_Phdr, typename Elf_Shdr>
223bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
224 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Write(OatWriter* oat_writer,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700225 const std::vector<const DexFile*>& dex_files_unused,
226 const std::string& android_root_unused,
227 bool is_host_unused) {
Andreas Gampe79273802014-08-05 20:21:05 -0700228 constexpr bool debug = false;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700229 const OatHeader& oat_header = oat_writer->GetOatHeader();
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000230 Elf_Word oat_data_size = oat_header.GetExecutableOffset();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700231 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
232
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700233 OatWriterWrapper wrapper(oat_writer);
234
235 std::unique_ptr<ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
236 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> > builder(
237 new ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
238 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>(
239 &wrapper,
240 elf_file_,
241 compiler_driver_->GetInstructionSet(),
242 0,
243 oat_data_size,
244 oat_data_size,
245 oat_exec_size,
246 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
247 debug));
Alex Light78382fa2014-06-06 15:45:32 -0700248
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700249 if (!builder->Init()) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700250 return false;
251 }
252
Andreas Gampe79273802014-08-05 20:21:05 -0700253 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700254 WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700255 }
256
Alex Light53cb16b2014-06-12 11:26:29 -0700257 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700258 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches(
259 ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, sizeof(uintptr_t), sizeof(uintptr_t));
Vladimir Markof4da6752014-08-01 19:04:18 +0100260 const std::vector<uintptr_t>& locations = oat_writer->GetAbsolutePatchLocations();
261 const uint8_t* begin = reinterpret_cast<const uint8_t*>(&locations[0]);
262 const uint8_t* end = begin + locations.size() * sizeof(locations[0]);
263 oat_patches.GetBuffer()->assign(begin, end);
264 if (debug) {
265 LOG(INFO) << "Prepared .oat_patches for " << locations.size() << " patches.";
266 }
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700267 builder->RegisterRawSection(oat_patches);
Alex Light53cb16b2014-06-12 11:26:29 -0700268 }
269
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700270 return builder->Write();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700271}
Mark Mendellae9fd932014-02-10 16:14:35 -0800272
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700273class LineTableGenerator FINAL : public Leb128Encoder {
274 public:
275 LineTableGenerator(int line_base, int line_range, int opcode_base,
276 std::vector<uint8_t>* data, uintptr_t current_address,
277 size_t current_line)
278 : Leb128Encoder(data), line_base_(line_base), line_range_(line_range),
279 opcode_base_(opcode_base), current_address_(current_address),
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700280 current_line_(current_line), current_file_index_(0) {}
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700281
282 void PutDelta(unsigned delta_addr, int delta_line) {
283 current_line_ += delta_line;
284 current_address_ += delta_addr;
285
286 if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) {
287 unsigned special_opcode = (delta_line - line_base_) +
288 (line_range_ * delta_addr) + opcode_base_;
289 if (special_opcode <= 255) {
290 PushByte(data_, special_opcode);
291 return;
292 }
293 }
294
295 // generate standart opcode for address advance
296 if (delta_addr != 0) {
297 PushByte(data_, DW_LNS_advance_pc);
298 PushBackUnsigned(delta_addr);
299 }
300
301 // generate standart opcode for line delta
302 if (delta_line != 0) {
303 PushByte(data_, DW_LNS_advance_line);
304 PushBackSigned(delta_line);
305 }
306
307 // generate standart opcode for new LTN entry
308 PushByte(data_, DW_LNS_copy);
309 }
310
311 void SetAddr(uintptr_t addr) {
312 if (current_address_ == addr) {
313 return;
314 }
315
316 current_address_ = addr;
317
318 PushByte(data_, 0); // extended opcode:
319 PushByte(data_, 1 + 4); // length: opcode_size + address_size
320 PushByte(data_, DW_LNE_set_address);
321 PushWord(data_, addr);
322 }
323
324 void SetLine(unsigned line) {
325 int delta_line = line - current_line_;
326 if (delta_line) {
327 current_line_ = line;
328 PushByte(data_, DW_LNS_advance_line);
329 PushBackSigned(delta_line);
330 }
331 }
332
333 void SetFile(unsigned file_index) {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700334 if (current_file_index_ != file_index) {
335 current_file_index_ = file_index;
336 PushByte(data_, DW_LNS_set_file);
337 PushBackUnsigned(file_index);
338 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700339 }
340
341 void EndSequence() {
342 // End of Line Table Program
343 // 0(=ext), 1(len), DW_LNE_end_sequence
344 PushByte(data_, 0);
345 PushByte(data_, 1);
346 PushByte(data_, DW_LNE_end_sequence);
347 }
348
349 private:
350 const int line_base_;
351 const int line_range_;
352 const int opcode_base_;
353 uintptr_t current_address_;
354 size_t current_line_;
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700355 unsigned current_file_index_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700356
357 DISALLOW_COPY_AND_ASSIGN(LineTableGenerator);
358};
359
360// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
361static void GetLineInfoForJava(const uint8_t* dbgstream, const SrcMap& pc2dex,
362 SrcMap* result, uint32_t start_pc = 0) {
363 if (dbgstream == nullptr) {
364 return;
365 }
366
367 int adjopcode;
368 uint32_t dex_offset = 0;
369 uint32_t java_line = DecodeUnsignedLeb128(&dbgstream);
370
371 // skip parameters
372 for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) {
373 DecodeUnsignedLeb128(&dbgstream);
374 }
375
376 for (bool is_end = false; is_end == false; ) {
377 uint8_t opcode = *dbgstream;
378 dbgstream++;
379 switch (opcode) {
380 case DexFile::DBG_END_SEQUENCE:
381 is_end = true;
382 break;
383
384 case DexFile::DBG_ADVANCE_PC:
385 dex_offset += DecodeUnsignedLeb128(&dbgstream);
386 break;
387
388 case DexFile::DBG_ADVANCE_LINE:
389 java_line += DecodeSignedLeb128(&dbgstream);
390 break;
391
392 case DexFile::DBG_START_LOCAL:
393 case DexFile::DBG_START_LOCAL_EXTENDED:
394 DecodeUnsignedLeb128(&dbgstream);
395 DecodeUnsignedLeb128(&dbgstream);
396 DecodeUnsignedLeb128(&dbgstream);
397
398 if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) {
399 DecodeUnsignedLeb128(&dbgstream);
400 }
401 break;
402
403 case DexFile::DBG_END_LOCAL:
404 case DexFile::DBG_RESTART_LOCAL:
405 DecodeUnsignedLeb128(&dbgstream);
406 break;
407
408 case DexFile::DBG_SET_PROLOGUE_END:
409 case DexFile::DBG_SET_EPILOGUE_BEGIN:
410 case DexFile::DBG_SET_FILE:
411 break;
412
413 default:
414 adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
415 dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
416 java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
417
418 for (SrcMap::const_iterator found = pc2dex.FindByTo(dex_offset);
419 found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset);
420 found++) {
421 result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)});
422 }
423 break;
424 }
Andreas Gampe79273802014-08-05 20:21:05 -0700425 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800426}
427
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700428/*
429 * @brief Generate the DWARF debug_info and debug_abbrev sections
430 * @param oat_writer The Oat file Writer.
431 * @param dbg_info Compilation unit information.
432 * @param dbg_abbrev Abbreviations used to generate dbg_info.
433 * @param dbg_str Debug strings.
434 */
435static void FillInCFIInformation(OatWriter* oat_writer,
436 std::vector<uint8_t>* dbg_info,
437 std::vector<uint8_t>* dbg_abbrev,
438 std::vector<uint8_t>* dbg_str,
439 std::vector<uint8_t>* dbg_line,
440 uint32_t text_section_offset) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700441 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
442
443 uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
444
Mark Mendellae9fd932014-02-10 16:14:35 -0800445 // Create the debug_abbrev section with boilerplate information.
446 // We only care about low_pc and high_pc right now for the compilation
447 // unit and methods.
448
449 // Tag 1: Compilation unit: DW_TAG_compile_unit.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700450 PushByte(dbg_abbrev, 1);
451 PushByte(dbg_abbrev, DW_TAG_compile_unit);
Mark Mendellae9fd932014-02-10 16:14:35 -0800452
453 // There are children (the methods).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700454 PushByte(dbg_abbrev, DW_CHILDREN_yes);
455
456 // DW_AT_producer DW_FORM_data1.
457 // REVIEW: we can get rid of dbg_str section if
458 // DW_FORM_string (immediate string) was used everywhere instead of
459 // DW_FORM_strp (ref to string from .debug_str section).
460 // DW_FORM_strp makes sense only if we reuse the strings.
461 PushByte(dbg_abbrev, DW_AT_producer);
462 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800463
464 // DW_LANG_Java DW_FORM_data1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700465 PushByte(dbg_abbrev, DW_AT_language);
466 PushByte(dbg_abbrev, DW_FORM_data1);
Mark Mendellae9fd932014-02-10 16:14:35 -0800467
468 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700469 PushByte(dbg_abbrev, DW_AT_low_pc);
470 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800471
472 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700473 PushByte(dbg_abbrev, DW_AT_high_pc);
474 PushByte(dbg_abbrev, DW_FORM_addr);
475
476 if (dbg_line != nullptr) {
477 // DW_AT_stmt_list DW_FORM_sec_offset.
478 PushByte(dbg_abbrev, DW_AT_stmt_list);
479 PushByte(dbg_abbrev, DW_FORM_sec_offset);
480 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800481
482 // End of DW_TAG_compile_unit.
483 PushHalf(dbg_abbrev, 0);
484
485 // Tag 2: Compilation unit: DW_TAG_subprogram.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700486 PushByte(dbg_abbrev, 2);
487 PushByte(dbg_abbrev, DW_TAG_subprogram);
Mark Mendellae9fd932014-02-10 16:14:35 -0800488
489 // There are no children.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700490 PushByte(dbg_abbrev, DW_CHILDREN_no);
Mark Mendellae9fd932014-02-10 16:14:35 -0800491
492 // Name of the method.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700493 PushByte(dbg_abbrev, DW_AT_name);
494 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800495
496 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700497 PushByte(dbg_abbrev, DW_AT_low_pc);
498 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800499
500 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700501 PushByte(dbg_abbrev, DW_AT_high_pc);
502 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800503
504 // End of DW_TAG_subprogram.
505 PushHalf(dbg_abbrev, 0);
506
507 // Start the debug_info section with the header information
508 // 'unit_length' will be filled in later.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700509 int cunit_length = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -0800510 PushWord(dbg_info, 0);
511
512 // 'version' - 3.
513 PushHalf(dbg_info, 3);
514
515 // Offset into .debug_abbrev section (always 0).
516 PushWord(dbg_info, 0);
517
518 // Address size: 4.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700519 PushByte(dbg_info, 4);
Mark Mendellae9fd932014-02-10 16:14:35 -0800520
521 // Start the description for the compilation unit.
522 // This uses tag 1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700523 PushByte(dbg_info, 1);
524
525 // The producer is Android dex2oat.
526 PushWord(dbg_info, producer_str_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800527
528 // The language is Java.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700529 PushByte(dbg_info, DW_LANG_Java);
Mark Mendellae9fd932014-02-10 16:14:35 -0800530
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700531 // low_pc and high_pc.
532 uint32_t cunit_low_pc = 0 - 1;
533 uint32_t cunit_high_pc = 0;
534 int cunit_low_pc_pos = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -0800535 PushWord(dbg_info, 0);
536 PushWord(dbg_info, 0);
537
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700538 if (dbg_line == nullptr) {
539 for (size_t i = 0; i < method_info.size(); ++i) {
540 const OatWriter::DebugInfo &dbg = method_info[i];
Mark Mendellae9fd932014-02-10 16:14:35 -0800541
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700542 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
543 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
544
545 // Start a new TAG: subroutine (2).
546 PushByte(dbg_info, 2);
547
548 // Enter name, low_pc, high_pc.
549 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
550 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
551 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800552 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700553 } else {
554 // TODO: in gdb info functions <regexp> - reports Java functions, but
555 // source file is <unknown> because .debug_line is formed as one
556 // compilation unit. To fix this it is possible to generate
557 // a separate compilation unit for every distinct Java source.
558 // Each of the these compilation units can have several non-adjacent
559 // method ranges.
560
561 // Line number table offset
562 PushWord(dbg_info, dbg_line->size());
563
564 size_t lnt_length = dbg_line->size();
565 PushWord(dbg_line, 0);
566
567 PushHalf(dbg_line, 4); // LNT Version DWARF v4 => 4
568
569 size_t lnt_hdr_length = dbg_line->size();
570 PushWord(dbg_line, 0); // TODO: 64-bit uses 8-byte here
571
572 PushByte(dbg_line, 1); // minimum_instruction_length (ubyte)
573 PushByte(dbg_line, 1); // maximum_operations_per_instruction (ubyte) = always 1
574 PushByte(dbg_line, 1); // default_is_stmt (ubyte)
575
576 const int8_t LINE_BASE = -5;
577 PushByte(dbg_line, LINE_BASE); // line_base (sbyte)
578
579 const uint8_t LINE_RANGE = 14;
580 PushByte(dbg_line, LINE_RANGE); // line_range (ubyte)
581
582 const uint8_t OPCODE_BASE = 13;
583 PushByte(dbg_line, OPCODE_BASE); // opcode_base (ubyte)
584
585 // Standard_opcode_lengths (array of ubyte).
586 PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1);
587 PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0);
588 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
589 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
590
591 PushByte(dbg_line, 0); // include_directories (sequence of path names) = EMPTY
592
593 // File_names (sequence of file entries).
594 std::unordered_map<const char*, size_t> files;
595 for (size_t i = 0; i < method_info.size(); ++i) {
596 const OatWriter::DebugInfo &dbg = method_info[i];
597 // TODO: add package directory to the file name
598 const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_;
599 auto found = files.find(file_name);
600 if (found == files.end()) {
601 size_t file_index = 1 + files.size();
602 files[file_name] = file_index;
603 PushStr(dbg_line, file_name);
604 PushByte(dbg_line, 0); // include directory index = LEB128(0) - no directory
605 PushByte(dbg_line, 0); // modification time = LEB128(0) - NA
606 PushByte(dbg_line, 0); // file length = LEB128(0) - NA
607 }
608 }
609 PushByte(dbg_line, 0); // End of file_names.
610
611 // Set lnt header length.
612 UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4);
613
614 // Generate Line Number Program code, one long program for all methods.
615 LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE,
616 dbg_line, 0, 1);
617
618 SrcMap pc2java_map;
619 for (size_t i = 0; i < method_info.size(); ++i) {
620 const OatWriter::DebugInfo &dbg = method_info[i];
621 const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_;
622 size_t file_index = files[file_name];
623 DCHECK_NE(file_index, 0U) << file_name;
624
625 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
626 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
627
628 // Start a new TAG: subroutine (2).
629 PushByte(dbg_info, 2);
630
631 // Enter name, low_pc, high_pc.
632 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
633 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
634 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
635
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700636 GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(),
637 &pc2java_map, dbg.low_pc_);
638 pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_);
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700639 if (!pc2java_map.empty()) {
640 line_table_generator.SetFile(file_index);
641 line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset);
642 line_table_generator.SetLine(1);
643 for (auto& src_map_elem : pc2java_map) {
644 line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_);
645 }
646 pc2java_map.clear();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700647 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800648 }
649
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700650 // End Sequence should have the highest address set.
651 line_table_generator.SetAddr(cunit_high_pc + text_section_offset);
652 line_table_generator.EndSequence();
Mark Mendellae9fd932014-02-10 16:14:35 -0800653
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700654 // set lnt length
655 UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4);
Mark Mendellae9fd932014-02-10 16:14:35 -0800656 }
657
658 // One byte terminator
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700659 PushByte(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800660
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700661 // Fill in cunit's low_pc and high_pc.
662 UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset);
663 UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset);
664
665 // We have now walked all the methods. Fill in lengths.
666 UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700667}
668
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700669template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
670 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
671 typename Elf_Phdr, typename Elf_Shdr>
672static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
673 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
674 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
675 OatWriter* oat_writer) {
676 std::unique_ptr<std::vector<uint8_t>> cfi_info(
677 ConstructCIEFrame(compiler_driver->GetInstructionSet()));
678
Ian Rogers0279ebb2014-10-08 17:27:48 -0700679 Elf_Addr text_section_address = builder->GetTextBuilder().GetSection()->sh_addr;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700680
681 // Iterate over the compiled methods.
682 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700683 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* symtab =
684 builder->GetSymtabBuilder();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700685 for (auto it = method_info.begin(); it != method_info.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700686 symtab->AddSymbol(it->method_name_, &builder->GetTextBuilder(), it->low_pc_, true,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700687 it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
688
689 // Include CFI for compiled method, if possible.
690 if (cfi_info.get() != nullptr) {
691 DCHECK(it->compiled_method_ != nullptr);
692
693 // Copy in the FDE, if present
694 const std::vector<uint8_t>* fde = it->compiled_method_->GetCFIInfo();
695 if (fde != nullptr) {
696 // Copy the information into cfi_info and then fix the address in the new copy.
697 int cur_offset = cfi_info->size();
698 cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
699
700 bool is_64bit = *(reinterpret_cast<const uint32_t*>(fde->data())) == 0xffffffff;
701
702 // Set the 'CIE_pointer' field.
703 uint64_t CIE_pointer = cur_offset + (is_64bit ? 12 : 4);
704 uint64_t offset_to_update = CIE_pointer;
705 if (is_64bit) {
706 (*cfi_info)[offset_to_update+0] = CIE_pointer;
707 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
708 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
709 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
710 (*cfi_info)[offset_to_update+4] = CIE_pointer >> 32;
711 (*cfi_info)[offset_to_update+5] = CIE_pointer >> 40;
712 (*cfi_info)[offset_to_update+6] = CIE_pointer >> 48;
713 (*cfi_info)[offset_to_update+7] = CIE_pointer >> 56;
714 } else {
715 (*cfi_info)[offset_to_update+0] = CIE_pointer;
716 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
717 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
718 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
719 }
720
721 // Set the 'initial_location' field.
722 offset_to_update += is_64bit ? 8 : 4;
723 if (is_64bit) {
724 const uint64_t quick_code_start = it->low_pc_ + text_section_address;
725 (*cfi_info)[offset_to_update+0] = quick_code_start;
726 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
727 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
728 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
729 (*cfi_info)[offset_to_update+4] = quick_code_start >> 32;
730 (*cfi_info)[offset_to_update+5] = quick_code_start >> 40;
731 (*cfi_info)[offset_to_update+6] = quick_code_start >> 48;
732 (*cfi_info)[offset_to_update+7] = quick_code_start >> 56;
733 } else {
734 const uint32_t quick_code_start = it->low_pc_ + text_section_address;
735 (*cfi_info)[offset_to_update+0] = quick_code_start;
736 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
737 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
738 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
739 }
740 }
741 }
742 }
743
744 bool hasCFI = (cfi_info.get() != nullptr);
745 bool hasLineInfo = false;
746 for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
747 if (dbg_info.dbgstream_ != nullptr &&
748 !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
749 hasLineInfo = true;
750 break;
751 }
752 }
753
754 if (hasLineInfo || hasCFI) {
755 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_info(".debug_info",
756 SHT_PROGBITS,
757 0, nullptr, 0, 1, 0);
758 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_abbrev(".debug_abbrev",
759 SHT_PROGBITS,
760 0, nullptr, 0, 1, 0);
761 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_str(".debug_str",
762 SHT_PROGBITS,
763 0, nullptr, 0, 1, 0);
764 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_line(".debug_line",
765 SHT_PROGBITS,
766 0, nullptr, 0, 1, 0);
767
768 FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
769 debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
770 hasLineInfo ? debug_line.GetBuffer() : nullptr,
771 text_section_address);
772
773 builder->RegisterRawSection(debug_info);
774 builder->RegisterRawSection(debug_abbrev);
775
776 if (hasCFI) {
777 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> eh_frame(".eh_frame",
778 SHT_PROGBITS,
779 SHF_ALLOC,
780 nullptr, 0, 4, 0);
781 eh_frame.SetBuffer(std::move(*cfi_info.get()));
782 builder->RegisterRawSection(eh_frame);
783 }
784
785 if (hasLineInfo) {
786 builder->RegisterRawSection(debug_line);
787 }
788
789 builder->RegisterRawSection(debug_str);
790 }
791}
792
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000793// Explicit instantiations
794template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
795 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>;
796template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
797 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>;
798
Brian Carlstrom7940e442013-07-12 13:46:57 -0700799} // namespace art