blob: 1bd83b6c854fa5d0615df6b93235808ed6b0fe9b [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"
Brian Carlstrom7940e442013-07-12 13:46:57 -070025#include "driver/compiler_driver.h"
Vladimir Marko20f85592015-03-19 10:07:02 +000026#include "driver/compiler_options.h"
Alex Light3470ab42014-06-18 10:35:45 -070027#include "dwarf.h"
David Srbecky6f715892015-03-30 14:21:42 +010028#include "dwarf/debug_frame_writer.h"
29#include "dwarf/debug_line_writer.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070030#include "elf_builder.h"
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070031#include "elf_file.h"
Nicolas Geoffray50cfe742014-02-19 13:27:42 +000032#include "elf_utils.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070033#include "file_output_stream.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070034#include "globals.h"
Andreas Gampe79273802014-08-05 20:21:05 -070035#include "leb128.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070036#include "oat.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070037#include "oat_writer.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070038#include "utils.h"
39
40namespace art {
41
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070042static void PushByte(std::vector<uint8_t>* buf, int data) {
43 buf->push_back(data & 0xff);
44}
45
46static uint32_t PushStr(std::vector<uint8_t>* buf, const char* str, const char* def = nullptr) {
47 if (str == nullptr) {
48 str = def;
49 }
50
51 uint32_t offset = buf->size();
52 for (size_t i = 0; str[i] != '\0'; ++i) {
53 buf->push_back(str[i]);
54 }
55 buf->push_back('\0');
56 return offset;
57}
58
59static uint32_t PushStr(std::vector<uint8_t>* buf, const std::string &str) {
60 uint32_t offset = buf->size();
61 buf->insert(buf->end(), str.begin(), str.end());
62 buf->push_back('\0');
63 return offset;
64}
65
Andreas Gampe79273802014-08-05 20:21:05 -070066static void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) {
67 (*buf)[offset+0] = data;
68 (*buf)[offset+1] = data >> 8;
69 (*buf)[offset+2] = data >> 16;
70 (*buf)[offset+3] = data >> 24;
71}
72
Andreas Gampe79273802014-08-05 20:21:05 -070073static void PushHalf(std::vector<uint8_t>* buf, int data) {
74 buf->push_back(data & 0xff);
75 buf->push_back((data >> 8) & 0xff);
76}
77
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000078template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
79 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
80 typename Elf_Phdr, typename Elf_Shdr>
81bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000082 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Create(File* elf_file,
Brian Carlstromb12f3472014-06-11 14:54:46 -070083 OatWriter* oat_writer,
84 const std::vector<const DexFile*>& dex_files,
85 const std::string& android_root,
86 bool is_host,
87 const CompilerDriver& driver) {
88 ElfWriterQuick elf_writer(driver, elf_file);
89 return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
90}
91
Ian Rogers0279ebb2014-10-08 17:27:48 -070092class OatWriterWrapper FINAL : public CodeOutput {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070093 public:
94 explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {}
95
Vladimir Markof4da6752014-08-01 19:04:18 +010096 void SetCodeOffset(size_t offset) {
97 oat_writer_->SetOatDataOffset(offset);
98 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -070099 bool Write(OutputStream* out) OVERRIDE {
100 return oat_writer_->Write(out);
101 }
102 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700103 OatWriter* const oat_writer_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700104};
105
106template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
107 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
108 typename Elf_Phdr, typename Elf_Shdr>
109static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
110 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
111 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
112 OatWriter* oat_writer);
113
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000114template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
115 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
116 typename Elf_Phdr, typename Elf_Shdr>
117bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
118 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Write(OatWriter* oat_writer,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700119 const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED,
120 const std::string& android_root_unused ATTRIBUTE_UNUSED,
121 bool is_host_unused ATTRIBUTE_UNUSED) {
Andreas Gampe79273802014-08-05 20:21:05 -0700122 constexpr bool debug = false;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700123 const OatHeader& oat_header = oat_writer->GetOatHeader();
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000124 Elf_Word oat_data_size = oat_header.GetExecutableOffset();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700125 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
Vladimir Marko5c42c292015-02-25 12:02:49 +0000126 uint32_t oat_bss_size = oat_writer->GetBssSize();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700127
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700128 OatWriterWrapper wrapper(oat_writer);
129
130 std::unique_ptr<ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
131 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> > builder(
132 new ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
133 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>(
134 &wrapper,
135 elf_file_,
136 compiler_driver_->GetInstructionSet(),
137 0,
138 oat_data_size,
139 oat_data_size,
140 oat_exec_size,
Vladimir Marko5c42c292015-02-25 12:02:49 +0000141 RoundUp(oat_data_size + oat_exec_size, kPageSize),
142 oat_bss_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700143 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
144 debug));
Alex Light78382fa2014-06-06 15:45:32 -0700145
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700146 if (!builder->Init()) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700147 return false;
148 }
149
Andreas Gampe79273802014-08-05 20:21:05 -0700150 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700151 WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700152 }
153
Alex Light53cb16b2014-06-12 11:26:29 -0700154 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700155 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches(
156 ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, sizeof(uintptr_t), sizeof(uintptr_t));
Vladimir Markof4da6752014-08-01 19:04:18 +0100157 const std::vector<uintptr_t>& locations = oat_writer->GetAbsolutePatchLocations();
158 const uint8_t* begin = reinterpret_cast<const uint8_t*>(&locations[0]);
159 const uint8_t* end = begin + locations.size() * sizeof(locations[0]);
160 oat_patches.GetBuffer()->assign(begin, end);
161 if (debug) {
162 LOG(INFO) << "Prepared .oat_patches for " << locations.size() << " patches.";
163 }
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700164 builder->RegisterRawSection(oat_patches);
Alex Light53cb16b2014-06-12 11:26:29 -0700165 }
166
Brian Carlstrom18a49cc2014-08-29 16:20:48 -0700167 return builder->Write();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700168}
Mark Mendellae9fd932014-02-10 16:14:35 -0800169
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700170// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
David Srbecky6f715892015-03-30 14:21:42 +0100171static void GetLineInfoForJava(const uint8_t* dbgstream, DefaultSrcMap* dex2line) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700172 if (dbgstream == nullptr) {
173 return;
174 }
175
176 int adjopcode;
177 uint32_t dex_offset = 0;
178 uint32_t java_line = DecodeUnsignedLeb128(&dbgstream);
179
180 // skip parameters
181 for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) {
182 DecodeUnsignedLeb128(&dbgstream);
183 }
184
185 for (bool is_end = false; is_end == false; ) {
186 uint8_t opcode = *dbgstream;
187 dbgstream++;
188 switch (opcode) {
189 case DexFile::DBG_END_SEQUENCE:
190 is_end = true;
191 break;
192
193 case DexFile::DBG_ADVANCE_PC:
194 dex_offset += DecodeUnsignedLeb128(&dbgstream);
195 break;
196
197 case DexFile::DBG_ADVANCE_LINE:
198 java_line += DecodeSignedLeb128(&dbgstream);
199 break;
200
201 case DexFile::DBG_START_LOCAL:
202 case DexFile::DBG_START_LOCAL_EXTENDED:
203 DecodeUnsignedLeb128(&dbgstream);
204 DecodeUnsignedLeb128(&dbgstream);
205 DecodeUnsignedLeb128(&dbgstream);
206
207 if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) {
208 DecodeUnsignedLeb128(&dbgstream);
209 }
210 break;
211
212 case DexFile::DBG_END_LOCAL:
213 case DexFile::DBG_RESTART_LOCAL:
214 DecodeUnsignedLeb128(&dbgstream);
215 break;
216
217 case DexFile::DBG_SET_PROLOGUE_END:
218 case DexFile::DBG_SET_EPILOGUE_BEGIN:
219 case DexFile::DBG_SET_FILE:
220 break;
221
222 default:
223 adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
224 dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
225 java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
David Srbecky6f715892015-03-30 14:21:42 +0100226 dex2line->push_back({dex_offset, static_cast<int32_t>(java_line)});
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700227 break;
228 }
Andreas Gampe79273802014-08-05 20:21:05 -0700229 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800230}
231
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700232/*
233 * @brief Generate the DWARF debug_info and debug_abbrev sections
234 * @param oat_writer The Oat file Writer.
235 * @param dbg_info Compilation unit information.
236 * @param dbg_abbrev Abbreviations used to generate dbg_info.
237 * @param dbg_str Debug strings.
238 */
239static void FillInCFIInformation(OatWriter* oat_writer,
240 std::vector<uint8_t>* dbg_info,
241 std::vector<uint8_t>* dbg_abbrev,
242 std::vector<uint8_t>* dbg_str,
243 std::vector<uint8_t>* dbg_line,
244 uint32_t text_section_offset) {
David Srbecky6f715892015-03-30 14:21:42 +0100245 const std::vector<OatWriter::DebugInfo>& method_infos = oat_writer->GetCFIMethodInfo();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700246
247 uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
248
David Srbecky6f715892015-03-30 14:21:42 +0100249 constexpr bool use_64bit_addresses = false;
250
Mark Mendellae9fd932014-02-10 16:14:35 -0800251 // Create the debug_abbrev section with boilerplate information.
252 // We only care about low_pc and high_pc right now for the compilation
253 // unit and methods.
254
255 // Tag 1: Compilation unit: DW_TAG_compile_unit.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700256 PushByte(dbg_abbrev, 1);
David Srbecky6f715892015-03-30 14:21:42 +0100257 PushByte(dbg_abbrev, dwarf::DW_TAG_compile_unit);
Mark Mendellae9fd932014-02-10 16:14:35 -0800258
259 // There are children (the methods).
David Srbecky6f715892015-03-30 14:21:42 +0100260 PushByte(dbg_abbrev, dwarf::DW_CHILDREN_yes);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700261
262 // DW_AT_producer DW_FORM_data1.
263 // REVIEW: we can get rid of dbg_str section if
264 // DW_FORM_string (immediate string) was used everywhere instead of
265 // DW_FORM_strp (ref to string from .debug_str section).
266 // DW_FORM_strp makes sense only if we reuse the strings.
David Srbecky6f715892015-03-30 14:21:42 +0100267 PushByte(dbg_abbrev, dwarf::DW_AT_producer);
268 PushByte(dbg_abbrev, dwarf::DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800269
270 // DW_LANG_Java DW_FORM_data1.
David Srbecky6f715892015-03-30 14:21:42 +0100271 PushByte(dbg_abbrev, dwarf::DW_AT_language);
272 PushByte(dbg_abbrev, dwarf::DW_FORM_data1);
Mark Mendellae9fd932014-02-10 16:14:35 -0800273
274 // DW_AT_low_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100275 PushByte(dbg_abbrev, dwarf::DW_AT_low_pc);
276 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800277
278 // DW_AT_high_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100279 PushByte(dbg_abbrev, dwarf::DW_AT_high_pc);
280 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700281
282 if (dbg_line != nullptr) {
283 // DW_AT_stmt_list DW_FORM_sec_offset.
David Srbecky6f715892015-03-30 14:21:42 +0100284 PushByte(dbg_abbrev, dwarf::DW_AT_stmt_list);
285 PushByte(dbg_abbrev, dwarf::DW_FORM_data4);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700286 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800287
288 // End of DW_TAG_compile_unit.
David Srbecky6f715892015-03-30 14:21:42 +0100289 PushByte(dbg_abbrev, 0); // DW_AT.
290 PushByte(dbg_abbrev, 0); // DW_FORM.
Mark Mendellae9fd932014-02-10 16:14:35 -0800291
292 // Tag 2: Compilation unit: DW_TAG_subprogram.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700293 PushByte(dbg_abbrev, 2);
David Srbecky6f715892015-03-30 14:21:42 +0100294 PushByte(dbg_abbrev, dwarf::DW_TAG_subprogram);
Mark Mendellae9fd932014-02-10 16:14:35 -0800295
296 // There are no children.
David Srbecky6f715892015-03-30 14:21:42 +0100297 PushByte(dbg_abbrev, dwarf::DW_CHILDREN_no);
Mark Mendellae9fd932014-02-10 16:14:35 -0800298
299 // Name of the method.
David Srbecky6f715892015-03-30 14:21:42 +0100300 PushByte(dbg_abbrev, dwarf::DW_AT_name);
301 PushByte(dbg_abbrev, dwarf::DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -0800302
303 // DW_AT_low_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100304 PushByte(dbg_abbrev, dwarf::DW_AT_low_pc);
305 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800306
307 // DW_AT_high_pc DW_FORM_addr.
David Srbecky6f715892015-03-30 14:21:42 +0100308 PushByte(dbg_abbrev, dwarf::DW_AT_high_pc);
309 PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -0800310
311 // End of DW_TAG_subprogram.
David Srbecky6f715892015-03-30 14:21:42 +0100312 PushByte(dbg_abbrev, 0); // DW_AT.
313 PushByte(dbg_abbrev, 0); // DW_FORM.
314
315 // End of abbrevs for compilation unit
316 PushByte(dbg_abbrev, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800317
318 // Start the debug_info section with the header information
319 // 'unit_length' will be filled in later.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700320 int cunit_length = dbg_info->size();
Vladimir Marko80b96d12015-02-19 15:50:28 +0000321 Push32(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800322
323 // 'version' - 3.
324 PushHalf(dbg_info, 3);
325
326 // Offset into .debug_abbrev section (always 0).
Vladimir Marko80b96d12015-02-19 15:50:28 +0000327 Push32(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800328
David Srbecky6f715892015-03-30 14:21:42 +0100329 // Address size: 4 or 8.
330 PushByte(dbg_info, use_64bit_addresses ? 8 : 4);
Mark Mendellae9fd932014-02-10 16:14:35 -0800331
332 // Start the description for the compilation unit.
333 // This uses tag 1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700334 PushByte(dbg_info, 1);
335
336 // The producer is Android dex2oat.
Vladimir Marko80b96d12015-02-19 15:50:28 +0000337 Push32(dbg_info, producer_str_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800338
339 // The language is Java.
David Srbecky6f715892015-03-30 14:21:42 +0100340 PushByte(dbg_info, dwarf::DW_LANG_Java);
Mark Mendellae9fd932014-02-10 16:14:35 -0800341
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700342 // low_pc and high_pc.
David Srbecky6f715892015-03-30 14:21:42 +0100343 uint32_t cunit_low_pc = static_cast<uint32_t>(-1);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700344 uint32_t cunit_high_pc = 0;
David Srbecky6f715892015-03-30 14:21:42 +0100345 for (auto method_info : method_infos) {
346 cunit_low_pc = std::min(cunit_low_pc, method_info.low_pc_);
347 cunit_high_pc = std::max(cunit_high_pc, method_info.high_pc_);
348 }
349 Push32(dbg_info, cunit_low_pc + text_section_offset);
350 Push32(dbg_info, cunit_high_pc + text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800351
David Srbecky6f715892015-03-30 14:21:42 +0100352 if (dbg_line != nullptr) {
353 // Line number table offset.
354 Push32(dbg_info, dbg_line->size());
355 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800356
David Srbecky6f715892015-03-30 14:21:42 +0100357 for (auto method_info : method_infos) {
358 // Start a new TAG: subroutine (2).
359 PushByte(dbg_info, 2);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700360
David Srbecky6f715892015-03-30 14:21:42 +0100361 // Enter name, low_pc, high_pc.
362 Push32(dbg_info, PushStr(dbg_str, method_info.method_name_));
363 Push32(dbg_info, method_info.low_pc_ + text_section_offset);
364 Push32(dbg_info, method_info.high_pc_ + text_section_offset);
365 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700366
David Srbecky6f715892015-03-30 14:21:42 +0100367 if (dbg_line != nullptr) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700368 // TODO: in gdb info functions <regexp> - reports Java functions, but
369 // source file is <unknown> because .debug_line is formed as one
370 // compilation unit. To fix this it is possible to generate
371 // a separate compilation unit for every distinct Java source.
372 // Each of the these compilation units can have several non-adjacent
373 // method ranges.
374
David Srbecky6f715892015-03-30 14:21:42 +0100375 std::vector<dwarf::DebugLineWriter<>::FileEntry> files;
376 std::unordered_map<std::string, size_t> files_map;
377 std::vector<std::string> directories;
378 std::unordered_map<std::string, size_t> directories_map;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700379
David Srbecky6f715892015-03-30 14:21:42 +0100380 int code_factor_bits_ = 0;
381 int isa = -1;
382 switch (oat_writer->GetOatHeader().GetInstructionSet()) {
David Srbecky189ae822015-04-04 10:15:17 +0100383 case kArm: // arm actually means thumb2.
David Srbecky6f715892015-03-30 14:21:42 +0100384 case kThumb2:
385 code_factor_bits_ = 1; // 16-bit instuctions
386 isa = 1; // DW_ISA_ARM_thumb.
387 break;
David Srbecky6f715892015-03-30 14:21:42 +0100388 case kArm64:
389 case kMips:
390 case kMips64:
391 code_factor_bits_ = 2; // 32-bit instructions
392 break;
393 case kNone:
394 case kX86:
395 case kX86_64:
396 break;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700397 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700398
David Srbecky6f715892015-03-30 14:21:42 +0100399 dwarf::DebugLineOpCodeWriter<> opcodes(use_64bit_addresses, code_factor_bits_);
400 opcodes.SetAddress(text_section_offset + cunit_low_pc);
401 if (isa != -1) {
402 opcodes.SetISA(isa);
403 }
404 DefaultSrcMap dex2line_map;
405 for (size_t i = 0; i < method_infos.size(); i++) {
406 const OatWriter::DebugInfo& method_info = method_infos[i];
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700407
David Srbecky6f715892015-03-30 14:21:42 +0100408 // Addresses in the line table should be unique and increasing.
409 if (method_info.deduped_) {
410 continue;
411 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700412
David Srbecky6f715892015-03-30 14:21:42 +0100413 // Get and deduplicate directory and filename.
414 int file_index = 0; // 0 - primary source file of the compilation.
415 if (method_info.src_file_name_ != nullptr) {
416 std::string file_name(method_info.src_file_name_);
417 size_t file_name_slash = file_name.find_last_of('/');
418 std::string class_name(method_info.class_descriptor_);
419 size_t class_name_slash = class_name.find_last_of('/');
420 std::string full_path(file_name);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700421
David Srbecky6f715892015-03-30 14:21:42 +0100422 // Guess directory from package name.
423 int directory_index = 0; // 0 - current directory of the compilation.
424 if (file_name_slash == std::string::npos && // Just filename.
425 class_name.front() == 'L' && // Type descriptor for a class.
426 class_name_slash != std::string::npos) { // Has package name.
427 std::string package_name = class_name.substr(1, class_name_slash - 1);
428 auto it = directories_map.find(package_name);
429 if (it == directories_map.end()) {
430 directory_index = 1 + directories.size();
431 directories_map.emplace(package_name, directory_index);
432 directories.push_back(package_name);
433 } else {
434 directory_index = it->second;
435 }
436 full_path = package_name + "/" + file_name;
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700437 }
David Srbecky6f715892015-03-30 14:21:42 +0100438
439 // Add file entry.
440 auto it2 = files_map.find(full_path);
441 if (it2 == files_map.end()) {
442 file_index = 1 + files.size();
443 files_map.emplace(full_path, file_index);
444 files.push_back(dwarf::DebugLineWriter<>::FileEntry {
445 file_name,
446 directory_index,
447 0, // Modification time - NA.
448 0, // File size - NA.
449 });
450 } else {
451 file_index = it2->second;
452 }
453 }
454 opcodes.SetFile(file_index);
455
456 // Generate mapping opcodes from PC to Java lines.
457 dex2line_map.clear();
458 GetLineInfoForJava(method_info.dbgstream_, &dex2line_map);
459 uint32_t low_pc = text_section_offset + method_info.low_pc_;
460 if (file_index != 0 && !dex2line_map.empty()) {
461 bool first = true;
462 for (SrcMapElem pc2dex : method_info.compiled_method_->GetSrcMappingTable()) {
463 uint32_t pc = pc2dex.from_;
464 int dex = pc2dex.to_;
465 auto dex2line = dex2line_map.Find(static_cast<uint32_t>(dex));
466 if (dex2line.first) {
467 int line = dex2line.second;
468 if (first) {
469 first = false;
470 if (pc > 0) {
471 // Assume that any preceding code is prologue.
472 int first_line = dex2line_map.front().to_;
473 // Prologue is not a sensible place for a breakpoint.
474 opcodes.NegateStmt();
475 opcodes.AddRow(low_pc, first_line);
476 opcodes.NegateStmt();
477 opcodes.SetPrologueEnd();
478 }
479 opcodes.AddRow(low_pc + pc, line);
480 } else if (line != opcodes.CurrentLine()) {
481 opcodes.AddRow(low_pc + pc, line);
482 }
483 }
484 }
485 } else {
486 // line 0 - instruction cannot be attributed to any source line.
487 opcodes.AddRow(low_pc, 0);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700488 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800489 }
490
David Srbecky6f715892015-03-30 14:21:42 +0100491 opcodes.AdvancePC(text_section_offset + cunit_high_pc);
492 opcodes.EndSequence();
Mark Mendellae9fd932014-02-10 16:14:35 -0800493
David Srbecky6f715892015-03-30 14:21:42 +0100494 dwarf::DebugLineWriter<> dbg_line_writer(dbg_line);
495 dbg_line_writer.WriteTable(directories, files, opcodes);
Mark Mendellae9fd932014-02-10 16:14:35 -0800496 }
497
David Srbecky6f715892015-03-30 14:21:42 +0100498 // One byte terminator.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700499 PushByte(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -0800500
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700501 // We have now walked all the methods. Fill in lengths.
502 UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700503}
504
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700505template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
506 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
507 typename Elf_Phdr, typename Elf_Shdr>
Andreas Gampe86830382014-12-12 21:41:29 -0800508// Do not inline to avoid Clang stack frame problems. b/18738594
509NO_INLINE
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700510static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
511 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
512 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
513 OatWriter* oat_writer) {
David Srbecky8c578312015-04-07 19:46:22 +0100514 UNUSED(compiler_driver);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700515 Elf_Addr text_section_address = builder->GetTextBuilder().GetSection()->sh_addr;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700516
517 // Iterate over the compiled methods.
518 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700519 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* symtab =
520 builder->GetSymtabBuilder();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700521 for (auto it = method_info.begin(); it != method_info.end(); ++it) {
David Srbecky6f715892015-03-30 14:21:42 +0100522 uint32_t low_pc = it->low_pc_;
523 // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
524 low_pc += it->compiled_method_->CodeDelta();
525 symtab->AddSymbol(it->method_name_, &builder->GetTextBuilder(), low_pc,
526 true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700527
Ningsheng Jianf9734552014-10-27 14:56:34 +0800528 // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
529 // instructions, so that disassembler tools can correctly disassemble.
530 if (it->compiled_method_->GetInstructionSet() == kThumb2) {
531 symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true,
532 0, STB_LOCAL, STT_NOTYPE);
533 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700534 }
535
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700536 bool hasLineInfo = false;
537 for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
538 if (dbg_info.dbgstream_ != nullptr &&
539 !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
540 hasLineInfo = true;
541 break;
542 }
543 }
544
David Srbecky8c578312015-04-07 19:46:22 +0100545 if (hasLineInfo) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700546 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_info(".debug_info",
547 SHT_PROGBITS,
548 0, nullptr, 0, 1, 0);
549 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_abbrev(".debug_abbrev",
550 SHT_PROGBITS,
551 0, nullptr, 0, 1, 0);
552 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_str(".debug_str",
553 SHT_PROGBITS,
554 0, nullptr, 0, 1, 0);
555 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_line(".debug_line",
556 SHT_PROGBITS,
557 0, nullptr, 0, 1, 0);
558
559 FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
560 debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
561 hasLineInfo ? debug_line.GetBuffer() : nullptr,
562 text_section_address);
563
564 builder->RegisterRawSection(debug_info);
565 builder->RegisterRawSection(debug_abbrev);
566
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700567 if (hasLineInfo) {
568 builder->RegisterRawSection(debug_line);
569 }
570
571 builder->RegisterRawSection(debug_str);
572 }
573}
574
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000575// Explicit instantiations
576template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
577 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>;
578template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
579 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>;
580
Brian Carlstrom7940e442013-07-12 13:46:57 -0700581} // namespace art