blob: e45eb61030115e033c9452ef6fd9888039c3bd6a [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"
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070026#include "elf_file.h"
Nicolas Geoffray50cfe742014-02-19 13:27:42 +000027#include "elf_utils.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070028#include "file_output_stream.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070029#include "globals.h"
Andreas Gampe79273802014-08-05 20:21:05 -070030#include "leb128.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070031#include "oat.h"
Brian Carlstromc50d8e12013-07-23 22:35:16 -070032#include "oat_writer.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070033#include "utils.h"
34
35namespace art {
36
Brian Carlstromb12f3472014-06-11 14:54:46 -070037static constexpr Elf32_Word NextOffset(const Elf32_Shdr& cur, const Elf32_Shdr& prev) {
38 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
Brian Carlstrom7940e442013-07-12 13:46:57 -070039}
40
Brian Carlstromb12f3472014-06-11 14:54:46 -070041static uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
42 return ((binding) << 4) + ((type) & 0xf);
43}
44
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070045static void PushByte(std::vector<uint8_t>* buf, int data) {
46 buf->push_back(data & 0xff);
47}
48
49static uint32_t PushStr(std::vector<uint8_t>* buf, const char* str, const char* def = nullptr) {
50 if (str == nullptr) {
51 str = def;
52 }
53
54 uint32_t offset = buf->size();
55 for (size_t i = 0; str[i] != '\0'; ++i) {
56 buf->push_back(str[i]);
57 }
58 buf->push_back('\0');
59 return offset;
60}
61
62static uint32_t PushStr(std::vector<uint8_t>* buf, const std::string &str) {
63 uint32_t offset = buf->size();
64 buf->insert(buf->end(), str.begin(), str.end());
65 buf->push_back('\0');
66 return offset;
67}
68
Andreas Gampe79273802014-08-05 20:21:05 -070069static void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) {
70 (*buf)[offset+0] = data;
71 (*buf)[offset+1] = data >> 8;
72 (*buf)[offset+2] = data >> 16;
73 (*buf)[offset+3] = data >> 24;
74}
75
Andreas Gampe79273802014-08-05 20:21:05 -070076static void PushHalf(std::vector<uint8_t>* buf, int data) {
77 buf->push_back(data & 0xff);
78 buf->push_back((data >> 8) & 0xff);
79}
80
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070081bool ElfWriterQuick::ElfBuilder::Init() {
Brian Carlstromb12f3472014-06-11 14:54:46 -070082 // The basic layout of the elf file. Order may be different in final output.
Brian Carlstrom7940e442013-07-12 13:46:57 -070083 // +-------------------------+
84 // | Elf32_Ehdr |
85 // +-------------------------+
86 // | Elf32_Phdr PHDR |
87 // | Elf32_Phdr LOAD R | .dynsym .dynstr .hash .rodata
88 // | Elf32_Phdr LOAD R X | .text
89 // | Elf32_Phdr LOAD RW | .dynamic
90 // | Elf32_Phdr DYNAMIC | .dynamic
91 // +-------------------------+
92 // | .dynsym |
93 // | Elf32_Sym STN_UNDEF |
94 // | Elf32_Sym oatdata |
95 // | Elf32_Sym oatexec |
96 // | Elf32_Sym oatlastword |
97 // +-------------------------+
98 // | .dynstr |
99 // | \0 |
100 // | oatdata\0 |
101 // | oatexec\0 |
102 // | oatlastword\0 |
103 // | boot.oat\0 |
104 // +-------------------------+
105 // | .hash |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700106 // | Elf32_Word nbucket = b |
107 // | Elf32_Word nchain = c |
108 // | Elf32_Word bucket[0] |
109 // | ... |
110 // | Elf32_Word bucket[b - 1]|
111 // | Elf32_Word chain[0] |
112 // | ... |
113 // | Elf32_Word chain[c - 1] |
Brian Carlstrom7940e442013-07-12 13:46:57 -0700114 // +-------------------------+
115 // | .rodata |
116 // | oatdata..oatexec-4 |
117 // +-------------------------+
118 // | .text |
119 // | oatexec..oatlastword |
120 // +-------------------------+
121 // | .dynamic |
122 // | Elf32_Dyn DT_SONAME |
123 // | Elf32_Dyn DT_HASH |
124 // | Elf32_Dyn DT_SYMTAB |
125 // | Elf32_Dyn DT_SYMENT |
126 // | Elf32_Dyn DT_STRTAB |
127 // | Elf32_Dyn DT_STRSZ |
128 // | Elf32_Dyn DT_NULL |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700129 // +-------------------------+ (Optional)
130 // | .strtab | (Optional)
131 // | program symbol names | (Optional)
132 // +-------------------------+ (Optional)
133 // | .symtab | (Optional)
134 // | program symbols | (Optional)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700135 // +-------------------------+
136 // | .shstrtab |
137 // | \0 |
138 // | .dynamic\0 |
139 // | .dynsym\0 |
140 // | .dynstr\0 |
141 // | .hash\0 |
142 // | .rodata\0 |
143 // | .text\0 |
144 // | .shstrtab\0 |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700145 // | .symtab\0 | (Optional)
146 // | .strtab\0 | (Optional)
147 // | .debug_str\0 | (Optional)
148 // | .debug_info\0 | (Optional)
Tong Shen35e1e6a2014-07-30 09:31:22 -0700149 // | .eh_frame\0 | (Optional)
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700150 // | .debug_line\0 | (Optional)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700151 // | .debug_abbrev\0 | (Optional)
152 // +-------------------------+ (Optional)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700153 // | .debug_info | (Optional)
154 // +-------------------------+ (Optional)
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700155 // | .debug_abbrev | (Optional)
156 // +-------------------------+ (Optional)
Tong Shen35e1e6a2014-07-30 09:31:22 -0700157 // | .eh_frame | (Optional)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700158 // +-------------------------+ (Optional)
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700159 // | .debug_line | (Optional)
160 // +-------------------------+ (Optional)
161 // | .debug_str | (Optional)
162 // +-------------------------+ (Optional)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 // | Elf32_Shdr NULL |
164 // | Elf32_Shdr .dynsym |
165 // | Elf32_Shdr .dynstr |
166 // | Elf32_Shdr .hash |
167 // | Elf32_Shdr .text |
168 // | Elf32_Shdr .rodata |
169 // | Elf32_Shdr .dynamic |
170 // | Elf32_Shdr .shstrtab |
Mark Mendellae9fd932014-02-10 16:14:35 -0800171 // | Elf32_Shdr .debug_info | (Optional)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700172 // | Elf32_Shdr .debug_abbrev| (Optional)
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700173 // | Elf32_Shdr .eh_frame | (Optional)
174 // | Elf32_Shdr .debug_line | (Optional)
175 // | Elf32_Shdr .debug_str | (Optional)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700176 // +-------------------------+
177
Brian Carlstromb12f3472014-06-11 14:54:46 -0700178 if (fatal_error_) {
179 return false;
180 }
181 // Step 1. Figure out all the offsets.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700182
Brian Carlstromb12f3472014-06-11 14:54:46 -0700183 if (debug_logging_) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700184 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
185 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700186 }
187
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700188 memset(&program_headers_, 0, sizeof(program_headers_));
189 program_headers_[PH_PHDR].p_type = PT_PHDR;
190 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
191 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
192 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
193 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
194 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
195 program_headers_[PH_PHDR].p_flags = PF_R;
196 program_headers_[PH_PHDR].p_align = sizeof(Elf32_Word);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700197
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700198 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
199 program_headers_[PH_LOAD_R__].p_offset = 0;
200 program_headers_[PH_LOAD_R__].p_vaddr = 0;
201 program_headers_[PH_LOAD_R__].p_paddr = 0;
202 program_headers_[PH_LOAD_R__].p_flags = PF_R;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700203
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700204 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
205 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700206
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700207 program_headers_[PH_LOAD_RW_].p_type = PT_LOAD;
208 program_headers_[PH_LOAD_RW_].p_flags = PF_R | PF_W;
209
210 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
211 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700212
213 // Get the dynstr string.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700214 dynstr_ = dynsym_builder_.GenerateStrtab();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700215
216 // Add the SONAME to the dynstr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700217 dynstr_soname_offset_ = dynstr_.size();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700218 std::string file_name(elf_file_->GetPath());
219 size_t directory_separator_pos = file_name.rfind('/');
220 if (directory_separator_pos != std::string::npos) {
221 file_name = file_name.substr(directory_separator_pos + 1);
222 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700223 dynstr_ += file_name;
224 dynstr_ += '\0';
Brian Carlstromb12f3472014-06-11 14:54:46 -0700225 if (debug_logging_) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700226 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
227 << std::hex << " " << dynstr_.size();
Brian Carlstrom8758c642014-06-11 14:22:02 -0700228 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
229 << std::hex << " " << dynsym_builder_.GetSize();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230 }
231
Brian Carlstromb12f3472014-06-11 14:54:46 -0700232 // Get the section header string table.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700233 shstrtab_ += '\0';
Brian Carlstromb12f3472014-06-11 14:54:46 -0700234
235 // Setup sym_undef
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700236 memset(&null_hdr_, 0, sizeof(null_hdr_));
237 null_hdr_.sh_type = SHT_NULL;
238 null_hdr_.sh_link = SHN_UNDEF;
239 section_ptrs_.push_back(&null_hdr_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700240
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700241 section_index_ = 1;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700242
243 // setup .dynsym
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700244 section_ptrs_.push_back(&dynsym_builder_.section_);
245 AssignSectionStr(&dynsym_builder_, &shstrtab_);
246 dynsym_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700247
248 // Setup .dynstr
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700249 section_ptrs_.push_back(&dynsym_builder_.strtab_.section_);
250 AssignSectionStr(&dynsym_builder_.strtab_, &shstrtab_);
251 dynsym_builder_.strtab_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700252
253 // Setup .hash
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700254 section_ptrs_.push_back(&hash_builder_.section_);
255 AssignSectionStr(&hash_builder_, &shstrtab_);
256 hash_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700257
258 // Setup .rodata
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700259 section_ptrs_.push_back(&rodata_builder_.section_);
260 AssignSectionStr(&rodata_builder_, &shstrtab_);
261 rodata_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700262
263 // Setup .text
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700264 section_ptrs_.push_back(&text_builder_.section_);
265 AssignSectionStr(&text_builder_, &shstrtab_);
266 text_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700267
268 // Setup .dynamic
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700269 section_ptrs_.push_back(&dynamic_builder_.section_);
270 AssignSectionStr(&dynamic_builder_, &shstrtab_);
271 dynamic_builder_.section_index_ = section_index_++;
Mark Mendellae9fd932014-02-10 16:14:35 -0800272
Brian Carlstromb12f3472014-06-11 14:54:46 -0700273 // Fill in the hash section.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700274 hash_ = dynsym_builder_.GenerateHashContents();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700275
276 if (debug_logging_) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700277 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf32_Word)
278 << std::hex << " " << hash_.size() * sizeof(Elf32_Word);
Mark Mendellae9fd932014-02-10 16:14:35 -0800279 }
280
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700281 Elf32_Word base_offset = sizeof(Elf32_Ehdr) + sizeof(program_headers_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700282
283 // Get the layout in the sections.
284 //
285 // Get the layout of the dynsym section.
286 dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign);
287 dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset;
Brian Carlstrom8758c642014-06-11 14:22:02 -0700288 dynsym_builder_.section_.sh_size = dynsym_builder_.GetSize() * sizeof(Elf32_Sym);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700289 dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink();
290
291 // Get the layout of the dynstr section.
292 dynsym_builder_.strtab_.section_.sh_offset = NextOffset(dynsym_builder_.strtab_.section_,
293 dynsym_builder_.section_);
294 dynsym_builder_.strtab_.section_.sh_addr = dynsym_builder_.strtab_.section_.sh_offset;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700295 dynsym_builder_.strtab_.section_.sh_size = dynstr_.size();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700296 dynsym_builder_.strtab_.section_.sh_link = dynsym_builder_.strtab_.GetLink();
297
298 // Get the layout of the hash section
299 hash_builder_.section_.sh_offset = NextOffset(hash_builder_.section_,
300 dynsym_builder_.strtab_.section_);
301 hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700302 hash_builder_.section_.sh_size = hash_.size() * sizeof(Elf32_Word);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700303 hash_builder_.section_.sh_link = hash_builder_.GetLink();
304
305 // Get the layout of the rodata section.
306 rodata_builder_.section_.sh_offset = NextOffset(rodata_builder_.section_,
307 hash_builder_.section_);
308 rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset;
309 rodata_builder_.section_.sh_size = rodata_builder_.size_;
310 rodata_builder_.section_.sh_link = rodata_builder_.GetLink();
311
312 // Get the layout of the text section.
313 text_builder_.section_.sh_offset = NextOffset(text_builder_.section_, rodata_builder_.section_);
314 text_builder_.section_.sh_addr = text_builder_.section_.sh_offset;
315 text_builder_.section_.sh_size = text_builder_.size_;
316 text_builder_.section_.sh_link = text_builder_.GetLink();
317 CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize);
318
319 // Get the layout of the dynamic section.
320 dynamic_builder_.section_.sh_offset = NextOffset(dynamic_builder_.section_,
321 text_builder_.section_);
322 dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset;
Brian Carlstrom8758c642014-06-11 14:22:02 -0700323 dynamic_builder_.section_.sh_size = dynamic_builder_.GetSize() * sizeof(Elf32_Dyn);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700324 dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink();
325
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700326 if (debug_logging_) {
327 LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset
328 << " dynsym size=" << dynsym_builder_.section_.sh_size;
329 LOG(INFO) << "dynstr off=" << dynsym_builder_.strtab_.section_.sh_offset
330 << " dynstr size=" << dynsym_builder_.strtab_.section_.sh_size;
331 LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset
332 << " hash size=" << hash_builder_.section_.sh_size;
333 LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset
334 << " rodata size=" << rodata_builder_.section_.sh_size;
335 LOG(INFO) << "text off=" << text_builder_.section_.sh_offset
336 << " text size=" << text_builder_.section_.sh_size;
337 LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset
338 << " dynamic size=" << dynamic_builder_.section_.sh_size;
339 }
340
341 return true;
342}
343
344bool ElfWriterQuick::ElfBuilder::Write() {
345 std::vector<ElfFilePiece> pieces;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700346 Elf32_Shdr prev = dynamic_builder_.section_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700347 std::string strtab;
348
349 if (IncludingDebugSymbols()) {
350 // Setup .symtab
351 section_ptrs_.push_back(&symtab_builder_.section_);
352 AssignSectionStr(&symtab_builder_, &shstrtab_);
353 symtab_builder_.section_index_ = section_index_++;
354
355 // Setup .strtab
356 section_ptrs_.push_back(&symtab_builder_.strtab_.section_);
357 AssignSectionStr(&symtab_builder_.strtab_, &shstrtab_);
358 symtab_builder_.strtab_.section_index_ = section_index_++;
359
360 strtab = symtab_builder_.GenerateStrtab();
361 if (debug_logging_) {
362 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
363 << std::hex << " " << strtab.size();
364 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
365 << std::hex << " " << symtab_builder_.GetSize();
366 }
367 }
368
369 // Setup all the other sections.
370 for (ElfRawSectionBuilder *builder = other_builders_.data(),
371 *end = builder + other_builders_.size();
372 builder != end; ++builder) {
373 section_ptrs_.push_back(&builder->section_);
374 AssignSectionStr(builder, &shstrtab_);
375 builder->section_index_ = section_index_++;
376 }
377
378 // Setup shstrtab
379 section_ptrs_.push_back(&shstrtab_builder_.section_);
380 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
381 shstrtab_builder_.section_index_ = section_index_++;
382
383 if (debug_logging_) {
384 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
385 << std::hex << " " << shstrtab_.size();
386 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
387 << std::hex << " " << section_ptrs_.size();
388 }
389
Brian Carlstromb12f3472014-06-11 14:54:46 -0700390 if (IncludingDebugSymbols()) {
391 // Get the layout of the symtab section.
392 symtab_builder_.section_.sh_offset = NextOffset(symtab_builder_.section_,
393 dynamic_builder_.section_);
394 symtab_builder_.section_.sh_addr = 0;
395 // Add to leave space for the null symbol.
Brian Carlstrom8758c642014-06-11 14:22:02 -0700396 symtab_builder_.section_.sh_size = symtab_builder_.GetSize() * sizeof(Elf32_Sym);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700397 symtab_builder_.section_.sh_link = symtab_builder_.GetLink();
398
399 // Get the layout of the dynstr section.
400 symtab_builder_.strtab_.section_.sh_offset = NextOffset(symtab_builder_.strtab_.section_,
401 symtab_builder_.section_);
402 symtab_builder_.strtab_.section_.sh_addr = 0;
403 symtab_builder_.strtab_.section_.sh_size = strtab.size();
404 symtab_builder_.strtab_.section_.sh_link = symtab_builder_.strtab_.GetLink();
405
406 prev = symtab_builder_.strtab_.section_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700407 if (debug_logging_) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700408 LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset
409 << " symtab size=" << symtab_builder_.section_.sh_size;
410 LOG(INFO) << "strtab off=" << symtab_builder_.strtab_.section_.sh_offset
411 << " strtab size=" << symtab_builder_.strtab_.section_.sh_size;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700412 }
413 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700414
Brian Carlstromb12f3472014-06-11 14:54:46 -0700415 // Get the layout of the extra sections. (This will deal with the debug
416 // sections if they are there)
417 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
418 it->section_.sh_offset = NextOffset(it->section_, prev);
419 it->section_.sh_addr = 0;
420 it->section_.sh_size = it->GetBuffer()->size();
421 it->section_.sh_link = it->GetLink();
422 pieces.push_back(ElfFilePiece(it->name_, it->section_.sh_offset,
423 it->GetBuffer()->data(), it->GetBuffer()->size()));
424 prev = it->section_;
425 if (debug_logging_) {
426 LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset
427 << " " << it->name_ << " size=" << it->section_.sh_size;
428 }
429 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700430
Brian Carlstromb12f3472014-06-11 14:54:46 -0700431 // Get the layout of the shstrtab section
432 shstrtab_builder_.section_.sh_offset = NextOffset(shstrtab_builder_.section_, prev);
433 shstrtab_builder_.section_.sh_addr = 0;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700434 shstrtab_builder_.section_.sh_size = shstrtab_.size();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700435 shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink();
436 if (debug_logging_) {
437 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset
438 << " shstrtab size=" << shstrtab_builder_.section_.sh_size;
Mark Mendellae9fd932014-02-10 16:14:35 -0800439 }
440
Brian Carlstromb12f3472014-06-11 14:54:46 -0700441 // The section list comes after come after.
442 Elf32_Word sections_offset = RoundUp(
443 shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size,
444 sizeof(Elf32_Word));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700445
Brian Carlstromb12f3472014-06-11 14:54:46 -0700446 // Setup the actual symbol arrays.
447 std::vector<Elf32_Sym> dynsym = dynsym_builder_.GenerateSymtab();
Brian Carlstrom8758c642014-06-11 14:22:02 -0700448 CHECK_EQ(dynsym.size() * sizeof(Elf32_Sym), dynsym_builder_.section_.sh_size);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700449 std::vector<Elf32_Sym> symtab;
450 if (IncludingDebugSymbols()) {
451 symtab = symtab_builder_.GenerateSymtab();
Brian Carlstrom8758c642014-06-11 14:22:02 -0700452 CHECK_EQ(symtab.size() * sizeof(Elf32_Sym), symtab_builder_.section_.sh_size);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700453 }
454
455 // Setup the dynamic section.
456 // This will add the 2 values we cannot know until now time, namely the size
457 // and the soname_offset.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700458 std::vector<Elf32_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
459 dynstr_soname_offset_);
Brian Carlstrom8758c642014-06-11 14:22:02 -0700460 CHECK_EQ(dynamic.size() * sizeof(Elf32_Dyn), dynamic_builder_.section_.sh_size);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700461
462 // Finish setup of the program headers now that we know the layout of the
463 // whole file.
464 Elf32_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700465 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
466 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
467 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700468
469 Elf32_Word load_rx_size = text_builder_.section_.sh_size;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700470 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset;
471 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.section_.sh_offset;
472 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.section_.sh_offset;
473 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
474 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
475 program_headers_[PH_LOAD_R_X].p_align = text_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700476
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700477 program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset;
478 program_headers_[PH_LOAD_RW_].p_vaddr = dynamic_builder_.section_.sh_offset;
479 program_headers_[PH_LOAD_RW_].p_paddr = dynamic_builder_.section_.sh_offset;
480 program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size;
481 program_headers_[PH_LOAD_RW_].p_memsz = dynamic_builder_.section_.sh_size;
482 program_headers_[PH_LOAD_RW_].p_align = dynamic_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700483
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700484 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset;
485 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.section_.sh_offset;
486 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.section_.sh_offset;
487 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size;
488 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.section_.sh_size;
489 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700490
491 // Finish setup of the Ehdr values.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700492 elf_header_.e_phoff = PHDR_OFFSET;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700493 elf_header_.e_shoff = sections_offset;
494 elf_header_.e_phnum = PH_NUM;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700495 elf_header_.e_shnum = section_ptrs_.size();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700496 elf_header_.e_shstrndx = shstrtab_builder_.section_index_;
497
498 // Add the rest of the pieces to the list.
499 pieces.push_back(ElfFilePiece("Elf Header", 0, &elf_header_, sizeof(elf_header_)));
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700500 pieces.push_back(ElfFilePiece("Program headers", PHDR_OFFSET,
501 &program_headers_, sizeof(program_headers_)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700502 pieces.push_back(ElfFilePiece(".dynamic", dynamic_builder_.section_.sh_offset,
503 dynamic.data(), dynamic_builder_.section_.sh_size));
504 pieces.push_back(ElfFilePiece(".dynsym", dynsym_builder_.section_.sh_offset,
Brian Carlstrom8758c642014-06-11 14:22:02 -0700505 dynsym.data(), dynsym.size() * sizeof(Elf32_Sym)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700506 pieces.push_back(ElfFilePiece(".dynstr", dynsym_builder_.strtab_.section_.sh_offset,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700507 dynstr_.c_str(), dynstr_.size()));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700508 pieces.push_back(ElfFilePiece(".hash", hash_builder_.section_.sh_offset,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700509 hash_.data(), hash_.size() * sizeof(Elf32_Word)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700510 pieces.push_back(ElfFilePiece(".rodata", rodata_builder_.section_.sh_offset,
Alex Light3470ab42014-06-18 10:35:45 -0700511 nullptr, rodata_builder_.section_.sh_size));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700512 pieces.push_back(ElfFilePiece(".text", text_builder_.section_.sh_offset,
Alex Light3470ab42014-06-18 10:35:45 -0700513 nullptr, text_builder_.section_.sh_size));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700514 if (IncludingDebugSymbols()) {
515 pieces.push_back(ElfFilePiece(".symtab", symtab_builder_.section_.sh_offset,
516 symtab.data(), symtab.size() * sizeof(Elf32_Sym)));
517 pieces.push_back(ElfFilePiece(".strtab", symtab_builder_.strtab_.section_.sh_offset,
518 strtab.c_str(), strtab.size()));
519 }
520 pieces.push_back(ElfFilePiece(".shstrtab", shstrtab_builder_.section_.sh_offset,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700521 &shstrtab_[0], shstrtab_.size()));
522 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700523 // Just add all the sections in induvidually since they are all over the
524 // place on the heap/stack.
525 Elf32_Word cur_off = sections_offset + i * sizeof(Elf32_Shdr);
526 pieces.push_back(ElfFilePiece("section table piece", cur_off,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700527 section_ptrs_[i], sizeof(Elf32_Shdr)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700528 }
529
530 if (!WriteOutFile(pieces)) {
531 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700532 return false;
533 }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700534 // write out the actual oat file data.
535 Elf32_Word oat_data_offset = rodata_builder_.section_.sh_offset;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700536 if (static_cast<off_t>(oat_data_offset) != lseek(elf_file_->Fd(), oat_data_offset, SEEK_SET)) {
537 PLOG(ERROR) << "Failed to seek to .rodata offset " << oat_data_offset
538 << " for " << elf_file_->GetPath();
539 return false;
540 }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700541 std::unique_ptr<BufferedOutputStream> output_stream(
542 new BufferedOutputStream(new FileOutputStream(elf_file_)));
543 if (!oat_writer_->Write(output_stream.get())) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700544 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file_->GetPath();
545 return false;
546 }
547
Brian Carlstrom35f72252014-06-11 21:24:53 +0000548 return true;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700549}
550
551bool ElfWriterQuick::ElfBuilder::WriteOutFile(const std::vector<ElfFilePiece>& pieces) {
552 // TODO It would be nice if this checked for overlap.
553 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
554 if (it->data_) {
555 if (static_cast<off_t>(it->offset_) != lseek(elf_file_->Fd(), it->offset_, SEEK_SET)) {
556 PLOG(ERROR) << "Failed to seek to " << it->dbg_name_ << " offset location "
557 << it->offset_ << " for " << elf_file_->GetPath();
558 return false;
559 }
560 if (!elf_file_->WriteFully(it->data_, it->size_)) {
561 PLOG(ERROR) << "Failed to write " << it->dbg_name_ << " for " << elf_file_->GetPath();
562 return false;
563 }
564 }
565 }
566 return true;
567}
568
569void ElfWriterQuick::ElfBuilder::SetupDynamic() {
570 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
571 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, &dynsym_builder_.strtab_);
572 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
573 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf32_Sym));
574}
575
576void ElfWriterQuick::ElfBuilder::SetupRequiredSymbols() {
577 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
578 rodata_builder_.size_, STB_GLOBAL, STT_OBJECT);
579 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
580 text_builder_.size_, STB_GLOBAL, STT_OBJECT);
581 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.size_ - 4,
582 true, 4, STB_GLOBAL, STT_OBJECT);
583}
584
Brian Carlstrom8758c642014-06-11 14:22:02 -0700585void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700586 if (tag == DT_NULL) {
587 return;
588 }
Alex Light3470ab42014-06-18 10:35:45 -0700589 dynamics_.push_back({nullptr, tag, d_un});
Brian Carlstromb12f3472014-06-11 14:54:46 -0700590}
591
Brian Carlstrom8758c642014-06-11 14:22:02 -0700592void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700593 ElfSectionBuilder* section) {
594 if (tag == DT_NULL) {
595 return;
596 }
597 dynamics_.push_back({section, tag, d_un});
598}
599
Brian Carlstrom8758c642014-06-11 14:22:02 -0700600std::vector<Elf32_Dyn> ElfWriterQuick::ElfDynamicBuilder::GetDynamics(Elf32_Word strsz,
601 Elf32_Word soname) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700602 std::vector<Elf32_Dyn> ret;
603 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
604 if (it->section_) {
605 // We are adding an address relative to a section.
606 ret.push_back(
Brian Carlstrom8758c642014-06-11 14:22:02 -0700607 {it->tag_, {it->off_ + it->section_->section_.sh_addr}});
Brian Carlstromb12f3472014-06-11 14:54:46 -0700608 } else {
609 ret.push_back({it->tag_, {it->off_}});
610 }
611 }
612 ret.push_back({DT_STRSZ, {strsz}});
613 ret.push_back({DT_SONAME, {soname}});
614 ret.push_back({DT_NULL, {0}});
615 return ret;
616}
617
618std::vector<Elf32_Sym> ElfWriterQuick::ElfSymtabBuilder::GenerateSymtab() {
619 std::vector<Elf32_Sym> ret;
620 Elf32_Sym undef_sym;
621 memset(&undef_sym, 0, sizeof(undef_sym));
622 undef_sym.st_shndx = SHN_UNDEF;
623 ret.push_back(undef_sym);
624
625 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
626 Elf32_Sym sym;
627 memset(&sym, 0, sizeof(sym));
628 sym.st_name = it->name_idx_;
629 if (it->is_relative_) {
630 sym.st_value = it->addr_ + it->section_->section_.sh_offset;
631 } else {
632 sym.st_value = it->addr_;
633 }
634 sym.st_size = it->size_;
635 sym.st_other = it->other_;
636 sym.st_shndx = it->section_->section_index_;
637 sym.st_info = it->info_;
638
639 ret.push_back(sym);
640 }
641 return ret;
642}
643
644std::string ElfWriterQuick::ElfSymtabBuilder::GenerateStrtab() {
645 std::string tab;
646 tab += '\0';
647 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
648 it->name_idx_ = tab.size();
649 tab += it->name_;
650 tab += '\0';
651 }
652 strtab_.section_.sh_size = tab.size();
653 return tab;
654}
655
656void ElfWriterQuick::ElfBuilder::AssignSectionStr(
657 ElfSectionBuilder* builder, std::string* strtab) {
658 builder->section_.sh_name = strtab->size();
659 *strtab += builder->name_;
660 *strtab += '\0';
661 if (debug_logging_) {
662 LOG(INFO) << "adding section name \"" << builder->name_ << "\" "
663 << "to shstrtab at offset " << builder->section_.sh_name;
664 }
665}
666
667// from bionic
668static unsigned elfhash(const char *_name) {
669 const unsigned char *name = (const unsigned char *) _name;
670 unsigned h = 0, g;
671
672 while (*name) {
673 h = (h << 4) + *name++;
674 g = h & 0xf0000000;
675 h ^= g;
676 h ^= g >> 24;
677 }
678 return h;
679}
680
681
682std::vector<Elf32_Word> ElfWriterQuick::ElfSymtabBuilder::GenerateHashContents() {
683 // Here is how The ELF hash table works.
684 // There are 3 arrays to worry about.
685 // * The symbol table where the symbol information is.
686 // * The bucket array which is an array of indexes into the symtab and chain.
687 // * The chain array which is also an array of indexes into the symtab and chain.
688 //
689 // Lets say the state is something like this.
690 // +--------+ +--------+ +-----------+
691 // | symtab | | bucket | | chain |
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700692 // | null | | 1 | | STN_UNDEF |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700693 // | <sym1> | | 4 | | 2 |
694 // | <sym2> | | | | 5 |
695 // | <sym3> | | | | STN_UNDEF |
696 // | <sym4> | | | | 3 |
697 // | <sym5> | | | | STN_UNDEF |
698 // +--------+ +--------+ +-----------+
699 //
700 // The lookup process (in python psudocode) is
701 //
702 // def GetSym(name):
703 // # NB STN_UNDEF == 0
704 // indx = bucket[elfhash(name) % num_buckets]
705 // while indx != STN_UNDEF:
706 // if GetSymbolName(symtab[indx]) == name:
707 // return symtab[indx]
708 // indx = chain[indx]
709 // return SYMBOL_NOT_FOUND
710 //
711 // Between bucket and chain arrays every symtab index must be present exactly
712 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
713
714 // Select number of buckets.
715 // This is essentially arbitrary.
716 Elf32_Word nbuckets;
Brian Carlstrom8758c642014-06-11 14:22:02 -0700717 Elf32_Word chain_size = GetSize();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700718 if (symbols_.size() < 8) {
719 nbuckets = 2;
720 } else if (symbols_.size() < 32) {
721 nbuckets = 4;
722 } else if (symbols_.size() < 256) {
723 nbuckets = 16;
724 } else {
725 // Have about 32 ids per bucket.
726 nbuckets = RoundUp(symbols_.size()/32, 2);
727 }
728 std::vector<Elf32_Word> hash;
729 hash.push_back(nbuckets);
730 hash.push_back(chain_size);
731 uint32_t bucket_offset = hash.size();
732 uint32_t chain_offset = bucket_offset + nbuckets;
733 hash.resize(hash.size() + nbuckets + chain_size, 0);
734
735 Elf32_Word* buckets = hash.data() + bucket_offset;
736 Elf32_Word* chain = hash.data() + chain_offset;
737
738 // Set up the actual hash table.
739 for (Elf32_Word i = 0; i < symbols_.size(); i++) {
740 // Add 1 since we need to have the null symbol that is not in the symbols
741 // list.
742 Elf32_Word index = i + 1;
743 Elf32_Word hash_val = static_cast<Elf32_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
744 if (buckets[hash_val] == 0) {
745 buckets[hash_val] = index;
746 } else {
747 hash_val = buckets[hash_val];
748 CHECK_LT(hash_val, chain_size);
749 while (chain[hash_val] != 0) {
750 hash_val = chain[hash_val];
751 CHECK_LT(hash_val, chain_size);
752 }
753 chain[hash_val] = index;
754 // Check for loops. Works because if this is non-empty then there must be
755 // another cell which already contains the same symbol index as this one,
756 // which means some symbol has more then one name, which isn't allowed.
757 CHECK_EQ(chain[index], static_cast<Elf32_Word>(0));
758 }
759 }
760
761 return hash;
762}
763
764void ElfWriterQuick::ElfBuilder::SetupEhdr() {
765 memset(&elf_header_, 0, sizeof(elf_header_));
766 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
767 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
768 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
769 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
770 elf_header_.e_ident[EI_CLASS] = ELFCLASS32;
771 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
772 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
773 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
774 elf_header_.e_ident[EI_ABIVERSION] = 0;
775 elf_header_.e_type = ET_DYN;
776 elf_header_.e_version = 1;
777 elf_header_.e_entry = 0;
778 elf_header_.e_ehsize = sizeof(Elf32_Ehdr);
779 elf_header_.e_phentsize = sizeof(Elf32_Phdr);
780 elf_header_.e_shentsize = sizeof(Elf32_Shdr);
781 elf_header_.e_phoff = sizeof(Elf32_Ehdr);
782}
783
784void ElfWriterQuick::ElfBuilder::SetISA(InstructionSet isa) {
785 switch (isa) {
786 case kArm:
787 // Fall through.
788 case kThumb2: {
789 elf_header_.e_machine = EM_ARM;
790 elf_header_.e_flags = EF_ARM_EABI_VER5;
791 break;
792 }
793 case kArm64: {
794 elf_header_.e_machine = EM_AARCH64;
795 elf_header_.e_flags = 0;
796 break;
797 }
798 case kX86: {
799 elf_header_.e_machine = EM_386;
800 elf_header_.e_flags = 0;
801 break;
802 }
803 case kX86_64: {
804 elf_header_.e_machine = EM_X86_64;
805 elf_header_.e_flags = 0;
806 break;
807 }
808 case kMips: {
809 elf_header_.e_machine = EM_MIPS;
810 elf_header_.e_flags = (EF_MIPS_NOREORDER |
811 EF_MIPS_PIC |
812 EF_MIPS_CPIC |
813 EF_MIPS_ABI_O32 |
814 EF_MIPS_ARCH_32R2);
815 break;
816 }
817 default: {
818 fatal_error_ = true;
819 LOG(FATAL) << "Unknown instruction set: " << isa;
820 break;
821 }
822 }
823}
824
825void ElfWriterQuick::ElfSymtabBuilder::AddSymbol(
826 const std::string& name, const ElfSectionBuilder* section, Elf32_Addr addr,
827 bool is_relative, Elf32_Word size, uint8_t binding, uint8_t type, uint8_t other) {
828 CHECK(section);
829 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
830 MakeStInfo(binding, type), other, 0};
831 symbols_.push_back(state);
832}
833
834bool ElfWriterQuick::Create(File* elf_file,
835 OatWriter* oat_writer,
836 const std::vector<const DexFile*>& dex_files,
837 const std::string& android_root,
838 bool is_host,
839 const CompilerDriver& driver) {
840 ElfWriterQuick elf_writer(driver, elf_file);
841 return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
842}
843
Alex Light53cb16b2014-06-12 11:26:29 -0700844// Add patch information to this section. Each patch is a Elf32_Word that
845// identifies an offset from the start of the text section
846void ElfWriterQuick::ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug) {
847 size_t size =
848 compiler_driver_->GetCodeToPatch().size() +
849 compiler_driver_->GetMethodsToPatch().size() +
850 compiler_driver_->GetClassesToPatch().size();
851 if (size == 0) {
852 if (debug) {
853 LOG(INFO) << "No patches to record";
854 }
855 return;
856 }
857 buffer->resize(size * sizeof(uintptr_t));
858 if (debug) {
859 LOG(INFO) << "Patches reserved for " << size;
860 }
861}
862
Andreas Gampe79273802014-08-05 20:21:05 -0700863std::vector<uint8_t>* ConstructCIEFrameX86(bool is_x86_64) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700864 std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>;
Andreas Gampe79273802014-08-05 20:21:05 -0700865
866 // Length (will be filled in later in this routine).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700867 if (is_x86_64) {
868 PushWord(cfi_info, 0xffffffff); // Indicates 64bit
869 PushWord(cfi_info, 0);
870 PushWord(cfi_info, 0);
871 } else {
872 PushWord(cfi_info, 0);
873 }
Andreas Gampe79273802014-08-05 20:21:05 -0700874
875 // CIE id: always 0.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700876 if (is_x86_64) {
877 PushWord(cfi_info, 0);
878 PushWord(cfi_info, 0);
879 } else {
880 PushWord(cfi_info, 0);
881 }
Andreas Gampe79273802014-08-05 20:21:05 -0700882
883 // Version: always 1.
884 cfi_info->push_back(0x01);
885
886 // Augmentation: 'zR\0'
887 cfi_info->push_back(0x7a);
888 cfi_info->push_back(0x52);
889 cfi_info->push_back(0x0);
890
891 // Code alignment: 1.
892 EncodeUnsignedLeb128(1, cfi_info);
893
894 // Data alignment.
895 if (is_x86_64) {
896 EncodeSignedLeb128(-8, cfi_info);
897 } else {
898 EncodeSignedLeb128(-4, cfi_info);
899 }
900
901 // Return address register.
902 if (is_x86_64) {
903 // R16(RIP)
904 cfi_info->push_back(0x10);
905 } else {
906 // R8(EIP)
907 cfi_info->push_back(0x08);
908 }
909
910 // Augmentation length: 1.
911 cfi_info->push_back(1);
912
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700913 // Augmentation data.
914 if (is_x86_64) {
915 // 0x04 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
916 cfi_info->push_back(0x04);
917 } else {
918 // 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
919 cfi_info->push_back(0x03);
920 }
Andreas Gampe79273802014-08-05 20:21:05 -0700921
922 // Initial instructions.
923 if (is_x86_64) {
924 // DW_CFA_def_cfa R7(RSP) 8.
925 cfi_info->push_back(0x0c);
926 cfi_info->push_back(0x07);
927 cfi_info->push_back(0x08);
928
929 // DW_CFA_offset R16(RIP) 1 (* -8).
930 cfi_info->push_back(0x90);
931 cfi_info->push_back(0x01);
932 } else {
933 // DW_CFA_def_cfa R4(ESP) 4.
934 cfi_info->push_back(0x0c);
935 cfi_info->push_back(0x04);
936 cfi_info->push_back(0x04);
937
938 // DW_CFA_offset R8(EIP) 1 (* -4).
939 cfi_info->push_back(0x88);
940 cfi_info->push_back(0x01);
941 }
942
943 // Padding to a multiple of 4
944 while ((cfi_info->size() & 3) != 0) {
945 // DW_CFA_nop is encoded as 0.
946 cfi_info->push_back(0);
947 }
948
949 // Set the length of the CIE inside the generated bytes.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700950 if (is_x86_64) {
951 uint32_t length = cfi_info->size() - 12;
952 UpdateWord(cfi_info, 4, length);
953 } else {
954 uint32_t length = cfi_info->size() - 4;
955 UpdateWord(cfi_info, 0, length);
956 }
Andreas Gampe79273802014-08-05 20:21:05 -0700957 return cfi_info;
958}
959
960std::vector<uint8_t>* ConstructCIEFrame(InstructionSet isa) {
961 switch (isa) {
962 case kX86:
963 return ConstructCIEFrameX86(false);
964 case kX86_64:
965 return ConstructCIEFrameX86(true);
966
967 default:
968 // Not implemented.
969 return nullptr;
970 }
971}
972
Brian Carlstromb12f3472014-06-11 14:54:46 -0700973bool ElfWriterQuick::Write(OatWriter* oat_writer,
974 const std::vector<const DexFile*>& dex_files_unused,
975 const std::string& android_root_unused,
976 bool is_host_unused) {
Andreas Gampe79273802014-08-05 20:21:05 -0700977 constexpr bool debug = false;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700978 const OatHeader& oat_header = oat_writer->GetOatHeader();
979 Elf32_Word oat_data_size = oat_header.GetExecutableOffset();
980 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
981
982 ElfBuilder builder(oat_writer, elf_file_, compiler_driver_->GetInstructionSet(), 0,
Andreas Gampe79273802014-08-05 20:21:05 -0700983 oat_data_size, oat_data_size, oat_exec_size,
984 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
985 debug);
Alex Light78382fa2014-06-06 15:45:32 -0700986
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700987 if (!builder.Init()) {
988 return false;
989 }
990
Andreas Gampe79273802014-08-05 20:21:05 -0700991 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700992 WriteDebugSymbols(&builder, oat_writer);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700993 }
994
Alex Light53cb16b2014-06-12 11:26:29 -0700995 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
996 ElfRawSectionBuilder oat_patches(".oat_patches", SHT_OAT_PATCH, 0, NULL, 0,
Alex Light4b0d2d92014-08-06 13:37:23 -0700997 sizeof(uintptr_t), sizeof(uintptr_t));
Alex Light53cb16b2014-06-12 11:26:29 -0700998 ReservePatchSpace(oat_patches.GetBuffer(), debug);
999 builder.RegisterRawSection(oat_patches);
1000 }
1001
Brian Carlstromb12f3472014-06-11 14:54:46 -07001002 return builder.Write();
1003}
Mark Mendellae9fd932014-02-10 16:14:35 -08001004
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001005void ElfWriterQuick::WriteDebugSymbols(ElfBuilder* builder, OatWriter* oat_writer) {
Andreas Gampe79273802014-08-05 20:21:05 -07001006 std::unique_ptr<std::vector<uint8_t>> cfi_info(
1007 ConstructCIEFrame(compiler_driver_->GetInstructionSet()));
1008
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001009 Elf32_Addr text_section_address = builder->text_builder_.section_.sh_addr;
1010
Andreas Gampe79273802014-08-05 20:21:05 -07001011 // Iterate over the compiled methods.
Alex Light78382fa2014-06-06 15:45:32 -07001012 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001013 ElfSymtabBuilder* symtab = &builder->symtab_builder_;
Alex Light78382fa2014-06-06 15:45:32 -07001014 for (auto it = method_info.begin(); it != method_info.end(); ++it) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001015 symtab->AddSymbol(it->method_name_, &builder->text_builder_, it->low_pc_, true,
Alex Light78382fa2014-06-06 15:45:32 -07001016 it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
Andreas Gampe79273802014-08-05 20:21:05 -07001017
1018 // Include CFI for compiled method, if possible.
1019 if (cfi_info.get() != nullptr) {
1020 DCHECK(it->compiled_method_ != nullptr);
1021
1022 // Copy in the FDE, if present
1023 const std::vector<uint8_t>* fde = it->compiled_method_->GetCFIInfo();
1024 if (fde != nullptr) {
1025 // Copy the information into cfi_info and then fix the address in the new copy.
1026 int cur_offset = cfi_info->size();
1027 cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
1028
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001029 bool is_64bit = *(reinterpret_cast<const uint32_t*>(fde->data())) == 0xffffffff;
Andreas Gampe79273802014-08-05 20:21:05 -07001030
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001031 // Set the 'CIE_pointer' field.
1032 uint64_t CIE_pointer = cur_offset + (is_64bit ? 12 : 4);
1033 uint64_t offset_to_update = CIE_pointer;
1034 if (is_64bit) {
1035 (*cfi_info)[offset_to_update+0] = CIE_pointer;
1036 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1037 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1038 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1039 (*cfi_info)[offset_to_update+4] = CIE_pointer >> 32;
1040 (*cfi_info)[offset_to_update+5] = CIE_pointer >> 40;
1041 (*cfi_info)[offset_to_update+6] = CIE_pointer >> 48;
1042 (*cfi_info)[offset_to_update+7] = CIE_pointer >> 56;
1043 } else {
1044 (*cfi_info)[offset_to_update+0] = CIE_pointer;
1045 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1046 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1047 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1048 }
1049
1050 // Set the 'initial_location' field.
1051 offset_to_update += is_64bit ? 8 : 4;
1052 if (is_64bit) {
1053 const uint64_t quick_code_start = it->low_pc_ + text_section_address;
1054 (*cfi_info)[offset_to_update+0] = quick_code_start;
1055 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1056 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1057 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1058 (*cfi_info)[offset_to_update+4] = quick_code_start >> 32;
1059 (*cfi_info)[offset_to_update+5] = quick_code_start >> 40;
1060 (*cfi_info)[offset_to_update+6] = quick_code_start >> 48;
1061 (*cfi_info)[offset_to_update+7] = quick_code_start >> 56;
1062 } else {
1063 const uint32_t quick_code_start = it->low_pc_ + text_section_address;
1064 (*cfi_info)[offset_to_update+0] = quick_code_start;
1065 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1066 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1067 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1068 }
Andreas Gampe79273802014-08-05 20:21:05 -07001069 }
1070 }
Alex Light78382fa2014-06-06 15:45:32 -07001071 }
Alex Light78382fa2014-06-06 15:45:32 -07001072
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001073 bool hasCFI = (cfi_info.get() != nullptr);
1074 bool hasLineInfo = false;
1075 for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
1076 if (dbg_info.dbgstream_ != nullptr &&
1077 !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
1078 hasLineInfo = true;
1079 break;
1080 }
1081 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001082
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001083 if (hasLineInfo || hasCFI) {
1084 ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1085 ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1086 ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1087 ElfRawSectionBuilder debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1088
1089 FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
1090 debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
1091 hasLineInfo ? debug_line.GetBuffer() : nullptr,
1092 text_section_address);
1093
1094 builder->RegisterRawSection(debug_info);
1095 builder->RegisterRawSection(debug_abbrev);
1096
1097 if (hasCFI) {
1098 ElfRawSectionBuilder eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
1099 eh_frame.SetBuffer(std::move(*cfi_info.get()));
1100 builder->RegisterRawSection(eh_frame);
1101 }
1102
1103 if (hasLineInfo) {
1104 builder->RegisterRawSection(debug_line);
1105 }
1106
1107 builder->RegisterRawSection(debug_str);
1108 }
1109}
1110
1111class LineTableGenerator FINAL : public Leb128Encoder {
1112 public:
1113 LineTableGenerator(int line_base, int line_range, int opcode_base,
1114 std::vector<uint8_t>* data, uintptr_t current_address,
1115 size_t current_line)
1116 : Leb128Encoder(data), line_base_(line_base), line_range_(line_range),
1117 opcode_base_(opcode_base), current_address_(current_address),
1118 current_line_(current_line) {}
1119
1120 void PutDelta(unsigned delta_addr, int delta_line) {
1121 current_line_ += delta_line;
1122 current_address_ += delta_addr;
1123
1124 if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) {
1125 unsigned special_opcode = (delta_line - line_base_) +
1126 (line_range_ * delta_addr) + opcode_base_;
1127 if (special_opcode <= 255) {
1128 PushByte(data_, special_opcode);
1129 return;
1130 }
1131 }
1132
1133 // generate standart opcode for address advance
1134 if (delta_addr != 0) {
1135 PushByte(data_, DW_LNS_advance_pc);
1136 PushBackUnsigned(delta_addr);
1137 }
1138
1139 // generate standart opcode for line delta
1140 if (delta_line != 0) {
1141 PushByte(data_, DW_LNS_advance_line);
1142 PushBackSigned(delta_line);
1143 }
1144
1145 // generate standart opcode for new LTN entry
1146 PushByte(data_, DW_LNS_copy);
1147 }
1148
1149 void SetAddr(uintptr_t addr) {
1150 if (current_address_ == addr) {
1151 return;
1152 }
1153
1154 current_address_ = addr;
1155
1156 PushByte(data_, 0); // extended opcode:
1157 PushByte(data_, 1 + 4); // length: opcode_size + address_size
1158 PushByte(data_, DW_LNE_set_address);
1159 PushWord(data_, addr);
1160 }
1161
1162 void SetLine(unsigned line) {
1163 int delta_line = line - current_line_;
1164 if (delta_line) {
1165 current_line_ = line;
1166 PushByte(data_, DW_LNS_advance_line);
1167 PushBackSigned(delta_line);
1168 }
1169 }
1170
1171 void SetFile(unsigned file_index) {
1172 PushByte(data_, DW_LNS_set_file);
1173 PushBackUnsigned(file_index);
1174 }
1175
1176 void EndSequence() {
1177 // End of Line Table Program
1178 // 0(=ext), 1(len), DW_LNE_end_sequence
1179 PushByte(data_, 0);
1180 PushByte(data_, 1);
1181 PushByte(data_, DW_LNE_end_sequence);
1182 }
1183
1184 private:
1185 const int line_base_;
1186 const int line_range_;
1187 const int opcode_base_;
1188 uintptr_t current_address_;
1189 size_t current_line_;
1190
1191 DISALLOW_COPY_AND_ASSIGN(LineTableGenerator);
1192};
1193
1194// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
1195static void GetLineInfoForJava(const uint8_t* dbgstream, const SrcMap& pc2dex,
1196 SrcMap* result, uint32_t start_pc = 0) {
1197 if (dbgstream == nullptr) {
1198 return;
1199 }
1200
1201 int adjopcode;
1202 uint32_t dex_offset = 0;
1203 uint32_t java_line = DecodeUnsignedLeb128(&dbgstream);
1204
1205 // skip parameters
1206 for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) {
1207 DecodeUnsignedLeb128(&dbgstream);
1208 }
1209
1210 for (bool is_end = false; is_end == false; ) {
1211 uint8_t opcode = *dbgstream;
1212 dbgstream++;
1213 switch (opcode) {
1214 case DexFile::DBG_END_SEQUENCE:
1215 is_end = true;
1216 break;
1217
1218 case DexFile::DBG_ADVANCE_PC:
1219 dex_offset += DecodeUnsignedLeb128(&dbgstream);
1220 break;
1221
1222 case DexFile::DBG_ADVANCE_LINE:
1223 java_line += DecodeSignedLeb128(&dbgstream);
1224 break;
1225
1226 case DexFile::DBG_START_LOCAL:
1227 case DexFile::DBG_START_LOCAL_EXTENDED:
1228 DecodeUnsignedLeb128(&dbgstream);
1229 DecodeUnsignedLeb128(&dbgstream);
1230 DecodeUnsignedLeb128(&dbgstream);
1231
1232 if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) {
1233 DecodeUnsignedLeb128(&dbgstream);
1234 }
1235 break;
1236
1237 case DexFile::DBG_END_LOCAL:
1238 case DexFile::DBG_RESTART_LOCAL:
1239 DecodeUnsignedLeb128(&dbgstream);
1240 break;
1241
1242 case DexFile::DBG_SET_PROLOGUE_END:
1243 case DexFile::DBG_SET_EPILOGUE_BEGIN:
1244 case DexFile::DBG_SET_FILE:
1245 break;
1246
1247 default:
1248 adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
1249 dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
1250 java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
1251
1252 for (SrcMap::const_iterator found = pc2dex.FindByTo(dex_offset);
1253 found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset);
1254 found++) {
1255 result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)});
1256 }
1257 break;
1258 }
Andreas Gampe79273802014-08-05 20:21:05 -07001259 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001260}
1261
Mark Mendellae9fd932014-02-10 16:14:35 -08001262void ElfWriterQuick::FillInCFIInformation(OatWriter* oat_writer,
1263 std::vector<uint8_t>* dbg_info,
1264 std::vector<uint8_t>* dbg_abbrev,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001265 std::vector<uint8_t>* dbg_str,
1266 std::vector<uint8_t>* dbg_line,
1267 uint32_t text_section_offset) {
1268 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
1269
1270 uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
1271
Mark Mendellae9fd932014-02-10 16:14:35 -08001272 // Create the debug_abbrev section with boilerplate information.
1273 // We only care about low_pc and high_pc right now for the compilation
1274 // unit and methods.
1275
1276 // Tag 1: Compilation unit: DW_TAG_compile_unit.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001277 PushByte(dbg_abbrev, 1);
1278 PushByte(dbg_abbrev, DW_TAG_compile_unit);
Mark Mendellae9fd932014-02-10 16:14:35 -08001279
1280 // There are children (the methods).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001281 PushByte(dbg_abbrev, DW_CHILDREN_yes);
1282
1283 // DW_AT_producer DW_FORM_data1.
1284 // REVIEW: we can get rid of dbg_str section if
1285 // DW_FORM_string (immediate string) was used everywhere instead of
1286 // DW_FORM_strp (ref to string from .debug_str section).
1287 // DW_FORM_strp makes sense only if we reuse the strings.
1288 PushByte(dbg_abbrev, DW_AT_producer);
1289 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -08001290
1291 // DW_LANG_Java DW_FORM_data1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001292 PushByte(dbg_abbrev, DW_AT_language);
1293 PushByte(dbg_abbrev, DW_FORM_data1);
Mark Mendellae9fd932014-02-10 16:14:35 -08001294
1295 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001296 PushByte(dbg_abbrev, DW_AT_low_pc);
1297 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001298
1299 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001300 PushByte(dbg_abbrev, DW_AT_high_pc);
1301 PushByte(dbg_abbrev, DW_FORM_addr);
1302
1303 if (dbg_line != nullptr) {
1304 // DW_AT_stmt_list DW_FORM_sec_offset.
1305 PushByte(dbg_abbrev, DW_AT_stmt_list);
1306 PushByte(dbg_abbrev, DW_FORM_sec_offset);
1307 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001308
1309 // End of DW_TAG_compile_unit.
1310 PushHalf(dbg_abbrev, 0);
1311
1312 // Tag 2: Compilation unit: DW_TAG_subprogram.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001313 PushByte(dbg_abbrev, 2);
1314 PushByte(dbg_abbrev, DW_TAG_subprogram);
Mark Mendellae9fd932014-02-10 16:14:35 -08001315
1316 // There are no children.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001317 PushByte(dbg_abbrev, DW_CHILDREN_no);
Mark Mendellae9fd932014-02-10 16:14:35 -08001318
1319 // Name of the method.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001320 PushByte(dbg_abbrev, DW_AT_name);
1321 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -08001322
1323 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001324 PushByte(dbg_abbrev, DW_AT_low_pc);
1325 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001326
1327 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001328 PushByte(dbg_abbrev, DW_AT_high_pc);
1329 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001330
1331 // End of DW_TAG_subprogram.
1332 PushHalf(dbg_abbrev, 0);
1333
1334 // Start the debug_info section with the header information
1335 // 'unit_length' will be filled in later.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001336 int cunit_length = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -08001337 PushWord(dbg_info, 0);
1338
1339 // 'version' - 3.
1340 PushHalf(dbg_info, 3);
1341
1342 // Offset into .debug_abbrev section (always 0).
1343 PushWord(dbg_info, 0);
1344
1345 // Address size: 4.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001346 PushByte(dbg_info, 4);
Mark Mendellae9fd932014-02-10 16:14:35 -08001347
1348 // Start the description for the compilation unit.
1349 // This uses tag 1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001350 PushByte(dbg_info, 1);
1351
1352 // The producer is Android dex2oat.
1353 PushWord(dbg_info, producer_str_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -08001354
1355 // The language is Java.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001356 PushByte(dbg_info, DW_LANG_Java);
Mark Mendellae9fd932014-02-10 16:14:35 -08001357
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001358 // low_pc and high_pc.
1359 uint32_t cunit_low_pc = 0 - 1;
1360 uint32_t cunit_high_pc = 0;
1361 int cunit_low_pc_pos = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -08001362 PushWord(dbg_info, 0);
1363 PushWord(dbg_info, 0);
1364
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001365 if (dbg_line == nullptr) {
1366 for (size_t i = 0; i < method_info.size(); ++i) {
1367 const OatWriter::DebugInfo &dbg = method_info[i];
Mark Mendellae9fd932014-02-10 16:14:35 -08001368
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001369 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1370 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1371
1372 // Start a new TAG: subroutine (2).
1373 PushByte(dbg_info, 2);
1374
1375 // Enter name, low_pc, high_pc.
1376 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1377 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1378 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -08001379 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001380 } else {
1381 // TODO: in gdb info functions <regexp> - reports Java functions, but
1382 // source file is <unknown> because .debug_line is formed as one
1383 // compilation unit. To fix this it is possible to generate
1384 // a separate compilation unit for every distinct Java source.
1385 // Each of the these compilation units can have several non-adjacent
1386 // method ranges.
1387
1388 // Line number table offset
1389 PushWord(dbg_info, dbg_line->size());
1390
1391 size_t lnt_length = dbg_line->size();
1392 PushWord(dbg_line, 0);
1393
1394 PushHalf(dbg_line, 4); // LNT Version DWARF v4 => 4
1395
1396 size_t lnt_hdr_length = dbg_line->size();
1397 PushWord(dbg_line, 0); // TODO: 64-bit uses 8-byte here
1398
1399 PushByte(dbg_line, 1); // minimum_instruction_length (ubyte)
1400 PushByte(dbg_line, 1); // maximum_operations_per_instruction (ubyte) = always 1
1401 PushByte(dbg_line, 1); // default_is_stmt (ubyte)
1402
1403 const int8_t LINE_BASE = -5;
1404 PushByte(dbg_line, LINE_BASE); // line_base (sbyte)
1405
1406 const uint8_t LINE_RANGE = 14;
1407 PushByte(dbg_line, LINE_RANGE); // line_range (ubyte)
1408
1409 const uint8_t OPCODE_BASE = 13;
1410 PushByte(dbg_line, OPCODE_BASE); // opcode_base (ubyte)
1411
1412 // Standard_opcode_lengths (array of ubyte).
1413 PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1);
1414 PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0);
1415 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1416 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1417
1418 PushByte(dbg_line, 0); // include_directories (sequence of path names) = EMPTY
1419
1420 // File_names (sequence of file entries).
1421 std::unordered_map<const char*, size_t> files;
1422 for (size_t i = 0; i < method_info.size(); ++i) {
1423 const OatWriter::DebugInfo &dbg = method_info[i];
1424 // TODO: add package directory to the file name
1425 const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_;
1426 auto found = files.find(file_name);
1427 if (found == files.end()) {
1428 size_t file_index = 1 + files.size();
1429 files[file_name] = file_index;
1430 PushStr(dbg_line, file_name);
1431 PushByte(dbg_line, 0); // include directory index = LEB128(0) - no directory
1432 PushByte(dbg_line, 0); // modification time = LEB128(0) - NA
1433 PushByte(dbg_line, 0); // file length = LEB128(0) - NA
1434 }
1435 }
1436 PushByte(dbg_line, 0); // End of file_names.
1437
1438 // Set lnt header length.
1439 UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4);
1440
1441 // Generate Line Number Program code, one long program for all methods.
1442 LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE,
1443 dbg_line, 0, 1);
1444
1445 SrcMap pc2java_map;
1446 for (size_t i = 0; i < method_info.size(); ++i) {
1447 const OatWriter::DebugInfo &dbg = method_info[i];
1448 const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_;
1449 size_t file_index = files[file_name];
1450 DCHECK_NE(file_index, 0U) << file_name;
1451
1452 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1453 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1454
1455 // Start a new TAG: subroutine (2).
1456 PushByte(dbg_info, 2);
1457
1458 // Enter name, low_pc, high_pc.
1459 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1460 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1461 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
1462
1463 pc2java_map.clear();
1464 GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(),
1465 &pc2java_map, dbg.low_pc_);
1466 pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_);
1467
1468 line_table_generator.SetFile(file_index);
1469 line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset);
1470 line_table_generator.SetLine(1);
1471 for (auto& src_map_elem : pc2java_map) {
1472 line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_);
1473 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001474 }
1475
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001476 // End Sequence should have the highest address set.
1477 line_table_generator.SetAddr(cunit_high_pc + text_section_offset);
1478 line_table_generator.EndSequence();
Mark Mendellae9fd932014-02-10 16:14:35 -08001479
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001480 // set lnt length
1481 UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4);
Mark Mendellae9fd932014-02-10 16:14:35 -08001482 }
1483
1484 // One byte terminator
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001485 PushByte(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -08001486
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001487 // Fill in cunit's low_pc and high_pc.
1488 UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset);
1489 UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset);
1490
1491 // We have now walked all the methods. Fill in lengths.
1492 UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001493}
1494
1495} // namespace art