blob: 4c69fc8fd0f0754e04cf3c337e7ce96bc6869258 [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
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000037template <typename Elf_Word, typename Elf_Shdr>
38static constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
Brian Carlstromb12f3472014-06-11 14:54:46 -070039 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
Brian Carlstrom7940e442013-07-12 13:46:57 -070040}
41
Brian Carlstromb12f3472014-06-11 14:54:46 -070042static uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
43 return ((binding) << 4) + ((type) & 0xf);
44}
45
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070046static void PushByte(std::vector<uint8_t>* buf, int data) {
47 buf->push_back(data & 0xff);
48}
49
50static uint32_t PushStr(std::vector<uint8_t>* buf, const char* str, const char* def = nullptr) {
51 if (str == nullptr) {
52 str = def;
53 }
54
55 uint32_t offset = buf->size();
56 for (size_t i = 0; str[i] != '\0'; ++i) {
57 buf->push_back(str[i]);
58 }
59 buf->push_back('\0');
60 return offset;
61}
62
63static uint32_t PushStr(std::vector<uint8_t>* buf, const std::string &str) {
64 uint32_t offset = buf->size();
65 buf->insert(buf->end(), str.begin(), str.end());
66 buf->push_back('\0');
67 return offset;
68}
69
Andreas Gampe79273802014-08-05 20:21:05 -070070static void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) {
71 (*buf)[offset+0] = data;
72 (*buf)[offset+1] = data >> 8;
73 (*buf)[offset+2] = data >> 16;
74 (*buf)[offset+3] = data >> 24;
75}
76
Andreas Gampe79273802014-08-05 20:21:05 -070077static void PushHalf(std::vector<uint8_t>* buf, int data) {
78 buf->push_back(data & 0xff);
79 buf->push_back((data >> 8) & 0xff);
80}
81
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000082template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
83 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
84 typename Elf_Phdr, typename Elf_Shdr>
85bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
86 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::Init() {
Brian Carlstromb12f3472014-06-11 14:54:46 -070087 // The basic layout of the elf file. Order may be different in final output.
Brian Carlstrom7940e442013-07-12 13:46:57 -070088 // +-------------------------+
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000089 // | Elf_Ehdr |
Brian Carlstrom7940e442013-07-12 13:46:57 -070090 // +-------------------------+
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000091 // | Elf_Phdr PHDR |
92 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
93 // | Elf_Phdr LOAD R X | .text
94 // | Elf_Phdr LOAD RW | .dynamic
95 // | Elf_Phdr DYNAMIC | .dynamic
Brian Carlstrom7940e442013-07-12 13:46:57 -070096 // +-------------------------+
97 // | .dynsym |
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000098 // | Elf_Sym STN_UNDEF |
99 // | Elf_Sym oatdata |
100 // | Elf_Sym oatexec |
101 // | Elf_Sym oatlastword |
Brian Carlstrom7940e442013-07-12 13:46:57 -0700102 // +-------------------------+
103 // | .dynstr |
104 // | \0 |
105 // | oatdata\0 |
106 // | oatexec\0 |
107 // | oatlastword\0 |
108 // | boot.oat\0 |
109 // +-------------------------+
110 // | .hash |
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000111 // | Elf_Word nbucket = b |
112 // | Elf_Word nchain = c |
113 // | Elf_Word bucket[0] |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700114 // | ... |
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000115 // | Elf_Word bucket[b - 1] |
116 // | Elf_Word chain[0] |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700117 // | ... |
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000118 // | Elf_Word chain[c - 1] |
Brian Carlstrom7940e442013-07-12 13:46:57 -0700119 // +-------------------------+
120 // | .rodata |
121 // | oatdata..oatexec-4 |
122 // +-------------------------+
123 // | .text |
124 // | oatexec..oatlastword |
125 // +-------------------------+
126 // | .dynamic |
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000127 // | Elf_Dyn DT_SONAME |
128 // | Elf_Dyn DT_HASH |
129 // | Elf_Dyn DT_SYMTAB |
130 // | Elf_Dyn DT_SYMENT |
131 // | Elf_Dyn DT_STRTAB |
132 // | Elf_Dyn DT_STRSZ |
133 // | Elf_Dyn DT_NULL |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700134 // +-------------------------+ (Optional)
135 // | .strtab | (Optional)
136 // | program symbol names | (Optional)
137 // +-------------------------+ (Optional)
138 // | .symtab | (Optional)
139 // | program symbols | (Optional)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700140 // +-------------------------+
141 // | .shstrtab |
142 // | \0 |
143 // | .dynamic\0 |
144 // | .dynsym\0 |
145 // | .dynstr\0 |
146 // | .hash\0 |
147 // | .rodata\0 |
148 // | .text\0 |
149 // | .shstrtab\0 |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700150 // | .symtab\0 | (Optional)
151 // | .strtab\0 | (Optional)
152 // | .debug_str\0 | (Optional)
153 // | .debug_info\0 | (Optional)
Tong Shen35e1e6a2014-07-30 09:31:22 -0700154 // | .eh_frame\0 | (Optional)
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700155 // | .debug_line\0 | (Optional)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700156 // | .debug_abbrev\0 | (Optional)
157 // +-------------------------+ (Optional)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700158 // | .debug_info | (Optional)
159 // +-------------------------+ (Optional)
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700160 // | .debug_abbrev | (Optional)
161 // +-------------------------+ (Optional)
Tong Shen35e1e6a2014-07-30 09:31:22 -0700162 // | .eh_frame | (Optional)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700163 // +-------------------------+ (Optional)
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700164 // | .debug_line | (Optional)
165 // +-------------------------+ (Optional)
166 // | .debug_str | (Optional)
167 // +-------------------------+ (Optional)
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000168 // | Elf_Shdr NULL |
169 // | Elf_Shdr .dynsym |
170 // | Elf_Shdr .dynstr |
171 // | Elf_Shdr .hash |
172 // | Elf_Shdr .text |
173 // | Elf_Shdr .rodata |
174 // | Elf_Shdr .dynamic |
175 // | Elf_Shdr .shstrtab |
176 // | Elf_Shdr .debug_info | (Optional)
177 // | Elf_Shdr .debug_abbrev | (Optional)
178 // | Elf_Shdr .eh_frame | (Optional)
179 // | Elf_Shdr .debug_line | (Optional)
180 // | Elf_Shdr .debug_str | (Optional)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700181 // +-------------------------+
182
Brian Carlstromb12f3472014-06-11 14:54:46 -0700183 if (fatal_error_) {
184 return false;
185 }
186 // Step 1. Figure out all the offsets.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700187
Brian Carlstromb12f3472014-06-11 14:54:46 -0700188 if (debug_logging_) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700189 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
190 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700191 }
192
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700193 memset(&program_headers_, 0, sizeof(program_headers_));
194 program_headers_[PH_PHDR].p_type = PT_PHDR;
195 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
196 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
197 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
198 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
199 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
200 program_headers_[PH_PHDR].p_flags = PF_R;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000201 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700202
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700203 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
204 program_headers_[PH_LOAD_R__].p_offset = 0;
205 program_headers_[PH_LOAD_R__].p_vaddr = 0;
206 program_headers_[PH_LOAD_R__].p_paddr = 0;
207 program_headers_[PH_LOAD_R__].p_flags = PF_R;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700208
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700209 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
210 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700211
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700212 program_headers_[PH_LOAD_RW_].p_type = PT_LOAD;
213 program_headers_[PH_LOAD_RW_].p_flags = PF_R | PF_W;
214
215 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
216 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700217
218 // Get the dynstr string.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700219 dynstr_ = dynsym_builder_.GenerateStrtab();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700220
221 // Add the SONAME to the dynstr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700222 dynstr_soname_offset_ = dynstr_.size();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700223 std::string file_name(elf_file_->GetPath());
224 size_t directory_separator_pos = file_name.rfind('/');
225 if (directory_separator_pos != std::string::npos) {
226 file_name = file_name.substr(directory_separator_pos + 1);
227 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700228 dynstr_ += file_name;
229 dynstr_ += '\0';
Brian Carlstromb12f3472014-06-11 14:54:46 -0700230 if (debug_logging_) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700231 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
232 << std::hex << " " << dynstr_.size();
Brian Carlstrom8758c642014-06-11 14:22:02 -0700233 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
234 << std::hex << " " << dynsym_builder_.GetSize();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700235 }
236
Brian Carlstromb12f3472014-06-11 14:54:46 -0700237 // Get the section header string table.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700238 shstrtab_ += '\0';
Brian Carlstromb12f3472014-06-11 14:54:46 -0700239
240 // Setup sym_undef
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700241 memset(&null_hdr_, 0, sizeof(null_hdr_));
242 null_hdr_.sh_type = SHT_NULL;
243 null_hdr_.sh_link = SHN_UNDEF;
244 section_ptrs_.push_back(&null_hdr_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700245
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700246 section_index_ = 1;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700247
248 // setup .dynsym
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700249 section_ptrs_.push_back(&dynsym_builder_.section_);
250 AssignSectionStr(&dynsym_builder_, &shstrtab_);
251 dynsym_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700252
253 // Setup .dynstr
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700254 section_ptrs_.push_back(&dynsym_builder_.strtab_.section_);
255 AssignSectionStr(&dynsym_builder_.strtab_, &shstrtab_);
256 dynsym_builder_.strtab_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700257
258 // Setup .hash
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700259 section_ptrs_.push_back(&hash_builder_.section_);
260 AssignSectionStr(&hash_builder_, &shstrtab_);
261 hash_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700262
263 // Setup .rodata
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700264 section_ptrs_.push_back(&rodata_builder_.section_);
265 AssignSectionStr(&rodata_builder_, &shstrtab_);
266 rodata_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700267
268 // Setup .text
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700269 section_ptrs_.push_back(&text_builder_.section_);
270 AssignSectionStr(&text_builder_, &shstrtab_);
271 text_builder_.section_index_ = section_index_++;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700272
273 // Setup .dynamic
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700274 section_ptrs_.push_back(&dynamic_builder_.section_);
275 AssignSectionStr(&dynamic_builder_, &shstrtab_);
276 dynamic_builder_.section_index_ = section_index_++;
Mark Mendellae9fd932014-02-10 16:14:35 -0800277
Brian Carlstromb12f3472014-06-11 14:54:46 -0700278 // Fill in the hash section.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700279 hash_ = dynsym_builder_.GenerateHashContents();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700280
281 if (debug_logging_) {
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000282 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
283 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
Mark Mendellae9fd932014-02-10 16:14:35 -0800284 }
285
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000286 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700287
288 // Get the layout in the sections.
289 //
290 // Get the layout of the dynsym section.
291 dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign);
292 dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000293 dynsym_builder_.section_.sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700294 dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink();
295
296 // Get the layout of the dynstr section.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000297 dynsym_builder_.strtab_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
298 (dynsym_builder_.strtab_.section_,
299 dynsym_builder_.section_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700300 dynsym_builder_.strtab_.section_.sh_addr = dynsym_builder_.strtab_.section_.sh_offset;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700301 dynsym_builder_.strtab_.section_.sh_size = dynstr_.size();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700302 dynsym_builder_.strtab_.section_.sh_link = dynsym_builder_.strtab_.GetLink();
303
304 // Get the layout of the hash section
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000305 hash_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
306 (hash_builder_.section_,
307 dynsym_builder_.strtab_.section_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700308 hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000309 hash_builder_.section_.sh_size = hash_.size() * sizeof(Elf_Word);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700310 hash_builder_.section_.sh_link = hash_builder_.GetLink();
311
312 // Get the layout of the rodata section.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000313 rodata_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
314 (rodata_builder_.section_,
315 hash_builder_.section_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700316 rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset;
317 rodata_builder_.section_.sh_size = rodata_builder_.size_;
318 rodata_builder_.section_.sh_link = rodata_builder_.GetLink();
319
320 // Get the layout of the text section.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000321 text_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
322 (text_builder_.section_, rodata_builder_.section_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700323 text_builder_.section_.sh_addr = text_builder_.section_.sh_offset;
324 text_builder_.section_.sh_size = text_builder_.size_;
325 text_builder_.section_.sh_link = text_builder_.GetLink();
326 CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize);
327
328 // Get the layout of the dynamic section.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000329 dynamic_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
330 (dynamic_builder_.section_,
331 text_builder_.section_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700332 dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000333 dynamic_builder_.section_.sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700334 dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink();
335
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700336 if (debug_logging_) {
337 LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset
338 << " dynsym size=" << dynsym_builder_.section_.sh_size;
339 LOG(INFO) << "dynstr off=" << dynsym_builder_.strtab_.section_.sh_offset
340 << " dynstr size=" << dynsym_builder_.strtab_.section_.sh_size;
341 LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset
342 << " hash size=" << hash_builder_.section_.sh_size;
343 LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset
344 << " rodata size=" << rodata_builder_.section_.sh_size;
345 LOG(INFO) << "text off=" << text_builder_.section_.sh_offset
346 << " text size=" << text_builder_.section_.sh_size;
347 LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset
348 << " dynamic size=" << dynamic_builder_.section_.sh_size;
349 }
350
351 return true;
352}
353
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000354template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
355 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
356 typename Elf_Phdr, typename Elf_Shdr>
357bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
358 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::Write() {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700359 std::vector<ElfFilePiece> pieces;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000360 Elf_Shdr prev = dynamic_builder_.section_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700361 std::string strtab;
362
363 if (IncludingDebugSymbols()) {
364 // Setup .symtab
365 section_ptrs_.push_back(&symtab_builder_.section_);
366 AssignSectionStr(&symtab_builder_, &shstrtab_);
367 symtab_builder_.section_index_ = section_index_++;
368
369 // Setup .strtab
370 section_ptrs_.push_back(&symtab_builder_.strtab_.section_);
371 AssignSectionStr(&symtab_builder_.strtab_, &shstrtab_);
372 symtab_builder_.strtab_.section_index_ = section_index_++;
373
374 strtab = symtab_builder_.GenerateStrtab();
375 if (debug_logging_) {
376 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
377 << std::hex << " " << strtab.size();
378 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
379 << std::hex << " " << symtab_builder_.GetSize();
380 }
381 }
382
383 // Setup all the other sections.
384 for (ElfRawSectionBuilder *builder = other_builders_.data(),
385 *end = builder + other_builders_.size();
386 builder != end; ++builder) {
387 section_ptrs_.push_back(&builder->section_);
388 AssignSectionStr(builder, &shstrtab_);
389 builder->section_index_ = section_index_++;
390 }
391
392 // Setup shstrtab
393 section_ptrs_.push_back(&shstrtab_builder_.section_);
394 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
395 shstrtab_builder_.section_index_ = section_index_++;
396
397 if (debug_logging_) {
398 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
399 << std::hex << " " << shstrtab_.size();
400 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
401 << std::hex << " " << section_ptrs_.size();
402 }
403
Brian Carlstromb12f3472014-06-11 14:54:46 -0700404 if (IncludingDebugSymbols()) {
405 // Get the layout of the symtab section.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000406 symtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
407 (symtab_builder_.section_,
408 dynamic_builder_.section_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700409 symtab_builder_.section_.sh_addr = 0;
410 // Add to leave space for the null symbol.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000411 symtab_builder_.section_.sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700412 symtab_builder_.section_.sh_link = symtab_builder_.GetLink();
413
414 // Get the layout of the dynstr section.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000415 symtab_builder_.strtab_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
416 (symtab_builder_.strtab_.section_,
417 symtab_builder_.section_);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700418 symtab_builder_.strtab_.section_.sh_addr = 0;
419 symtab_builder_.strtab_.section_.sh_size = strtab.size();
420 symtab_builder_.strtab_.section_.sh_link = symtab_builder_.strtab_.GetLink();
421
422 prev = symtab_builder_.strtab_.section_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700423 if (debug_logging_) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700424 LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset
425 << " symtab size=" << symtab_builder_.section_.sh_size;
426 LOG(INFO) << "strtab off=" << symtab_builder_.strtab_.section_.sh_offset
427 << " strtab size=" << symtab_builder_.strtab_.section_.sh_size;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700428 }
429 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700430
Brian Carlstromb12f3472014-06-11 14:54:46 -0700431 // Get the layout of the extra sections. (This will deal with the debug
432 // sections if they are there)
433 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000434 it->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>(it->section_, prev);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700435 it->section_.sh_addr = 0;
436 it->section_.sh_size = it->GetBuffer()->size();
437 it->section_.sh_link = it->GetLink();
438 pieces.push_back(ElfFilePiece(it->name_, it->section_.sh_offset,
439 it->GetBuffer()->data(), it->GetBuffer()->size()));
440 prev = it->section_;
441 if (debug_logging_) {
442 LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset
443 << " " << it->name_ << " size=" << it->section_.sh_size;
444 }
445 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700446
Brian Carlstromb12f3472014-06-11 14:54:46 -0700447 // Get the layout of the shstrtab section
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000448 shstrtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
449 (shstrtab_builder_.section_, prev);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700450 shstrtab_builder_.section_.sh_addr = 0;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700451 shstrtab_builder_.section_.sh_size = shstrtab_.size();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700452 shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink();
453 if (debug_logging_) {
454 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset
455 << " shstrtab size=" << shstrtab_builder_.section_.sh_size;
Mark Mendellae9fd932014-02-10 16:14:35 -0800456 }
457
Brian Carlstromb12f3472014-06-11 14:54:46 -0700458 // The section list comes after come after.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000459 Elf_Word sections_offset = RoundUp(
Brian Carlstromb12f3472014-06-11 14:54:46 -0700460 shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000461 sizeof(Elf_Word));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700462
Brian Carlstromb12f3472014-06-11 14:54:46 -0700463 // Setup the actual symbol arrays.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000464 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
465 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.section_.sh_size);
466 std::vector<Elf_Sym> symtab;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700467 if (IncludingDebugSymbols()) {
468 symtab = symtab_builder_.GenerateSymtab();
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000469 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.section_.sh_size);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700470 }
471
472 // Setup the dynamic section.
473 // This will add the 2 values we cannot know until now time, namely the size
474 // and the soname_offset.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000475 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700476 dynstr_soname_offset_);
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000477 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.section_.sh_size);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700478
479 // Finish setup of the program headers now that we know the layout of the
480 // whole file.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000481 Elf_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700482 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
483 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
484 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700485
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000486 Elf_Word load_rx_size = text_builder_.section_.sh_size;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700487 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset;
488 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.section_.sh_offset;
489 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.section_.sh_offset;
490 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
491 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
492 program_headers_[PH_LOAD_R_X].p_align = text_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700493
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700494 program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset;
495 program_headers_[PH_LOAD_RW_].p_vaddr = dynamic_builder_.section_.sh_offset;
496 program_headers_[PH_LOAD_RW_].p_paddr = dynamic_builder_.section_.sh_offset;
497 program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size;
498 program_headers_[PH_LOAD_RW_].p_memsz = dynamic_builder_.section_.sh_size;
499 program_headers_[PH_LOAD_RW_].p_align = dynamic_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700500
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700501 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset;
502 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.section_.sh_offset;
503 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.section_.sh_offset;
504 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size;
505 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.section_.sh_size;
506 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.section_.sh_addralign;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700507
508 // Finish setup of the Ehdr values.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700509 elf_header_.e_phoff = PHDR_OFFSET;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700510 elf_header_.e_shoff = sections_offset;
511 elf_header_.e_phnum = PH_NUM;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700512 elf_header_.e_shnum = section_ptrs_.size();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700513 elf_header_.e_shstrndx = shstrtab_builder_.section_index_;
514
515 // Add the rest of the pieces to the list.
516 pieces.push_back(ElfFilePiece("Elf Header", 0, &elf_header_, sizeof(elf_header_)));
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700517 pieces.push_back(ElfFilePiece("Program headers", PHDR_OFFSET,
518 &program_headers_, sizeof(program_headers_)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700519 pieces.push_back(ElfFilePiece(".dynamic", dynamic_builder_.section_.sh_offset,
520 dynamic.data(), dynamic_builder_.section_.sh_size));
521 pieces.push_back(ElfFilePiece(".dynsym", dynsym_builder_.section_.sh_offset,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000522 dynsym.data(), dynsym.size() * sizeof(Elf_Sym)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700523 pieces.push_back(ElfFilePiece(".dynstr", dynsym_builder_.strtab_.section_.sh_offset,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700524 dynstr_.c_str(), dynstr_.size()));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700525 pieces.push_back(ElfFilePiece(".hash", hash_builder_.section_.sh_offset,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000526 hash_.data(), hash_.size() * sizeof(Elf_Word)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700527 pieces.push_back(ElfFilePiece(".rodata", rodata_builder_.section_.sh_offset,
Alex Light3470ab42014-06-18 10:35:45 -0700528 nullptr, rodata_builder_.section_.sh_size));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700529 pieces.push_back(ElfFilePiece(".text", text_builder_.section_.sh_offset,
Alex Light3470ab42014-06-18 10:35:45 -0700530 nullptr, text_builder_.section_.sh_size));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700531 if (IncludingDebugSymbols()) {
532 pieces.push_back(ElfFilePiece(".symtab", symtab_builder_.section_.sh_offset,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000533 symtab.data(), symtab.size() * sizeof(Elf_Sym)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700534 pieces.push_back(ElfFilePiece(".strtab", symtab_builder_.strtab_.section_.sh_offset,
535 strtab.c_str(), strtab.size()));
536 }
537 pieces.push_back(ElfFilePiece(".shstrtab", shstrtab_builder_.section_.sh_offset,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700538 &shstrtab_[0], shstrtab_.size()));
539 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700540 // Just add all the sections in induvidually since they are all over the
541 // place on the heap/stack.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000542 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700543 pieces.push_back(ElfFilePiece("section table piece", cur_off,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000544 section_ptrs_[i], sizeof(Elf_Shdr)));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700545 }
546
547 if (!WriteOutFile(pieces)) {
548 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700549 return false;
550 }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700551 // write out the actual oat file data.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000552 Elf_Word oat_data_offset = rodata_builder_.section_.sh_offset;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700553 if (static_cast<off_t>(oat_data_offset) != lseek(elf_file_->Fd(), oat_data_offset, SEEK_SET)) {
554 PLOG(ERROR) << "Failed to seek to .rodata offset " << oat_data_offset
555 << " for " << elf_file_->GetPath();
556 return false;
557 }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700558 std::unique_ptr<BufferedOutputStream> output_stream(
559 new BufferedOutputStream(new FileOutputStream(elf_file_)));
560 if (!oat_writer_->Write(output_stream.get())) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700561 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file_->GetPath();
562 return false;
563 }
564
Brian Carlstrom35f72252014-06-11 21:24:53 +0000565 return true;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700566}
567
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000568template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
569 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
570 typename Elf_Phdr, typename Elf_Shdr>
571bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
572 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::WriteOutFile(const std::vector<ElfFilePiece>& pieces) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700573 // TODO It would be nice if this checked for overlap.
574 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
575 if (it->data_) {
576 if (static_cast<off_t>(it->offset_) != lseek(elf_file_->Fd(), it->offset_, SEEK_SET)) {
577 PLOG(ERROR) << "Failed to seek to " << it->dbg_name_ << " offset location "
578 << it->offset_ << " for " << elf_file_->GetPath();
579 return false;
580 }
581 if (!elf_file_->WriteFully(it->data_, it->size_)) {
582 PLOG(ERROR) << "Failed to write " << it->dbg_name_ << " for " << elf_file_->GetPath();
583 return false;
584 }
585 }
586 }
587 return true;
588}
589
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000590template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
591 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
592 typename Elf_Phdr, typename Elf_Shdr>
593void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
594 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::SetupDynamic() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700595 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
596 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, &dynsym_builder_.strtab_);
597 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000598 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700599}
600
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000601template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
602 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
603 typename Elf_Phdr, typename Elf_Shdr>
604void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
605 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::SetupRequiredSymbols() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700606 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
607 rodata_builder_.size_, STB_GLOBAL, STT_OBJECT);
608 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
609 text_builder_.size_, STB_GLOBAL, STT_OBJECT);
610 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.size_ - 4,
611 true, 4, STB_GLOBAL, STT_OBJECT);
612}
613
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000614template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
615 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
616 typename Elf_Phdr, typename Elf_Shdr>
617void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
618 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfDynamicBuilder::AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700619 if (tag == DT_NULL) {
620 return;
621 }
Alex Light3470ab42014-06-18 10:35:45 -0700622 dynamics_.push_back({nullptr, tag, d_un});
Brian Carlstromb12f3472014-06-11 14:54:46 -0700623}
624
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000625template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
626 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
627 typename Elf_Phdr, typename Elf_Shdr>
628void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
629 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfDynamicBuilder::AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700630 ElfSectionBuilder* section) {
631 if (tag == DT_NULL) {
632 return;
633 }
634 dynamics_.push_back({section, tag, d_un});
635}
636
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000637template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
638 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
639 typename Elf_Phdr, typename Elf_Shdr>
640std::vector<Elf_Dyn> ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
641 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfDynamicBuilder::GetDynamics(Elf_Word strsz,
642 Elf_Word soname) {
643 std::vector<Elf_Dyn> ret;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700644 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
645 if (it->section_) {
646 // We are adding an address relative to a section.
647 ret.push_back(
Brian Carlstrom8758c642014-06-11 14:22:02 -0700648 {it->tag_, {it->off_ + it->section_->section_.sh_addr}});
Brian Carlstromb12f3472014-06-11 14:54:46 -0700649 } else {
650 ret.push_back({it->tag_, {it->off_}});
651 }
652 }
653 ret.push_back({DT_STRSZ, {strsz}});
654 ret.push_back({DT_SONAME, {soname}});
655 ret.push_back({DT_NULL, {0}});
656 return ret;
657}
658
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000659template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
660 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
661 typename Elf_Phdr, typename Elf_Shdr>
662std::vector<Elf_Sym> ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
663 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfSymtabBuilder::GenerateSymtab() {
664 std::vector<Elf_Sym> ret;
665 Elf_Sym undef_sym;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700666 memset(&undef_sym, 0, sizeof(undef_sym));
667 undef_sym.st_shndx = SHN_UNDEF;
668 ret.push_back(undef_sym);
669
670 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000671 Elf_Sym sym;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700672 memset(&sym, 0, sizeof(sym));
673 sym.st_name = it->name_idx_;
674 if (it->is_relative_) {
675 sym.st_value = it->addr_ + it->section_->section_.sh_offset;
676 } else {
677 sym.st_value = it->addr_;
678 }
679 sym.st_size = it->size_;
680 sym.st_other = it->other_;
681 sym.st_shndx = it->section_->section_index_;
682 sym.st_info = it->info_;
683
684 ret.push_back(sym);
685 }
686 return ret;
687}
688
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000689template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
690 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
691 typename Elf_Phdr, typename Elf_Shdr>
692std::string ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
693 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfSymtabBuilder::GenerateStrtab() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700694 std::string tab;
695 tab += '\0';
696 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
697 it->name_idx_ = tab.size();
698 tab += it->name_;
699 tab += '\0';
700 }
701 strtab_.section_.sh_size = tab.size();
702 return tab;
703}
704
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000705template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
706 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
707 typename Elf_Phdr, typename Elf_Shdr>
708void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
709 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::AssignSectionStr(
Brian Carlstromb12f3472014-06-11 14:54:46 -0700710 ElfSectionBuilder* builder, std::string* strtab) {
711 builder->section_.sh_name = strtab->size();
712 *strtab += builder->name_;
713 *strtab += '\0';
714 if (debug_logging_) {
715 LOG(INFO) << "adding section name \"" << builder->name_ << "\" "
716 << "to shstrtab at offset " << builder->section_.sh_name;
717 }
718}
719
720// from bionic
721static unsigned elfhash(const char *_name) {
722 const unsigned char *name = (const unsigned char *) _name;
723 unsigned h = 0, g;
724
725 while (*name) {
726 h = (h << 4) + *name++;
727 g = h & 0xf0000000;
728 h ^= g;
729 h ^= g >> 24;
730 }
731 return h;
732}
733
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000734template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
735 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
736 typename Elf_Phdr, typename Elf_Shdr>
737std::vector<Elf_Word> ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
738 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfSymtabBuilder::GenerateHashContents() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700739 // Here is how The ELF hash table works.
740 // There are 3 arrays to worry about.
741 // * The symbol table where the symbol information is.
742 // * The bucket array which is an array of indexes into the symtab and chain.
743 // * The chain array which is also an array of indexes into the symtab and chain.
744 //
745 // Lets say the state is something like this.
746 // +--------+ +--------+ +-----------+
747 // | symtab | | bucket | | chain |
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700748 // | null | | 1 | | STN_UNDEF |
Brian Carlstromb12f3472014-06-11 14:54:46 -0700749 // | <sym1> | | 4 | | 2 |
750 // | <sym2> | | | | 5 |
751 // | <sym3> | | | | STN_UNDEF |
752 // | <sym4> | | | | 3 |
753 // | <sym5> | | | | STN_UNDEF |
754 // +--------+ +--------+ +-----------+
755 //
756 // The lookup process (in python psudocode) is
757 //
758 // def GetSym(name):
759 // # NB STN_UNDEF == 0
760 // indx = bucket[elfhash(name) % num_buckets]
761 // while indx != STN_UNDEF:
762 // if GetSymbolName(symtab[indx]) == name:
763 // return symtab[indx]
764 // indx = chain[indx]
765 // return SYMBOL_NOT_FOUND
766 //
767 // Between bucket and chain arrays every symtab index must be present exactly
768 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
769
770 // Select number of buckets.
771 // This is essentially arbitrary.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000772 Elf_Word nbuckets;
773 Elf_Word chain_size = GetSize();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700774 if (symbols_.size() < 8) {
775 nbuckets = 2;
776 } else if (symbols_.size() < 32) {
777 nbuckets = 4;
778 } else if (symbols_.size() < 256) {
779 nbuckets = 16;
780 } else {
781 // Have about 32 ids per bucket.
782 nbuckets = RoundUp(symbols_.size()/32, 2);
783 }
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000784 std::vector<Elf_Word> hash;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700785 hash.push_back(nbuckets);
786 hash.push_back(chain_size);
787 uint32_t bucket_offset = hash.size();
788 uint32_t chain_offset = bucket_offset + nbuckets;
789 hash.resize(hash.size() + nbuckets + chain_size, 0);
790
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000791 Elf_Word* buckets = hash.data() + bucket_offset;
792 Elf_Word* chain = hash.data() + chain_offset;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700793
794 // Set up the actual hash table.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000795 for (Elf_Word i = 0; i < symbols_.size(); i++) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700796 // Add 1 since we need to have the null symbol that is not in the symbols
797 // list.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000798 Elf_Word index = i + 1;
799 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700800 if (buckets[hash_val] == 0) {
801 buckets[hash_val] = index;
802 } else {
803 hash_val = buckets[hash_val];
804 CHECK_LT(hash_val, chain_size);
805 while (chain[hash_val] != 0) {
806 hash_val = chain[hash_val];
807 CHECK_LT(hash_val, chain_size);
808 }
809 chain[hash_val] = index;
810 // Check for loops. Works because if this is non-empty then there must be
811 // another cell which already contains the same symbol index as this one,
812 // which means some symbol has more then one name, which isn't allowed.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000813 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
Brian Carlstromb12f3472014-06-11 14:54:46 -0700814 }
815 }
816
817 return hash;
818}
819
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000820template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
821 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
822 typename Elf_Phdr, typename Elf_Shdr>
823void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
824 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::SetupEhdr() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700825 memset(&elf_header_, 0, sizeof(elf_header_));
826 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
827 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
828 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
829 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
830 elf_header_.e_ident[EI_CLASS] = ELFCLASS32;
831 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
832 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
833 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
834 elf_header_.e_ident[EI_ABIVERSION] = 0;
835 elf_header_.e_type = ET_DYN;
836 elf_header_.e_version = 1;
837 elf_header_.e_entry = 0;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000838 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
839 elf_header_.e_phentsize = sizeof(Elf_Phdr);
840 elf_header_.e_shentsize = sizeof(Elf_Shdr);
841 elf_header_.e_phoff = sizeof(Elf_Ehdr);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700842}
843
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000844template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
845 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
846 typename Elf_Phdr, typename Elf_Shdr>
847void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
848 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfBuilder::SetISA(InstructionSet isa) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700849 switch (isa) {
850 case kArm:
851 // Fall through.
852 case kThumb2: {
853 elf_header_.e_machine = EM_ARM;
854 elf_header_.e_flags = EF_ARM_EABI_VER5;
855 break;
856 }
857 case kArm64: {
858 elf_header_.e_machine = EM_AARCH64;
859 elf_header_.e_flags = 0;
860 break;
861 }
862 case kX86: {
863 elf_header_.e_machine = EM_386;
864 elf_header_.e_flags = 0;
865 break;
866 }
867 case kX86_64: {
868 elf_header_.e_machine = EM_X86_64;
869 elf_header_.e_flags = 0;
870 break;
871 }
872 case kMips: {
873 elf_header_.e_machine = EM_MIPS;
874 elf_header_.e_flags = (EF_MIPS_NOREORDER |
875 EF_MIPS_PIC |
876 EF_MIPS_CPIC |
877 EF_MIPS_ABI_O32 |
878 EF_MIPS_ARCH_32R2);
879 break;
880 }
881 default: {
882 fatal_error_ = true;
883 LOG(FATAL) << "Unknown instruction set: " << isa;
884 break;
885 }
886 }
887}
888
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000889template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
890 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
891 typename Elf_Phdr, typename Elf_Shdr>
892void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
893 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ElfSymtabBuilder::AddSymbol(
894 const std::string& name, const ElfSectionBuilder* section, Elf_Addr addr,
895 bool is_relative, Elf_Word size, uint8_t binding, uint8_t type, uint8_t other) {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700896 CHECK(section);
897 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
898 MakeStInfo(binding, type), other, 0};
899 symbols_.push_back(state);
900}
901
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000902template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
903 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
904 typename Elf_Phdr, typename Elf_Shdr>
905bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
906 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Create(File* elf_file,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700907 OatWriter* oat_writer,
908 const std::vector<const DexFile*>& dex_files,
909 const std::string& android_root,
910 bool is_host,
911 const CompilerDriver& driver) {
912 ElfWriterQuick elf_writer(driver, elf_file);
913 return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
914}
915
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000916template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
917 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
918 typename Elf_Phdr, typename Elf_Shdr>
919// Add patch information to this section. Each patch is a Elf_Word that
Alex Light53cb16b2014-06-12 11:26:29 -0700920// identifies an offset from the start of the text section
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000921void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
922 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug) {
Alex Light53cb16b2014-06-12 11:26:29 -0700923 size_t size =
924 compiler_driver_->GetCodeToPatch().size() +
925 compiler_driver_->GetMethodsToPatch().size() +
926 compiler_driver_->GetClassesToPatch().size();
927 if (size == 0) {
928 if (debug) {
929 LOG(INFO) << "No patches to record";
930 }
931 return;
932 }
933 buffer->resize(size * sizeof(uintptr_t));
934 if (debug) {
935 LOG(INFO) << "Patches reserved for " << size;
936 }
937}
938
Andreas Gampe79273802014-08-05 20:21:05 -0700939std::vector<uint8_t>* ConstructCIEFrameX86(bool is_x86_64) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700940 std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>;
Andreas Gampe79273802014-08-05 20:21:05 -0700941
942 // Length (will be filled in later in this routine).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700943 if (is_x86_64) {
944 PushWord(cfi_info, 0xffffffff); // Indicates 64bit
945 PushWord(cfi_info, 0);
946 PushWord(cfi_info, 0);
947 } else {
948 PushWord(cfi_info, 0);
949 }
Andreas Gampe79273802014-08-05 20:21:05 -0700950
951 // CIE id: always 0.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700952 if (is_x86_64) {
953 PushWord(cfi_info, 0);
954 PushWord(cfi_info, 0);
955 } else {
956 PushWord(cfi_info, 0);
957 }
Andreas Gampe79273802014-08-05 20:21:05 -0700958
959 // Version: always 1.
960 cfi_info->push_back(0x01);
961
962 // Augmentation: 'zR\0'
963 cfi_info->push_back(0x7a);
964 cfi_info->push_back(0x52);
965 cfi_info->push_back(0x0);
966
967 // Code alignment: 1.
968 EncodeUnsignedLeb128(1, cfi_info);
969
970 // Data alignment.
971 if (is_x86_64) {
972 EncodeSignedLeb128(-8, cfi_info);
973 } else {
974 EncodeSignedLeb128(-4, cfi_info);
975 }
976
977 // Return address register.
978 if (is_x86_64) {
979 // R16(RIP)
980 cfi_info->push_back(0x10);
981 } else {
982 // R8(EIP)
983 cfi_info->push_back(0x08);
984 }
985
986 // Augmentation length: 1.
987 cfi_info->push_back(1);
988
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700989 // Augmentation data.
990 if (is_x86_64) {
991 // 0x04 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
992 cfi_info->push_back(0x04);
993 } else {
994 // 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
995 cfi_info->push_back(0x03);
996 }
Andreas Gampe79273802014-08-05 20:21:05 -0700997
998 // Initial instructions.
999 if (is_x86_64) {
1000 // DW_CFA_def_cfa R7(RSP) 8.
1001 cfi_info->push_back(0x0c);
1002 cfi_info->push_back(0x07);
1003 cfi_info->push_back(0x08);
1004
1005 // DW_CFA_offset R16(RIP) 1 (* -8).
1006 cfi_info->push_back(0x90);
1007 cfi_info->push_back(0x01);
1008 } else {
1009 // DW_CFA_def_cfa R4(ESP) 4.
1010 cfi_info->push_back(0x0c);
1011 cfi_info->push_back(0x04);
1012 cfi_info->push_back(0x04);
1013
1014 // DW_CFA_offset R8(EIP) 1 (* -4).
1015 cfi_info->push_back(0x88);
1016 cfi_info->push_back(0x01);
1017 }
1018
1019 // Padding to a multiple of 4
1020 while ((cfi_info->size() & 3) != 0) {
1021 // DW_CFA_nop is encoded as 0.
1022 cfi_info->push_back(0);
1023 }
1024
1025 // Set the length of the CIE inside the generated bytes.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001026 if (is_x86_64) {
1027 uint32_t length = cfi_info->size() - 12;
1028 UpdateWord(cfi_info, 4, length);
1029 } else {
1030 uint32_t length = cfi_info->size() - 4;
1031 UpdateWord(cfi_info, 0, length);
1032 }
Andreas Gampe79273802014-08-05 20:21:05 -07001033 return cfi_info;
1034}
1035
1036std::vector<uint8_t>* ConstructCIEFrame(InstructionSet isa) {
1037 switch (isa) {
1038 case kX86:
1039 return ConstructCIEFrameX86(false);
1040 case kX86_64:
1041 return ConstructCIEFrameX86(true);
1042
1043 default:
1044 // Not implemented.
1045 return nullptr;
1046 }
1047}
1048
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001049template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
1050 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
1051 typename Elf_Phdr, typename Elf_Shdr>
1052bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
1053 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Write(OatWriter* oat_writer,
Brian Carlstromb12f3472014-06-11 14:54:46 -07001054 const std::vector<const DexFile*>& dex_files_unused,
1055 const std::string& android_root_unused,
1056 bool is_host_unused) {
Andreas Gampe79273802014-08-05 20:21:05 -07001057 constexpr bool debug = false;
Brian Carlstromb12f3472014-06-11 14:54:46 -07001058 const OatHeader& oat_header = oat_writer->GetOatHeader();
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001059 Elf_Word oat_data_size = oat_header.GetExecutableOffset();
Brian Carlstromb12f3472014-06-11 14:54:46 -07001060 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
1061
Brian Carlstrom18a49cc2014-08-29 16:20:48 -07001062 std::unique_ptr<ElfBuilder> builder(new ElfBuilder(
1063 oat_writer,
1064 elf_file_,
1065 compiler_driver_->GetInstructionSet(),
1066 0,
1067 oat_data_size,
1068 oat_data_size,
1069 oat_exec_size,
1070 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
1071 debug));
Alex Light78382fa2014-06-06 15:45:32 -07001072
Brian Carlstrom18a49cc2014-08-29 16:20:48 -07001073 if (!builder->Init()) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001074 return false;
1075 }
1076
Andreas Gampe79273802014-08-05 20:21:05 -07001077 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
Brian Carlstrom18a49cc2014-08-29 16:20:48 -07001078 WriteDebugSymbols(builder.get(), oat_writer);
Brian Carlstromb12f3472014-06-11 14:54:46 -07001079 }
1080
Alex Light53cb16b2014-06-12 11:26:29 -07001081 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
1082 ElfRawSectionBuilder oat_patches(".oat_patches", SHT_OAT_PATCH, 0, NULL, 0,
Alex Light4b0d2d92014-08-06 13:37:23 -07001083 sizeof(uintptr_t), sizeof(uintptr_t));
Alex Light53cb16b2014-06-12 11:26:29 -07001084 ReservePatchSpace(oat_patches.GetBuffer(), debug);
Brian Carlstrom18a49cc2014-08-29 16:20:48 -07001085 builder->RegisterRawSection(oat_patches);
Alex Light53cb16b2014-06-12 11:26:29 -07001086 }
1087
Brian Carlstrom18a49cc2014-08-29 16:20:48 -07001088 return builder->Write();
Brian Carlstromb12f3472014-06-11 14:54:46 -07001089}
Mark Mendellae9fd932014-02-10 16:14:35 -08001090
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001091template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
1092 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
1093 typename Elf_Phdr, typename Elf_Shdr>
1094void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
1095 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::WriteDebugSymbols(ElfBuilder* builder, OatWriter* oat_writer) {
Andreas Gampe79273802014-08-05 20:21:05 -07001096 std::unique_ptr<std::vector<uint8_t>> cfi_info(
1097 ConstructCIEFrame(compiler_driver_->GetInstructionSet()));
1098
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001099 Elf_Addr text_section_address = builder->text_builder_.section_.sh_addr;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001100
Andreas Gampe79273802014-08-05 20:21:05 -07001101 // Iterate over the compiled methods.
Alex Light78382fa2014-06-06 15:45:32 -07001102 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001103 ElfSymtabBuilder* symtab = &builder->symtab_builder_;
Alex Light78382fa2014-06-06 15:45:32 -07001104 for (auto it = method_info.begin(); it != method_info.end(); ++it) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001105 symtab->AddSymbol(it->method_name_, &builder->text_builder_, it->low_pc_, true,
Alex Light78382fa2014-06-06 15:45:32 -07001106 it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
Andreas Gampe79273802014-08-05 20:21:05 -07001107
1108 // Include CFI for compiled method, if possible.
1109 if (cfi_info.get() != nullptr) {
1110 DCHECK(it->compiled_method_ != nullptr);
1111
1112 // Copy in the FDE, if present
1113 const std::vector<uint8_t>* fde = it->compiled_method_->GetCFIInfo();
1114 if (fde != nullptr) {
1115 // Copy the information into cfi_info and then fix the address in the new copy.
1116 int cur_offset = cfi_info->size();
1117 cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
1118
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001119 bool is_64bit = *(reinterpret_cast<const uint32_t*>(fde->data())) == 0xffffffff;
Andreas Gampe79273802014-08-05 20:21:05 -07001120
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001121 // Set the 'CIE_pointer' field.
1122 uint64_t CIE_pointer = cur_offset + (is_64bit ? 12 : 4);
1123 uint64_t offset_to_update = CIE_pointer;
1124 if (is_64bit) {
1125 (*cfi_info)[offset_to_update+0] = CIE_pointer;
1126 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1127 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1128 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1129 (*cfi_info)[offset_to_update+4] = CIE_pointer >> 32;
1130 (*cfi_info)[offset_to_update+5] = CIE_pointer >> 40;
1131 (*cfi_info)[offset_to_update+6] = CIE_pointer >> 48;
1132 (*cfi_info)[offset_to_update+7] = CIE_pointer >> 56;
1133 } else {
1134 (*cfi_info)[offset_to_update+0] = CIE_pointer;
1135 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1136 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1137 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1138 }
1139
1140 // Set the 'initial_location' field.
1141 offset_to_update += is_64bit ? 8 : 4;
1142 if (is_64bit) {
1143 const uint64_t quick_code_start = it->low_pc_ + text_section_address;
1144 (*cfi_info)[offset_to_update+0] = quick_code_start;
1145 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1146 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1147 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1148 (*cfi_info)[offset_to_update+4] = quick_code_start >> 32;
1149 (*cfi_info)[offset_to_update+5] = quick_code_start >> 40;
1150 (*cfi_info)[offset_to_update+6] = quick_code_start >> 48;
1151 (*cfi_info)[offset_to_update+7] = quick_code_start >> 56;
1152 } else {
1153 const uint32_t quick_code_start = it->low_pc_ + text_section_address;
1154 (*cfi_info)[offset_to_update+0] = quick_code_start;
1155 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1156 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1157 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1158 }
Andreas Gampe79273802014-08-05 20:21:05 -07001159 }
1160 }
Alex Light78382fa2014-06-06 15:45:32 -07001161 }
Alex Light78382fa2014-06-06 15:45:32 -07001162
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001163 bool hasCFI = (cfi_info.get() != nullptr);
1164 bool hasLineInfo = false;
1165 for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
1166 if (dbg_info.dbgstream_ != nullptr &&
1167 !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
1168 hasLineInfo = true;
1169 break;
1170 }
1171 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001172
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001173 if (hasLineInfo || hasCFI) {
1174 ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1175 ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1176 ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1177 ElfRawSectionBuilder debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1178
1179 FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
1180 debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
1181 hasLineInfo ? debug_line.GetBuffer() : nullptr,
1182 text_section_address);
1183
1184 builder->RegisterRawSection(debug_info);
1185 builder->RegisterRawSection(debug_abbrev);
1186
1187 if (hasCFI) {
1188 ElfRawSectionBuilder eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
1189 eh_frame.SetBuffer(std::move(*cfi_info.get()));
1190 builder->RegisterRawSection(eh_frame);
1191 }
1192
1193 if (hasLineInfo) {
1194 builder->RegisterRawSection(debug_line);
1195 }
1196
1197 builder->RegisterRawSection(debug_str);
1198 }
1199}
1200
1201class LineTableGenerator FINAL : public Leb128Encoder {
1202 public:
1203 LineTableGenerator(int line_base, int line_range, int opcode_base,
1204 std::vector<uint8_t>* data, uintptr_t current_address,
1205 size_t current_line)
1206 : Leb128Encoder(data), line_base_(line_base), line_range_(line_range),
1207 opcode_base_(opcode_base), current_address_(current_address),
Yevgeny Rouban33ac8192014-08-19 18:39:57 +07001208 current_line_(current_line), current_file_index_(0) {}
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001209
1210 void PutDelta(unsigned delta_addr, int delta_line) {
1211 current_line_ += delta_line;
1212 current_address_ += delta_addr;
1213
1214 if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) {
1215 unsigned special_opcode = (delta_line - line_base_) +
1216 (line_range_ * delta_addr) + opcode_base_;
1217 if (special_opcode <= 255) {
1218 PushByte(data_, special_opcode);
1219 return;
1220 }
1221 }
1222
1223 // generate standart opcode for address advance
1224 if (delta_addr != 0) {
1225 PushByte(data_, DW_LNS_advance_pc);
1226 PushBackUnsigned(delta_addr);
1227 }
1228
1229 // generate standart opcode for line delta
1230 if (delta_line != 0) {
1231 PushByte(data_, DW_LNS_advance_line);
1232 PushBackSigned(delta_line);
1233 }
1234
1235 // generate standart opcode for new LTN entry
1236 PushByte(data_, DW_LNS_copy);
1237 }
1238
1239 void SetAddr(uintptr_t addr) {
1240 if (current_address_ == addr) {
1241 return;
1242 }
1243
1244 current_address_ = addr;
1245
1246 PushByte(data_, 0); // extended opcode:
1247 PushByte(data_, 1 + 4); // length: opcode_size + address_size
1248 PushByte(data_, DW_LNE_set_address);
1249 PushWord(data_, addr);
1250 }
1251
1252 void SetLine(unsigned line) {
1253 int delta_line = line - current_line_;
1254 if (delta_line) {
1255 current_line_ = line;
1256 PushByte(data_, DW_LNS_advance_line);
1257 PushBackSigned(delta_line);
1258 }
1259 }
1260
1261 void SetFile(unsigned file_index) {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +07001262 if (current_file_index_ != file_index) {
1263 current_file_index_ = file_index;
1264 PushByte(data_, DW_LNS_set_file);
1265 PushBackUnsigned(file_index);
1266 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001267 }
1268
1269 void EndSequence() {
1270 // End of Line Table Program
1271 // 0(=ext), 1(len), DW_LNE_end_sequence
1272 PushByte(data_, 0);
1273 PushByte(data_, 1);
1274 PushByte(data_, DW_LNE_end_sequence);
1275 }
1276
1277 private:
1278 const int line_base_;
1279 const int line_range_;
1280 const int opcode_base_;
1281 uintptr_t current_address_;
1282 size_t current_line_;
Yevgeny Rouban33ac8192014-08-19 18:39:57 +07001283 unsigned current_file_index_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001284
1285 DISALLOW_COPY_AND_ASSIGN(LineTableGenerator);
1286};
1287
1288// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
1289static void GetLineInfoForJava(const uint8_t* dbgstream, const SrcMap& pc2dex,
1290 SrcMap* result, uint32_t start_pc = 0) {
1291 if (dbgstream == nullptr) {
1292 return;
1293 }
1294
1295 int adjopcode;
1296 uint32_t dex_offset = 0;
1297 uint32_t java_line = DecodeUnsignedLeb128(&dbgstream);
1298
1299 // skip parameters
1300 for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) {
1301 DecodeUnsignedLeb128(&dbgstream);
1302 }
1303
1304 for (bool is_end = false; is_end == false; ) {
1305 uint8_t opcode = *dbgstream;
1306 dbgstream++;
1307 switch (opcode) {
1308 case DexFile::DBG_END_SEQUENCE:
1309 is_end = true;
1310 break;
1311
1312 case DexFile::DBG_ADVANCE_PC:
1313 dex_offset += DecodeUnsignedLeb128(&dbgstream);
1314 break;
1315
1316 case DexFile::DBG_ADVANCE_LINE:
1317 java_line += DecodeSignedLeb128(&dbgstream);
1318 break;
1319
1320 case DexFile::DBG_START_LOCAL:
1321 case DexFile::DBG_START_LOCAL_EXTENDED:
1322 DecodeUnsignedLeb128(&dbgstream);
1323 DecodeUnsignedLeb128(&dbgstream);
1324 DecodeUnsignedLeb128(&dbgstream);
1325
1326 if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) {
1327 DecodeUnsignedLeb128(&dbgstream);
1328 }
1329 break;
1330
1331 case DexFile::DBG_END_LOCAL:
1332 case DexFile::DBG_RESTART_LOCAL:
1333 DecodeUnsignedLeb128(&dbgstream);
1334 break;
1335
1336 case DexFile::DBG_SET_PROLOGUE_END:
1337 case DexFile::DBG_SET_EPILOGUE_BEGIN:
1338 case DexFile::DBG_SET_FILE:
1339 break;
1340
1341 default:
1342 adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
1343 dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
1344 java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
1345
1346 for (SrcMap::const_iterator found = pc2dex.FindByTo(dex_offset);
1347 found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset);
1348 found++) {
1349 result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)});
1350 }
1351 break;
1352 }
Andreas Gampe79273802014-08-05 20:21:05 -07001353 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001354}
1355
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001356template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
1357 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
1358 typename Elf_Phdr, typename Elf_Shdr>
1359void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
1360 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::FillInCFIInformation(OatWriter* oat_writer,
Mark Mendellae9fd932014-02-10 16:14:35 -08001361 std::vector<uint8_t>* dbg_info,
1362 std::vector<uint8_t>* dbg_abbrev,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001363 std::vector<uint8_t>* dbg_str,
1364 std::vector<uint8_t>* dbg_line,
1365 uint32_t text_section_offset) {
1366 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
1367
1368 uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
1369
Mark Mendellae9fd932014-02-10 16:14:35 -08001370 // Create the debug_abbrev section with boilerplate information.
1371 // We only care about low_pc and high_pc right now for the compilation
1372 // unit and methods.
1373
1374 // Tag 1: Compilation unit: DW_TAG_compile_unit.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001375 PushByte(dbg_abbrev, 1);
1376 PushByte(dbg_abbrev, DW_TAG_compile_unit);
Mark Mendellae9fd932014-02-10 16:14:35 -08001377
1378 // There are children (the methods).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001379 PushByte(dbg_abbrev, DW_CHILDREN_yes);
1380
1381 // DW_AT_producer DW_FORM_data1.
1382 // REVIEW: we can get rid of dbg_str section if
1383 // DW_FORM_string (immediate string) was used everywhere instead of
1384 // DW_FORM_strp (ref to string from .debug_str section).
1385 // DW_FORM_strp makes sense only if we reuse the strings.
1386 PushByte(dbg_abbrev, DW_AT_producer);
1387 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -08001388
1389 // DW_LANG_Java DW_FORM_data1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001390 PushByte(dbg_abbrev, DW_AT_language);
1391 PushByte(dbg_abbrev, DW_FORM_data1);
Mark Mendellae9fd932014-02-10 16:14:35 -08001392
1393 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001394 PushByte(dbg_abbrev, DW_AT_low_pc);
1395 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001396
1397 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001398 PushByte(dbg_abbrev, DW_AT_high_pc);
1399 PushByte(dbg_abbrev, DW_FORM_addr);
1400
1401 if (dbg_line != nullptr) {
1402 // DW_AT_stmt_list DW_FORM_sec_offset.
1403 PushByte(dbg_abbrev, DW_AT_stmt_list);
1404 PushByte(dbg_abbrev, DW_FORM_sec_offset);
1405 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001406
1407 // End of DW_TAG_compile_unit.
1408 PushHalf(dbg_abbrev, 0);
1409
1410 // Tag 2: Compilation unit: DW_TAG_subprogram.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001411 PushByte(dbg_abbrev, 2);
1412 PushByte(dbg_abbrev, DW_TAG_subprogram);
Mark Mendellae9fd932014-02-10 16:14:35 -08001413
1414 // There are no children.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001415 PushByte(dbg_abbrev, DW_CHILDREN_no);
Mark Mendellae9fd932014-02-10 16:14:35 -08001416
1417 // Name of the method.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001418 PushByte(dbg_abbrev, DW_AT_name);
1419 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -08001420
1421 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001422 PushByte(dbg_abbrev, DW_AT_low_pc);
1423 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001424
1425 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001426 PushByte(dbg_abbrev, DW_AT_high_pc);
1427 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001428
1429 // End of DW_TAG_subprogram.
1430 PushHalf(dbg_abbrev, 0);
1431
1432 // Start the debug_info section with the header information
1433 // 'unit_length' will be filled in later.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001434 int cunit_length = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -08001435 PushWord(dbg_info, 0);
1436
1437 // 'version' - 3.
1438 PushHalf(dbg_info, 3);
1439
1440 // Offset into .debug_abbrev section (always 0).
1441 PushWord(dbg_info, 0);
1442
1443 // Address size: 4.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001444 PushByte(dbg_info, 4);
Mark Mendellae9fd932014-02-10 16:14:35 -08001445
1446 // Start the description for the compilation unit.
1447 // This uses tag 1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001448 PushByte(dbg_info, 1);
1449
1450 // The producer is Android dex2oat.
1451 PushWord(dbg_info, producer_str_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -08001452
1453 // The language is Java.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001454 PushByte(dbg_info, DW_LANG_Java);
Mark Mendellae9fd932014-02-10 16:14:35 -08001455
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001456 // low_pc and high_pc.
1457 uint32_t cunit_low_pc = 0 - 1;
1458 uint32_t cunit_high_pc = 0;
1459 int cunit_low_pc_pos = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -08001460 PushWord(dbg_info, 0);
1461 PushWord(dbg_info, 0);
1462
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001463 if (dbg_line == nullptr) {
1464 for (size_t i = 0; i < method_info.size(); ++i) {
1465 const OatWriter::DebugInfo &dbg = method_info[i];
Mark Mendellae9fd932014-02-10 16:14:35 -08001466
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001467 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1468 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1469
1470 // Start a new TAG: subroutine (2).
1471 PushByte(dbg_info, 2);
1472
1473 // Enter name, low_pc, high_pc.
1474 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1475 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1476 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -08001477 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001478 } else {
1479 // TODO: in gdb info functions <regexp> - reports Java functions, but
1480 // source file is <unknown> because .debug_line is formed as one
1481 // compilation unit. To fix this it is possible to generate
1482 // a separate compilation unit for every distinct Java source.
1483 // Each of the these compilation units can have several non-adjacent
1484 // method ranges.
1485
1486 // Line number table offset
1487 PushWord(dbg_info, dbg_line->size());
1488
1489 size_t lnt_length = dbg_line->size();
1490 PushWord(dbg_line, 0);
1491
1492 PushHalf(dbg_line, 4); // LNT Version DWARF v4 => 4
1493
1494 size_t lnt_hdr_length = dbg_line->size();
1495 PushWord(dbg_line, 0); // TODO: 64-bit uses 8-byte here
1496
1497 PushByte(dbg_line, 1); // minimum_instruction_length (ubyte)
1498 PushByte(dbg_line, 1); // maximum_operations_per_instruction (ubyte) = always 1
1499 PushByte(dbg_line, 1); // default_is_stmt (ubyte)
1500
1501 const int8_t LINE_BASE = -5;
1502 PushByte(dbg_line, LINE_BASE); // line_base (sbyte)
1503
1504 const uint8_t LINE_RANGE = 14;
1505 PushByte(dbg_line, LINE_RANGE); // line_range (ubyte)
1506
1507 const uint8_t OPCODE_BASE = 13;
1508 PushByte(dbg_line, OPCODE_BASE); // opcode_base (ubyte)
1509
1510 // Standard_opcode_lengths (array of ubyte).
1511 PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1);
1512 PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0);
1513 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1514 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1515
1516 PushByte(dbg_line, 0); // include_directories (sequence of path names) = EMPTY
1517
1518 // File_names (sequence of file entries).
1519 std::unordered_map<const char*, size_t> files;
1520 for (size_t i = 0; i < method_info.size(); ++i) {
1521 const OatWriter::DebugInfo &dbg = method_info[i];
1522 // TODO: add package directory to the file name
1523 const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_;
1524 auto found = files.find(file_name);
1525 if (found == files.end()) {
1526 size_t file_index = 1 + files.size();
1527 files[file_name] = file_index;
1528 PushStr(dbg_line, file_name);
1529 PushByte(dbg_line, 0); // include directory index = LEB128(0) - no directory
1530 PushByte(dbg_line, 0); // modification time = LEB128(0) - NA
1531 PushByte(dbg_line, 0); // file length = LEB128(0) - NA
1532 }
1533 }
1534 PushByte(dbg_line, 0); // End of file_names.
1535
1536 // Set lnt header length.
1537 UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4);
1538
1539 // Generate Line Number Program code, one long program for all methods.
1540 LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE,
1541 dbg_line, 0, 1);
1542
1543 SrcMap pc2java_map;
1544 for (size_t i = 0; i < method_info.size(); ++i) {
1545 const OatWriter::DebugInfo &dbg = method_info[i];
1546 const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_;
1547 size_t file_index = files[file_name];
1548 DCHECK_NE(file_index, 0U) << file_name;
1549
1550 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1551 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1552
1553 // Start a new TAG: subroutine (2).
1554 PushByte(dbg_info, 2);
1555
1556 // Enter name, low_pc, high_pc.
1557 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1558 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1559 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
1560
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001561 GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(),
1562 &pc2java_map, dbg.low_pc_);
1563 pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_);
Yevgeny Rouban33ac8192014-08-19 18:39:57 +07001564 if (!pc2java_map.empty()) {
1565 line_table_generator.SetFile(file_index);
1566 line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset);
1567 line_table_generator.SetLine(1);
1568 for (auto& src_map_elem : pc2java_map) {
1569 line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_);
1570 }
1571 pc2java_map.clear();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001572 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001573 }
1574
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001575 // End Sequence should have the highest address set.
1576 line_table_generator.SetAddr(cunit_high_pc + text_section_offset);
1577 line_table_generator.EndSequence();
Mark Mendellae9fd932014-02-10 16:14:35 -08001578
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001579 // set lnt length
1580 UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4);
Mark Mendellae9fd932014-02-10 16:14:35 -08001581 }
1582
1583 // One byte terminator
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001584 PushByte(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -08001585
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001586 // Fill in cunit's low_pc and high_pc.
1587 UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset);
1588 UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset);
1589
1590 // We have now walked all the methods. Fill in lengths.
1591 UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001592}
1593
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001594// Explicit instantiations
1595template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
1596 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>;
1597template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
1598 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>;
1599
Brian Carlstrom7940e442013-07-12 13:46:57 -07001600} // namespace art