blob: 0216900f5575d946c02d43fe4e2f3c549330a15c [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
1062 ElfBuilder builder(oat_writer, elf_file_, compiler_driver_->GetInstructionSet(), 0,
Andreas Gampe79273802014-08-05 20:21:05 -07001063 oat_data_size, oat_data_size, oat_exec_size,
1064 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
1065 debug);
Alex Light78382fa2014-06-06 15:45:32 -07001066
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001067 if (!builder.Init()) {
1068 return false;
1069 }
1070
Andreas Gampe79273802014-08-05 20:21:05 -07001071 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001072 WriteDebugSymbols(&builder, oat_writer);
Brian Carlstromb12f3472014-06-11 14:54:46 -07001073 }
1074
Alex Light53cb16b2014-06-12 11:26:29 -07001075 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
1076 ElfRawSectionBuilder oat_patches(".oat_patches", SHT_OAT_PATCH, 0, NULL, 0,
Alex Light4b0d2d92014-08-06 13:37:23 -07001077 sizeof(uintptr_t), sizeof(uintptr_t));
Alex Light53cb16b2014-06-12 11:26:29 -07001078 ReservePatchSpace(oat_patches.GetBuffer(), debug);
1079 builder.RegisterRawSection(oat_patches);
1080 }
1081
Brian Carlstromb12f3472014-06-11 14:54:46 -07001082 return builder.Write();
1083}
Mark Mendellae9fd932014-02-10 16:14:35 -08001084
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001085template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
1086 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
1087 typename Elf_Phdr, typename Elf_Shdr>
1088void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
1089 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::WriteDebugSymbols(ElfBuilder* builder, OatWriter* oat_writer) {
Andreas Gampe79273802014-08-05 20:21:05 -07001090 std::unique_ptr<std::vector<uint8_t>> cfi_info(
1091 ConstructCIEFrame(compiler_driver_->GetInstructionSet()));
1092
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001093 Elf_Addr text_section_address = builder->text_builder_.section_.sh_addr;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001094
Andreas Gampe79273802014-08-05 20:21:05 -07001095 // Iterate over the compiled methods.
Alex Light78382fa2014-06-06 15:45:32 -07001096 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001097 ElfSymtabBuilder* symtab = &builder->symtab_builder_;
Alex Light78382fa2014-06-06 15:45:32 -07001098 for (auto it = method_info.begin(); it != method_info.end(); ++it) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001099 symtab->AddSymbol(it->method_name_, &builder->text_builder_, it->low_pc_, true,
Alex Light78382fa2014-06-06 15:45:32 -07001100 it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
Andreas Gampe79273802014-08-05 20:21:05 -07001101
1102 // Include CFI for compiled method, if possible.
1103 if (cfi_info.get() != nullptr) {
1104 DCHECK(it->compiled_method_ != nullptr);
1105
1106 // Copy in the FDE, if present
1107 const std::vector<uint8_t>* fde = it->compiled_method_->GetCFIInfo();
1108 if (fde != nullptr) {
1109 // Copy the information into cfi_info and then fix the address in the new copy.
1110 int cur_offset = cfi_info->size();
1111 cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
1112
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001113 bool is_64bit = *(reinterpret_cast<const uint32_t*>(fde->data())) == 0xffffffff;
Andreas Gampe79273802014-08-05 20:21:05 -07001114
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001115 // Set the 'CIE_pointer' field.
1116 uint64_t CIE_pointer = cur_offset + (is_64bit ? 12 : 4);
1117 uint64_t offset_to_update = CIE_pointer;
1118 if (is_64bit) {
1119 (*cfi_info)[offset_to_update+0] = CIE_pointer;
1120 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1121 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1122 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1123 (*cfi_info)[offset_to_update+4] = CIE_pointer >> 32;
1124 (*cfi_info)[offset_to_update+5] = CIE_pointer >> 40;
1125 (*cfi_info)[offset_to_update+6] = CIE_pointer >> 48;
1126 (*cfi_info)[offset_to_update+7] = CIE_pointer >> 56;
1127 } else {
1128 (*cfi_info)[offset_to_update+0] = CIE_pointer;
1129 (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1130 (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1131 (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1132 }
1133
1134 // Set the 'initial_location' field.
1135 offset_to_update += is_64bit ? 8 : 4;
1136 if (is_64bit) {
1137 const uint64_t quick_code_start = it->low_pc_ + text_section_address;
1138 (*cfi_info)[offset_to_update+0] = quick_code_start;
1139 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1140 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1141 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1142 (*cfi_info)[offset_to_update+4] = quick_code_start >> 32;
1143 (*cfi_info)[offset_to_update+5] = quick_code_start >> 40;
1144 (*cfi_info)[offset_to_update+6] = quick_code_start >> 48;
1145 (*cfi_info)[offset_to_update+7] = quick_code_start >> 56;
1146 } else {
1147 const uint32_t quick_code_start = it->low_pc_ + text_section_address;
1148 (*cfi_info)[offset_to_update+0] = quick_code_start;
1149 (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1150 (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1151 (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1152 }
Andreas Gampe79273802014-08-05 20:21:05 -07001153 }
1154 }
Alex Light78382fa2014-06-06 15:45:32 -07001155 }
Alex Light78382fa2014-06-06 15:45:32 -07001156
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001157 bool hasCFI = (cfi_info.get() != nullptr);
1158 bool hasLineInfo = false;
1159 for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
1160 if (dbg_info.dbgstream_ != nullptr &&
1161 !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
1162 hasLineInfo = true;
1163 break;
1164 }
1165 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001166
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001167 if (hasLineInfo || hasCFI) {
1168 ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1169 ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1170 ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1171 ElfRawSectionBuilder debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1172
1173 FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
1174 debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
1175 hasLineInfo ? debug_line.GetBuffer() : nullptr,
1176 text_section_address);
1177
1178 builder->RegisterRawSection(debug_info);
1179 builder->RegisterRawSection(debug_abbrev);
1180
1181 if (hasCFI) {
1182 ElfRawSectionBuilder eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
1183 eh_frame.SetBuffer(std::move(*cfi_info.get()));
1184 builder->RegisterRawSection(eh_frame);
1185 }
1186
1187 if (hasLineInfo) {
1188 builder->RegisterRawSection(debug_line);
1189 }
1190
1191 builder->RegisterRawSection(debug_str);
1192 }
1193}
1194
1195class LineTableGenerator FINAL : public Leb128Encoder {
1196 public:
1197 LineTableGenerator(int line_base, int line_range, int opcode_base,
1198 std::vector<uint8_t>* data, uintptr_t current_address,
1199 size_t current_line)
1200 : Leb128Encoder(data), line_base_(line_base), line_range_(line_range),
1201 opcode_base_(opcode_base), current_address_(current_address),
1202 current_line_(current_line) {}
1203
1204 void PutDelta(unsigned delta_addr, int delta_line) {
1205 current_line_ += delta_line;
1206 current_address_ += delta_addr;
1207
1208 if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) {
1209 unsigned special_opcode = (delta_line - line_base_) +
1210 (line_range_ * delta_addr) + opcode_base_;
1211 if (special_opcode <= 255) {
1212 PushByte(data_, special_opcode);
1213 return;
1214 }
1215 }
1216
1217 // generate standart opcode for address advance
1218 if (delta_addr != 0) {
1219 PushByte(data_, DW_LNS_advance_pc);
1220 PushBackUnsigned(delta_addr);
1221 }
1222
1223 // generate standart opcode for line delta
1224 if (delta_line != 0) {
1225 PushByte(data_, DW_LNS_advance_line);
1226 PushBackSigned(delta_line);
1227 }
1228
1229 // generate standart opcode for new LTN entry
1230 PushByte(data_, DW_LNS_copy);
1231 }
1232
1233 void SetAddr(uintptr_t addr) {
1234 if (current_address_ == addr) {
1235 return;
1236 }
1237
1238 current_address_ = addr;
1239
1240 PushByte(data_, 0); // extended opcode:
1241 PushByte(data_, 1 + 4); // length: opcode_size + address_size
1242 PushByte(data_, DW_LNE_set_address);
1243 PushWord(data_, addr);
1244 }
1245
1246 void SetLine(unsigned line) {
1247 int delta_line = line - current_line_;
1248 if (delta_line) {
1249 current_line_ = line;
1250 PushByte(data_, DW_LNS_advance_line);
1251 PushBackSigned(delta_line);
1252 }
1253 }
1254
1255 void SetFile(unsigned file_index) {
1256 PushByte(data_, DW_LNS_set_file);
1257 PushBackUnsigned(file_index);
1258 }
1259
1260 void EndSequence() {
1261 // End of Line Table Program
1262 // 0(=ext), 1(len), DW_LNE_end_sequence
1263 PushByte(data_, 0);
1264 PushByte(data_, 1);
1265 PushByte(data_, DW_LNE_end_sequence);
1266 }
1267
1268 private:
1269 const int line_base_;
1270 const int line_range_;
1271 const int opcode_base_;
1272 uintptr_t current_address_;
1273 size_t current_line_;
1274
1275 DISALLOW_COPY_AND_ASSIGN(LineTableGenerator);
1276};
1277
1278// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
1279static void GetLineInfoForJava(const uint8_t* dbgstream, const SrcMap& pc2dex,
1280 SrcMap* result, uint32_t start_pc = 0) {
1281 if (dbgstream == nullptr) {
1282 return;
1283 }
1284
1285 int adjopcode;
1286 uint32_t dex_offset = 0;
1287 uint32_t java_line = DecodeUnsignedLeb128(&dbgstream);
1288
1289 // skip parameters
1290 for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) {
1291 DecodeUnsignedLeb128(&dbgstream);
1292 }
1293
1294 for (bool is_end = false; is_end == false; ) {
1295 uint8_t opcode = *dbgstream;
1296 dbgstream++;
1297 switch (opcode) {
1298 case DexFile::DBG_END_SEQUENCE:
1299 is_end = true;
1300 break;
1301
1302 case DexFile::DBG_ADVANCE_PC:
1303 dex_offset += DecodeUnsignedLeb128(&dbgstream);
1304 break;
1305
1306 case DexFile::DBG_ADVANCE_LINE:
1307 java_line += DecodeSignedLeb128(&dbgstream);
1308 break;
1309
1310 case DexFile::DBG_START_LOCAL:
1311 case DexFile::DBG_START_LOCAL_EXTENDED:
1312 DecodeUnsignedLeb128(&dbgstream);
1313 DecodeUnsignedLeb128(&dbgstream);
1314 DecodeUnsignedLeb128(&dbgstream);
1315
1316 if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) {
1317 DecodeUnsignedLeb128(&dbgstream);
1318 }
1319 break;
1320
1321 case DexFile::DBG_END_LOCAL:
1322 case DexFile::DBG_RESTART_LOCAL:
1323 DecodeUnsignedLeb128(&dbgstream);
1324 break;
1325
1326 case DexFile::DBG_SET_PROLOGUE_END:
1327 case DexFile::DBG_SET_EPILOGUE_BEGIN:
1328 case DexFile::DBG_SET_FILE:
1329 break;
1330
1331 default:
1332 adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
1333 dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
1334 java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
1335
1336 for (SrcMap::const_iterator found = pc2dex.FindByTo(dex_offset);
1337 found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset);
1338 found++) {
1339 result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)});
1340 }
1341 break;
1342 }
Andreas Gampe79273802014-08-05 20:21:05 -07001343 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001344}
1345
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001346template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
1347 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
1348 typename Elf_Phdr, typename Elf_Shdr>
1349void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
1350 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::FillInCFIInformation(OatWriter* oat_writer,
Mark Mendellae9fd932014-02-10 16:14:35 -08001351 std::vector<uint8_t>* dbg_info,
1352 std::vector<uint8_t>* dbg_abbrev,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001353 std::vector<uint8_t>* dbg_str,
1354 std::vector<uint8_t>* dbg_line,
1355 uint32_t text_section_offset) {
1356 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
1357
1358 uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
1359
Mark Mendellae9fd932014-02-10 16:14:35 -08001360 // Create the debug_abbrev section with boilerplate information.
1361 // We only care about low_pc and high_pc right now for the compilation
1362 // unit and methods.
1363
1364 // Tag 1: Compilation unit: DW_TAG_compile_unit.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001365 PushByte(dbg_abbrev, 1);
1366 PushByte(dbg_abbrev, DW_TAG_compile_unit);
Mark Mendellae9fd932014-02-10 16:14:35 -08001367
1368 // There are children (the methods).
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001369 PushByte(dbg_abbrev, DW_CHILDREN_yes);
1370
1371 // DW_AT_producer DW_FORM_data1.
1372 // REVIEW: we can get rid of dbg_str section if
1373 // DW_FORM_string (immediate string) was used everywhere instead of
1374 // DW_FORM_strp (ref to string from .debug_str section).
1375 // DW_FORM_strp makes sense only if we reuse the strings.
1376 PushByte(dbg_abbrev, DW_AT_producer);
1377 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -08001378
1379 // DW_LANG_Java DW_FORM_data1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001380 PushByte(dbg_abbrev, DW_AT_language);
1381 PushByte(dbg_abbrev, DW_FORM_data1);
Mark Mendellae9fd932014-02-10 16:14:35 -08001382
1383 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001384 PushByte(dbg_abbrev, DW_AT_low_pc);
1385 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001386
1387 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001388 PushByte(dbg_abbrev, DW_AT_high_pc);
1389 PushByte(dbg_abbrev, DW_FORM_addr);
1390
1391 if (dbg_line != nullptr) {
1392 // DW_AT_stmt_list DW_FORM_sec_offset.
1393 PushByte(dbg_abbrev, DW_AT_stmt_list);
1394 PushByte(dbg_abbrev, DW_FORM_sec_offset);
1395 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001396
1397 // End of DW_TAG_compile_unit.
1398 PushHalf(dbg_abbrev, 0);
1399
1400 // Tag 2: Compilation unit: DW_TAG_subprogram.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001401 PushByte(dbg_abbrev, 2);
1402 PushByte(dbg_abbrev, DW_TAG_subprogram);
Mark Mendellae9fd932014-02-10 16:14:35 -08001403
1404 // There are no children.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001405 PushByte(dbg_abbrev, DW_CHILDREN_no);
Mark Mendellae9fd932014-02-10 16:14:35 -08001406
1407 // Name of the method.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001408 PushByte(dbg_abbrev, DW_AT_name);
1409 PushByte(dbg_abbrev, DW_FORM_strp);
Mark Mendellae9fd932014-02-10 16:14:35 -08001410
1411 // DW_AT_low_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001412 PushByte(dbg_abbrev, DW_AT_low_pc);
1413 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001414
1415 // DW_AT_high_pc DW_FORM_addr.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001416 PushByte(dbg_abbrev, DW_AT_high_pc);
1417 PushByte(dbg_abbrev, DW_FORM_addr);
Mark Mendellae9fd932014-02-10 16:14:35 -08001418
1419 // End of DW_TAG_subprogram.
1420 PushHalf(dbg_abbrev, 0);
1421
1422 // Start the debug_info section with the header information
1423 // 'unit_length' will be filled in later.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001424 int cunit_length = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -08001425 PushWord(dbg_info, 0);
1426
1427 // 'version' - 3.
1428 PushHalf(dbg_info, 3);
1429
1430 // Offset into .debug_abbrev section (always 0).
1431 PushWord(dbg_info, 0);
1432
1433 // Address size: 4.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001434 PushByte(dbg_info, 4);
Mark Mendellae9fd932014-02-10 16:14:35 -08001435
1436 // Start the description for the compilation unit.
1437 // This uses tag 1.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001438 PushByte(dbg_info, 1);
1439
1440 // The producer is Android dex2oat.
1441 PushWord(dbg_info, producer_str_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -08001442
1443 // The language is Java.
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001444 PushByte(dbg_info, DW_LANG_Java);
Mark Mendellae9fd932014-02-10 16:14:35 -08001445
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001446 // low_pc and high_pc.
1447 uint32_t cunit_low_pc = 0 - 1;
1448 uint32_t cunit_high_pc = 0;
1449 int cunit_low_pc_pos = dbg_info->size();
Mark Mendellae9fd932014-02-10 16:14:35 -08001450 PushWord(dbg_info, 0);
1451 PushWord(dbg_info, 0);
1452
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001453 if (dbg_line == nullptr) {
1454 for (size_t i = 0; i < method_info.size(); ++i) {
1455 const OatWriter::DebugInfo &dbg = method_info[i];
Mark Mendellae9fd932014-02-10 16:14:35 -08001456
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001457 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1458 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1459
1460 // Start a new TAG: subroutine (2).
1461 PushByte(dbg_info, 2);
1462
1463 // Enter name, low_pc, high_pc.
1464 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1465 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1466 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -08001467 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001468 } else {
1469 // TODO: in gdb info functions <regexp> - reports Java functions, but
1470 // source file is <unknown> because .debug_line is formed as one
1471 // compilation unit. To fix this it is possible to generate
1472 // a separate compilation unit for every distinct Java source.
1473 // Each of the these compilation units can have several non-adjacent
1474 // method ranges.
1475
1476 // Line number table offset
1477 PushWord(dbg_info, dbg_line->size());
1478
1479 size_t lnt_length = dbg_line->size();
1480 PushWord(dbg_line, 0);
1481
1482 PushHalf(dbg_line, 4); // LNT Version DWARF v4 => 4
1483
1484 size_t lnt_hdr_length = dbg_line->size();
1485 PushWord(dbg_line, 0); // TODO: 64-bit uses 8-byte here
1486
1487 PushByte(dbg_line, 1); // minimum_instruction_length (ubyte)
1488 PushByte(dbg_line, 1); // maximum_operations_per_instruction (ubyte) = always 1
1489 PushByte(dbg_line, 1); // default_is_stmt (ubyte)
1490
1491 const int8_t LINE_BASE = -5;
1492 PushByte(dbg_line, LINE_BASE); // line_base (sbyte)
1493
1494 const uint8_t LINE_RANGE = 14;
1495 PushByte(dbg_line, LINE_RANGE); // line_range (ubyte)
1496
1497 const uint8_t OPCODE_BASE = 13;
1498 PushByte(dbg_line, OPCODE_BASE); // opcode_base (ubyte)
1499
1500 // Standard_opcode_lengths (array of ubyte).
1501 PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1);
1502 PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0);
1503 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1504 PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1505
1506 PushByte(dbg_line, 0); // include_directories (sequence of path names) = EMPTY
1507
1508 // File_names (sequence of file entries).
1509 std::unordered_map<const char*, size_t> files;
1510 for (size_t i = 0; i < method_info.size(); ++i) {
1511 const OatWriter::DebugInfo &dbg = method_info[i];
1512 // TODO: add package directory to the file name
1513 const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_;
1514 auto found = files.find(file_name);
1515 if (found == files.end()) {
1516 size_t file_index = 1 + files.size();
1517 files[file_name] = file_index;
1518 PushStr(dbg_line, file_name);
1519 PushByte(dbg_line, 0); // include directory index = LEB128(0) - no directory
1520 PushByte(dbg_line, 0); // modification time = LEB128(0) - NA
1521 PushByte(dbg_line, 0); // file length = LEB128(0) - NA
1522 }
1523 }
1524 PushByte(dbg_line, 0); // End of file_names.
1525
1526 // Set lnt header length.
1527 UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4);
1528
1529 // Generate Line Number Program code, one long program for all methods.
1530 LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE,
1531 dbg_line, 0, 1);
1532
1533 SrcMap pc2java_map;
1534 for (size_t i = 0; i < method_info.size(); ++i) {
1535 const OatWriter::DebugInfo &dbg = method_info[i];
1536 const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_;
1537 size_t file_index = files[file_name];
1538 DCHECK_NE(file_index, 0U) << file_name;
1539
1540 cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1541 cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1542
1543 // Start a new TAG: subroutine (2).
1544 PushByte(dbg_info, 2);
1545
1546 // Enter name, low_pc, high_pc.
1547 PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1548 PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1549 PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
1550
1551 pc2java_map.clear();
1552 GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(),
1553 &pc2java_map, dbg.low_pc_);
1554 pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_);
1555
1556 line_table_generator.SetFile(file_index);
1557 line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset);
1558 line_table_generator.SetLine(1);
1559 for (auto& src_map_elem : pc2java_map) {
1560 line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_);
1561 }
Mark Mendellae9fd932014-02-10 16:14:35 -08001562 }
1563
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001564 // End Sequence should have the highest address set.
1565 line_table_generator.SetAddr(cunit_high_pc + text_section_offset);
1566 line_table_generator.EndSequence();
Mark Mendellae9fd932014-02-10 16:14:35 -08001567
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001568 // set lnt length
1569 UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4);
Mark Mendellae9fd932014-02-10 16:14:35 -08001570 }
1571
1572 // One byte terminator
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001573 PushByte(dbg_info, 0);
Mark Mendellae9fd932014-02-10 16:14:35 -08001574
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001575 // Fill in cunit's low_pc and high_pc.
1576 UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset);
1577 UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset);
1578
1579 // We have now walked all the methods. Fill in lengths.
1580 UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001581}
1582
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +00001583// Explicit instantiations
1584template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
1585 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>;
1586template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
1587 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>;
1588
Brian Carlstrom7940e442013-07-12 13:46:57 -07001589} // namespace art