blob: a822b24cdecaf89492c2addafa505aea24e157fc [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) {
Vladimir Marko80b96d12015-02-19 15:50:28 +000093 Push32(cfi_info, 0xffffffff); // Indicates 64bit
94 Push32(cfi_info, 0);
95 Push32(cfi_info, 0);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070096 } else {
Vladimir Marko80b96d12015-02-19 15:50:28 +000097 Push32(cfi_info, 0);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070098 }
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) {
Vladimir Marko80b96d12015-02-19 15:50:28 +0000102 Push32(cfi_info, 0);
103 Push32(cfi_info, 0);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700104 } else {
Vladimir Marko80b96d12015-02-19 15:50:28 +0000105 Push32(cfi_info, 0);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700106 }
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,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700225 const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED,
226 const std::string& android_root_unused ATTRIBUTE_UNUSED,
227 bool is_host_unused ATTRIBUTE_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;
Vladimir Marko5c42c292015-02-25 12:02:49 +0000232 uint32_t oat_bss_size = oat_writer->GetBssSize();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700233
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700234 OatWriterWrapper wrapper(oat_writer);
235
236 std::unique_ptr<ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
237 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> > builder(
238 new ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
239 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>(
240 &wrapper,
241 elf_file_,
242 compiler_driver_->GetInstructionSet(),
243 0,
244 oat_data_size,
245 oat_data_size,
246 oat_exec_size,
Vladimir Marko5c42c292015-02-25 12:02:49 +0000247 RoundUp(oat_data_size + oat_exec_size, kPageSize),
248 oat_bss_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700249 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
250 debug));
Alex Light78382fa2014-06-06 15:45:32 -0700251
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700252 if (!builder->Init()) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700253 return false;
254 }
255
Andreas Gampe79273802014-08-05 20:21:05 -0700256 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700257 WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700258 }
259
Alex Light53cb16b2014-06-12 11:26:29 -0700260 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700261 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches(
262 ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, sizeof(uintptr_t), sizeof(uintptr_t));
Vladimir Markof4da6752014-08-01 19:04:18 +0100263 const std::vector<uintptr_t>& locations = oat_writer->GetAbsolutePatchLocations();
264 const uint8_t* begin = reinterpret_cast<const uint8_t*>(&locations[0]);
265 const uint8_t* end = begin + locations.size() * sizeof(locations[0]);
266 oat_patches.GetBuffer()->assign(begin, end);
267 if (debug) {
268 LOG(INFO) << "Prepared .oat_patches for " << locations.size() << " patches.";
269 }
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700270 builder->RegisterRawSection(oat_patches);
Alex Light53cb16b2014-06-12 11:26:29 -0700271 }
272
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700273 return builder->Write();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700274}
Mark Mendellae9fd932014-02-10 16:14:35 -0800275
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700276class LineTableGenerator FINAL : public Leb128Encoder {
277 public:
278 LineTableGenerator(int line_base, int line_range, int opcode_base,
279 std::vector<uint8_t>* data, uintptr_t current_address,
280 size_t current_line)
281 : Leb128Encoder(data), line_base_(line_base), line_range_(line_range),
282 opcode_base_(opcode_base), current_address_(current_address),
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700283 current_line_(current_line), current_file_index_(0) {}
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700284
285 void PutDelta(unsigned delta_addr, int delta_line) {
286 current_line_ += delta_line;
287 current_address_ += delta_addr;
288
289 if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) {
290 unsigned special_opcode = (delta_line - line_base_) +
291 (line_range_ * delta_addr) + opcode_base_;
292 if (special_opcode <= 255) {
293 PushByte(data_, special_opcode);
294 return;
295 }
296 }
297
298 // generate standart opcode for address advance
299 if (delta_addr != 0) {
300 PushByte(data_, DW_LNS_advance_pc);
301 PushBackUnsigned(delta_addr);
302 }
303
304 // generate standart opcode for line delta
305 if (delta_line != 0) {
306 PushByte(data_, DW_LNS_advance_line);
307 PushBackSigned(delta_line);
308 }
309
310 // generate standart opcode for new LTN entry
311 PushByte(data_, DW_LNS_copy);
312 }
313
314 void SetAddr(uintptr_t addr) {
315 if (current_address_ == addr) {
316 return;
317 }
318
319 current_address_ = addr;
320
321 PushByte(data_, 0); // extended opcode:
322 PushByte(data_, 1 + 4); // length: opcode_size + address_size
323 PushByte(data_, DW_LNE_set_address);
Vladimir Marko80b96d12015-02-19 15:50:28 +0000324 Push32(data_, addr);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700325 }
326
327 void SetLine(unsigned line) {
328 int delta_line = line - current_line_;
329 if (delta_line) {
330 current_line_ = line;
331 PushByte(data_, DW_LNS_advance_line);
332 PushBackSigned(delta_line);
333 }
334 }
335
336 void SetFile(unsigned file_index) {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700337 if (current_file_index_ != file_index) {
338 current_file_index_ = file_index;
339 PushByte(data_, DW_LNS_set_file);
340 PushBackUnsigned(file_index);
341 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700342 }
343
344 void EndSequence() {
345 // End of Line Table Program
346 // 0(=ext), 1(len), DW_LNE_end_sequence
347 PushByte(data_, 0);
348 PushByte(data_, 1);
349 PushByte(data_, DW_LNE_end_sequence);
350 }
351
352 private:
353 const int line_base_;
354 const int line_range_;
355 const int opcode_base_;
356 uintptr_t current_address_;
357 size_t current_line_;
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700358 unsigned current_file_index_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700359
360 DISALLOW_COPY_AND_ASSIGN(LineTableGenerator);
361};
362
363// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800364static void GetLineInfoForJava(const uint8_t* dbgstream, const SwapSrcMap& pc2dex,
365 DefaultSrcMap* result, uint32_t start_pc = 0) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700366 if (dbgstream == nullptr) {
367 return;
368 }
369
370 int adjopcode;
371 uint32_t dex_offset = 0;
372 uint32_t java_line = DecodeUnsignedLeb128(&dbgstream);
373
374 // skip parameters
375 for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) {
376 DecodeUnsignedLeb128(&dbgstream);
377 }
378
379 for (bool is_end = false; is_end == false; ) {
380 uint8_t opcode = *dbgstream;
381 dbgstream++;
382 switch (opcode) {
383 case DexFile::DBG_END_SEQUENCE:
384 is_end = true;
385 break;
386
387 case DexFile::DBG_ADVANCE_PC:
388 dex_offset += DecodeUnsignedLeb128(&dbgstream);
389 break;
390
391 case DexFile::DBG_ADVANCE_LINE:
392 java_line += DecodeSignedLeb128(&dbgstream);
393 break;
394
395 case DexFile::DBG_START_LOCAL:
396 case DexFile::DBG_START_LOCAL_EXTENDED:
397 DecodeUnsignedLeb128(&dbgstream);
398 DecodeUnsignedLeb128(&dbgstream);
399 DecodeUnsignedLeb128(&dbgstream);
400
401 if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) {
402 DecodeUnsignedLeb128(&dbgstream);
403 }
404 break;
405
406 case DexFile::DBG_END_LOCAL:
407 case DexFile::DBG_RESTART_LOCAL:
408 DecodeUnsignedLeb128(&dbgstream);
409 break;
410
411 case DexFile::DBG_SET_PROLOGUE_END:
412 case DexFile::DBG_SET_EPILOGUE_BEGIN:
413 case DexFile::DBG_SET_FILE:
414 break;
415
416 default:
417 adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
418 dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
419 java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
420
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800421 for (SwapSrcMap::const_iterator found = pc2dex.FindByTo(dex_offset);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700422 found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset);
423 found++) {
424 result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)});
425 }
426 break;
427 }
Andreas Gampe79273802014-08-05 20:21:05 -0700428 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800429}
430
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700431/*
432 * @brief Generate the DWARF debug_info and debug_abbrev sections
433 * @param oat_writer The Oat file Writer.
434 * @param dbg_info Compilation unit information.
435 * @param dbg_abbrev Abbreviations used to generate dbg_info.
436 * @param dbg_str Debug strings.
437 */
438static void FillInCFIInformation(OatWriter* oat_writer,
439 std::vector<uint8_t>* dbg_info,
440 std::vector<uint8_t>* dbg_abbrev,
441 std::vector<uint8_t>* dbg_str,
442 std::vector<uint8_t>* dbg_line,
443 uint32_t text_section_offset) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700444 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
445
446 uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
447
Mark Mendellae9fd932014-02-10 16:14:35 -0800448 // Create the debug_abbrev section with boilerplate information.
449 // We only care about low_pc and high_pc right now for the compilation
450 // unit and methods.
451
452 // Tag 1: Compilation unit: DW_TAG_compile_unit.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700453 PushByte(dbg_abbrev, 1);
454 PushByte(dbg_abbrev, DW_TAG_compile_unit);
Mark Mendellae9fd932014-02-10 16:14:35 -0800455
456 // There are children (the methods).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700457 PushByte(dbg_abbrev, DW_CHILDREN_yes);
458
459 // DW_AT_producer DW_FORM_data1.
460 // REVIEW: we can get rid of dbg_str section if
461 // DW_FORM_string (immediate string) was used everywhere instead of
462 // DW_FORM_strp (ref to string from .debug_str section).
463 // DW_FORM_strp makes sense only if we reuse the strings.
464 PushByte(dbg_abbrev, DW_AT_producer);
465 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800466
467 // DW_LANG_Java DW_FORM_data1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700468 PushByte(dbg_abbrev, DW_AT_language);
469 PushByte(dbg_abbrev, DW_FORM_data1);
Mark Mendellae9fd932014-02-10 16:14:35 -0800470
471 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700472 PushByte(dbg_abbrev, DW_AT_low_pc);
473 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800474
475 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700476 PushByte(dbg_abbrev, DW_AT_high_pc);
477 PushByte(dbg_abbrev, DW_FORM_addr);
478
479 if (dbg_line != nullptr) {
480 // DW_AT_stmt_list DW_FORM_sec_offset.
481 PushByte(dbg_abbrev, DW_AT_stmt_list);
482 PushByte(dbg_abbrev, DW_FORM_sec_offset);
483 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800484
485 // End of DW_TAG_compile_unit.
486 PushHalf(dbg_abbrev, 0);
487
488 // Tag 2: Compilation unit: DW_TAG_subprogram.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700489 PushByte(dbg_abbrev, 2);
490 PushByte(dbg_abbrev, DW_TAG_subprogram);
Mark Mendellae9fd932014-02-10 16:14:35 -0800491
492 // There are no children.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700493 PushByte(dbg_abbrev, DW_CHILDREN_no);
Mark Mendellae9fd932014-02-10 16:14:35 -0800494
495 // Name of the method.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700496 PushByte(dbg_abbrev, DW_AT_name);
497 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800498
499 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700500 PushByte(dbg_abbrev, DW_AT_low_pc);
501 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800502
503 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700504 PushByte(dbg_abbrev, DW_AT_high_pc);
505 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800506
507 // End of DW_TAG_subprogram.
508 PushHalf(dbg_abbrev, 0);
509
510 // Start the debug_info section with the header information
511 // 'unit_length' will be filled in later.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700512 int cunit_length = dbg_info->size();
Vladimir Marko80b96d12015-02-19 15:50:28 +0000513 Push32(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800514
515 // 'version' - 3.
516 PushHalf(dbg_info, 3);
517
518 // Offset into .debug_abbrev section (always 0).
Vladimir Marko80b96d12015-02-19 15:50:28 +0000519 Push32(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800520
521 // Address size: 4.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700522 PushByte(dbg_info, 4);
Mark Mendellae9fd932014-02-10 16:14:35 -0800523
524 // Start the description for the compilation unit.
525 // This uses tag 1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700526 PushByte(dbg_info, 1);
527
528 // The producer is Android dex2oat.
Vladimir Marko80b96d12015-02-19 15:50:28 +0000529 Push32(dbg_info, producer_str_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800530
531 // The language is Java.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700532 PushByte(dbg_info, DW_LANG_Java);
Mark Mendellae9fd932014-02-10 16:14:35 -0800533
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700534 // low_pc and high_pc.
535 uint32_t cunit_low_pc = 0 - 1;
536 uint32_t cunit_high_pc = 0;
537 int cunit_low_pc_pos = dbg_info->size();
Vladimir Marko80b96d12015-02-19 15:50:28 +0000538 Push32(dbg_info, 0);
539 Push32(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800540
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700541 if (dbg_line == nullptr) {
542 for (size_t i = 0; i < method_info.size(); ++i) {
543 const OatWriter::DebugInfo &dbg = method_info[i];
Mark Mendellae9fd932014-02-10 16:14:35 -0800544
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700545 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
546 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
547
548 // Start a new TAG: subroutine (2).
549 PushByte(dbg_info, 2);
550
551 // Enter name, low_pc, high_pc.
Vladimir Marko80b96d12015-02-19 15:50:28 +0000552 Push32(dbg_info, PushStr(dbg_str, dbg.method_name_));
553 Push32(dbg_info, dbg.low_pc_ + text_section_offset);
554 Push32(dbg_info, dbg.high_pc_ + text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800555 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700556 } else {
557 // TODO: in gdb info functions <regexp> - reports Java functions, but
558 // source file is <unknown> because .debug_line is formed as one
559 // compilation unit. To fix this it is possible to generate
560 // a separate compilation unit for every distinct Java source.
561 // Each of the these compilation units can have several non-adjacent
562 // method ranges.
563
564 // Line number table offset
Vladimir Marko80b96d12015-02-19 15:50:28 +0000565 Push32(dbg_info, dbg_line->size());
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700566
567 size_t lnt_length = dbg_line->size();
Vladimir Marko80b96d12015-02-19 15:50:28 +0000568 Push32(dbg_line, 0);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700569
570 PushHalf(dbg_line, 4); // LNT Version DWARF v4 => 4
571
572 size_t lnt_hdr_length = dbg_line->size();
Vladimir Marko80b96d12015-02-19 15:50:28 +0000573 Push32(dbg_line, 0); // TODO: 64-bit uses 8-byte here
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700574
575 PushByte(dbg_line, 1); // minimum_instruction_length (ubyte)
576 PushByte(dbg_line, 1); // maximum_operations_per_instruction (ubyte) = always 1
577 PushByte(dbg_line, 1); // default_is_stmt (ubyte)
578
579 const int8_t LINE_BASE = -5;
580 PushByte(dbg_line, LINE_BASE); // line_base (sbyte)
581
582 const uint8_t LINE_RANGE = 14;
583 PushByte(dbg_line, LINE_RANGE); // line_range (ubyte)
584
585 const uint8_t OPCODE_BASE = 13;
586 PushByte(dbg_line, OPCODE_BASE); // opcode_base (ubyte)
587
588 // Standard_opcode_lengths (array of ubyte).
589 PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1);
590 PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0);
591 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
592 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
593
594 PushByte(dbg_line, 0); // include_directories (sequence of path names) = EMPTY
595
596 // File_names (sequence of file entries).
597 std::unordered_map<const char*, size_t> files;
598 for (size_t i = 0; i < method_info.size(); ++i) {
599 const OatWriter::DebugInfo &dbg = method_info[i];
600 // TODO: add package directory to the file name
601 const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_;
602 auto found = files.find(file_name);
603 if (found == files.end()) {
604 size_t file_index = 1 + files.size();
605 files[file_name] = file_index;
606 PushStr(dbg_line, file_name);
607 PushByte(dbg_line, 0); // include directory index = LEB128(0) - no directory
608 PushByte(dbg_line, 0); // modification time = LEB128(0) - NA
609 PushByte(dbg_line, 0); // file length = LEB128(0) - NA
610 }
611 }
612 PushByte(dbg_line, 0); // End of file_names.
613
614 // Set lnt header length.
615 UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4);
616
617 // Generate Line Number Program code, one long program for all methods.
618 LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE,
619 dbg_line, 0, 1);
620
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800621 DefaultSrcMap pc2java_map;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700622 for (size_t i = 0; i < method_info.size(); ++i) {
623 const OatWriter::DebugInfo &dbg = method_info[i];
624 const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_;
625 size_t file_index = files[file_name];
626 DCHECK_NE(file_index, 0U) << file_name;
627
628 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
629 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
630
631 // Start a new TAG: subroutine (2).
632 PushByte(dbg_info, 2);
633
634 // Enter name, low_pc, high_pc.
Vladimir Marko80b96d12015-02-19 15:50:28 +0000635 Push32(dbg_info, PushStr(dbg_str, dbg.method_name_));
636 Push32(dbg_info, dbg.low_pc_ + text_section_offset);
637 Push32(dbg_info, dbg.high_pc_ + text_section_offset);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700638
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700639 GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(),
640 &pc2java_map, dbg.low_pc_);
641 pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_);
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700642 if (!pc2java_map.empty()) {
643 line_table_generator.SetFile(file_index);
644 line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset);
645 line_table_generator.SetLine(1);
646 for (auto& src_map_elem : pc2java_map) {
647 line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_);
648 }
649 pc2java_map.clear();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700650 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800651 }
652
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700653 // End Sequence should have the highest address set.
654 line_table_generator.SetAddr(cunit_high_pc + text_section_offset);
655 line_table_generator.EndSequence();
Mark Mendellae9fd932014-02-10 16:14:35 -0800656
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700657 // set lnt length
658 UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4);
Mark Mendellae9fd932014-02-10 16:14:35 -0800659 }
660
661 // One byte terminator
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700662 PushByte(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800663
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700664 // Fill in cunit's low_pc and high_pc.
665 UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset);
666 UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset);
667
668 // We have now walked all the methods. Fill in lengths.
669 UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700670}
671
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700672template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
673 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
674 typename Elf_Phdr, typename Elf_Shdr>
Andreas Gampe86830382014-12-12 21:41:29 -0800675// Do not inline to avoid Clang stack frame problems. b/18738594
676NO_INLINE
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700677static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
678 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
679 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
680 OatWriter* oat_writer) {
681 std::unique_ptr<std::vector<uint8_t>> cfi_info(
682 ConstructCIEFrame(compiler_driver->GetInstructionSet()));
683
Ian Rogers0279ebb2014-10-08 17:27:48 -0700684 Elf_Addr text_section_address = builder->GetTextBuilder().GetSection()->sh_addr;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700685
686 // Iterate over the compiled methods.
687 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700688 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* symtab =
689 builder->GetSymtabBuilder();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700690 for (auto it = method_info.begin(); it != method_info.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700691 symtab->AddSymbol(it->method_name_, &builder->GetTextBuilder(), it->low_pc_, true,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700692 it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
693
Ningsheng Jianf9734552014-10-27 14:56:34 +0800694 // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
695 // instructions, so that disassembler tools can correctly disassemble.
696 if (it->compiled_method_->GetInstructionSet() == kThumb2) {
697 symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true,
698 0, STB_LOCAL, STT_NOTYPE);
699 }
700
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700701 // Include CFI for compiled method, if possible.
702 if (cfi_info.get() != nullptr) {
703 DCHECK(it->compiled_method_ != nullptr);
704
705 // Copy in the FDE, if present
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800706 const SwapVector<uint8_t>* fde = it->compiled_method_->GetCFIInfo();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700707 if (fde != nullptr) {
708 // Copy the information into cfi_info and then fix the address in the new copy.
709 int cur_offset = cfi_info->size();
710 cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
711
712 bool is_64bit = *(reinterpret_cast<const uint32_t*>(fde->data())) == 0xffffffff;
713
714 // Set the 'CIE_pointer' field.
715 uint64_t CIE_pointer = cur_offset + (is_64bit ? 12 : 4);
716 uint64_t offset_to_update = CIE_pointer;
717 if (is_64bit) {
718 (*cfi_info)[offset_to_update+0] = CIE_pointer;
719 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
720 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
721 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
722 (*cfi_info)[offset_to_update+4] = CIE_pointer >> 32;
723 (*cfi_info)[offset_to_update+5] = CIE_pointer >> 40;
724 (*cfi_info)[offset_to_update+6] = CIE_pointer >> 48;
725 (*cfi_info)[offset_to_update+7] = CIE_pointer >> 56;
726 } else {
727 (*cfi_info)[offset_to_update+0] = CIE_pointer;
728 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
729 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
730 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
731 }
732
733 // Set the 'initial_location' field.
734 offset_to_update += is_64bit ? 8 : 4;
735 if (is_64bit) {
736 const uint64_t quick_code_start = it->low_pc_ + text_section_address;
737 (*cfi_info)[offset_to_update+0] = quick_code_start;
738 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
739 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
740 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
741 (*cfi_info)[offset_to_update+4] = quick_code_start >> 32;
742 (*cfi_info)[offset_to_update+5] = quick_code_start >> 40;
743 (*cfi_info)[offset_to_update+6] = quick_code_start >> 48;
744 (*cfi_info)[offset_to_update+7] = quick_code_start >> 56;
745 } else {
746 const uint32_t quick_code_start = it->low_pc_ + text_section_address;
747 (*cfi_info)[offset_to_update+0] = quick_code_start;
748 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
749 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
750 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
751 }
752 }
753 }
754 }
755
756 bool hasCFI = (cfi_info.get() != nullptr);
757 bool hasLineInfo = false;
758 for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
759 if (dbg_info.dbgstream_ != nullptr &&
760 !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
761 hasLineInfo = true;
762 break;
763 }
764 }
765
766 if (hasLineInfo || hasCFI) {
767 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_info(".debug_info",
768 SHT_PROGBITS,
769 0, nullptr, 0, 1, 0);
770 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_abbrev(".debug_abbrev",
771 SHT_PROGBITS,
772 0, nullptr, 0, 1, 0);
773 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_str(".debug_str",
774 SHT_PROGBITS,
775 0, nullptr, 0, 1, 0);
776 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_line(".debug_line",
777 SHT_PROGBITS,
778 0, nullptr, 0, 1, 0);
779
780 FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
781 debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
782 hasLineInfo ? debug_line.GetBuffer() : nullptr,
783 text_section_address);
784
785 builder->RegisterRawSection(debug_info);
786 builder->RegisterRawSection(debug_abbrev);
787
788 if (hasCFI) {
789 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> eh_frame(".eh_frame",
790 SHT_PROGBITS,
791 SHF_ALLOC,
792 nullptr, 0, 4, 0);
793 eh_frame.SetBuffer(std::move(*cfi_info.get()));
794 builder->RegisterRawSection(eh_frame);
795 }
796
797 if (hasLineInfo) {
798 builder->RegisterRawSection(debug_line);
799 }
800
801 builder->RegisterRawSection(debug_str);
802 }
803}
804
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000805// Explicit instantiations
806template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
807 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>;
808template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
809 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>;
810
Brian Carlstrom7940e442013-07-12 13:46:57 -0700811} // namespace art