elf_writer_quick.cc revision e3ea83811d47152c00abea24a9b420651a33b496
16a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom/*
26a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Copyright (C) 2012 The Android Open Source Project
36a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
46a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
56a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * you may not use this file except in compliance with the License.
66a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * You may obtain a copy of the License at
76a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
86a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
96a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * See the License for the specific language governing permissions and
146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * limitations under the License.
156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom */
166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "elf_writer_quick.h"
186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
19e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban#include <unordered_map>
20e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
216a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "base/logging.h"
226a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "base/unix_file/fd_file.h"
23c6dfdacea2fd9e268f70328805b0366cdd6b7b9eBrian Carlstrom#include "buffered_output_stream.h"
247940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "driver/compiler_driver.h"
253470ab4011b5e18d590d5375e2f13a1e3bd69222Alex Light#include "dwarf.h"
26e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban#include "elf_file.h"
2750cfe74daaece80853cb3b45d4338329b7d0345bNicolas Geoffray#include "elf_utils.h"
28c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom#include "file_output_stream.h"
296a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "globals.h"
3079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe#include "leb128.h"
316a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "oat.h"
32c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom#include "oat_writer.h"
336a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "utils.h"
346a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromnamespace art {
366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
37b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromstatic constexpr Elf32_Word NextOffset(const Elf32_Shdr& cur, const Elf32_Shdr& prev) {
38b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
39ad13cb2db8c4a64298ed85c82ae7366ee73f7640Alex Light}
40ad13cb2db8c4a64298ed85c82ae7366ee73f7640Alex Light
41b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromstatic uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
42b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return ((binding) << 4) + ((type) & 0xf);
43b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
44b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
45e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic void PushByte(std::vector<uint8_t>* buf, int data) {
46e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  buf->push_back(data & 0xff);
47e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban}
48e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
49e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic uint32_t PushStr(std::vector<uint8_t>* buf, const char* str, const char* def = nullptr) {
50e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (str == nullptr) {
51e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    str = def;
52e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
53e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
54e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uint32_t offset = buf->size();
55e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  for (size_t i = 0; str[i] != '\0'; ++i) {
56e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    buf->push_back(str[i]);
57e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
58e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  buf->push_back('\0');
59e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  return offset;
60e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban}
61e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
62e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic uint32_t PushStr(std::vector<uint8_t>* buf, const std::string &str) {
63e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uint32_t offset = buf->size();
64e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  buf->insert(buf->end(), str.begin(), str.end());
65e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  buf->push_back('\0');
66e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  return offset;
67e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban}
68e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
6979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestatic void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) {
7079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  (*buf)[offset+0] = data;
7179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  (*buf)[offset+1] = data >> 8;
7279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  (*buf)[offset+2] = data >> 16;
7379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  (*buf)[offset+3] = data >> 24;
7479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe}
7579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
7679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestatic void PushHalf(std::vector<uint8_t>* buf, int data) {
7779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  buf->push_back(data & 0xff);
7879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  buf->push_back((data >> 8) & 0xff);
7979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe}
8079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
81e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanbool ElfWriterQuick::ElfBuilder::Init() {
82b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // The basic layout of the elf file. Order may be different in final output.
836a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
846a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Ehdr              |
856a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
866a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Phdr PHDR         |
876a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Phdr LOAD R       | .dynsym .dynstr .hash .rodata
886a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Phdr LOAD R X     | .text
896a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Phdr LOAD RW      | .dynamic
906a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Phdr DYNAMIC      | .dynamic
916a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
926a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .dynsym                 |
936a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Sym  STN_UNDEF    |
946a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Sym  oatdata      |
956a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Sym  oatexec      |
966a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Sym  oatlastword  |
976a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
986a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .dynstr                 |
996a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | \0                      |
1006a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | oatdata\0               |
1016a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | oatexec\0               |
1026a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | oatlastword\0           |
1036a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | boot.oat\0              |
1046a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
1056a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .hash                   |
106b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | Elf32_Word nbucket = b  |
107b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | Elf32_Word nchain  = c  |
108b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | Elf32_Word bucket[0]    |
109b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // |         ...             |
110b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | Elf32_Word bucket[b - 1]|
111b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | Elf32_Word chain[0]     |
112b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // |         ...             |
113b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | Elf32_Word chain[c - 1] |
1146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
1156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .rodata                 |
1166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | oatdata..oatexec-4      |
1176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
1186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .text                   |
1196a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | oatexec..oatlastword    |
1206a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
1216a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .dynamic                |
1226a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Dyn DT_SONAME     |
1236a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Dyn DT_HASH       |
1246a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Dyn DT_SYMTAB     |
1256a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Dyn DT_SYMENT     |
1266a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Dyn DT_STRTAB     |
1276a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Dyn DT_STRSZ      |
1286a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Dyn DT_NULL       |
129b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // +-------------------------+  (Optional)
130b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .strtab                 |  (Optional)
131b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | program symbol names    |  (Optional)
132b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // +-------------------------+  (Optional)
133b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .symtab                 |  (Optional)
134b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | program symbols         |  (Optional)
1356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
1366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .shstrtab               |
1376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | \0                      |
1386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .dynamic\0              |
1396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .dynsym\0               |
1406a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .dynstr\0               |
1416a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .hash\0                 |
1426a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .rodata\0               |
1436a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .text\0                 |
1446a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | .shstrtab\0             |
145b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .symtab\0               |  (Optional)
146b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .strtab\0               |  (Optional)
147b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .debug_str\0            |  (Optional)
148b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .debug_info\0           |  (Optional)
14935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen  // | .eh_frame\0             |  (Optional)
150e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // | .debug_line\0           |  (Optional)
151b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .debug_abbrev\0         |  (Optional)
152b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // +-------------------------+  (Optional)
153b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | .debug_info             |  (Optional)
154b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // +-------------------------+  (Optional)
155e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // | .debug_abbrev           |  (Optional)
156e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // +-------------------------+  (Optional)
15735e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen  // | .eh_frame               |  (Optional)
158b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // +-------------------------+  (Optional)
159e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // | .debug_line             |  (Optional)
160e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // +-------------------------+  (Optional)
161e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // | .debug_str              |  (Optional)
162e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // +-------------------------+  (Optional)
1636a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr NULL         |
1646a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr .dynsym      |
1656a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr .dynstr      |
1666a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr .hash        |
1676a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr .text        |
1686a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr .rodata      |
1696a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr .dynamic     |
1706a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // | Elf32_Shdr .shstrtab    |
171ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // | Elf32_Shdr .debug_info  |  (Optional)
172b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | Elf32_Shdr .debug_abbrev|  (Optional)
173e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // | Elf32_Shdr .eh_frame    |  (Optional)
174e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // | Elf32_Shdr .debug_line  |  (Optional)
175e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // | Elf32_Shdr .debug_str   |  (Optional)
1766a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // +-------------------------+
1776a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
178b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (fatal_error_) {
179b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    return false;
180b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
181b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Step 1. Figure out all the offsets.
1826a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
183b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (debug_logging_) {
184e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
185e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
1866a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
187e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
188e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  memset(&program_headers_, 0, sizeof(program_headers_));
189e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_type    = PT_PHDR;
190e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_offset  = PHDR_OFFSET;
191e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_vaddr   = PHDR_OFFSET;
192e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_paddr   = PHDR_OFFSET;
193e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_filesz  = sizeof(program_headers_);
194e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_memsz   = sizeof(program_headers_);
195e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_flags   = PF_R;
196e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_PHDR].p_align   = sizeof(Elf32_Word);
197e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
198e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_type    = PT_LOAD;
199e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_offset  = 0;
200e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_vaddr   = 0;
201e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_paddr   = 0;
202e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_flags   = PF_R;
203e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
204e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_type    = PT_LOAD;
205e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_flags   = PF_R | PF_X;
206e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
207e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_type    = PT_LOAD;
208e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_flags   = PF_R | PF_W;
209e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
210e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_type    = PT_DYNAMIC;
211e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_flags   = PF_R | PF_W;
2126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
213b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the dynstr string.
214e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynstr_ = dynsym_builder_.GenerateStrtab();
215b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
216b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Add the SONAME to the dynstr.
217e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynstr_soname_offset_ = dynstr_.size();
218b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::string file_name(elf_file_->GetPath());
219b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  size_t directory_separator_pos = file_name.rfind('/');
220b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (directory_separator_pos != std::string::npos) {
221b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    file_name = file_name.substr(directory_separator_pos + 1);
222b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
223e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynstr_ += file_name;
224e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynstr_ += '\0';
225b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (debug_logging_) {
226e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "dynstr size (bytes)   =" << dynstr_.size()
227e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << std::hex << " " << dynstr_.size();
2288758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom    LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
2298758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom              << std::hex << " " << dynsym_builder_.GetSize();
230b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
231b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
232b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the section header string table.
233e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  shstrtab_ += '\0';
2346a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
235b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup sym_undef
236e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  memset(&null_hdr_, 0, sizeof(null_hdr_));
237e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  null_hdr_.sh_type = SHT_NULL;
238e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  null_hdr_.sh_link = SHN_UNDEF;
239e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&null_hdr_);
240b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
241e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_index_ = 1;
242b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
243b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // setup .dynsym
244e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&dynsym_builder_.section_);
245e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  AssignSectionStr(&dynsym_builder_, &shstrtab_);
246e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynsym_builder_.section_index_ = section_index_++;
247b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
248b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup .dynstr
249e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&dynsym_builder_.strtab_.section_);
250e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  AssignSectionStr(&dynsym_builder_.strtab_, &shstrtab_);
251e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynsym_builder_.strtab_.section_index_ = section_index_++;
252b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
253b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup .hash
254e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&hash_builder_.section_);
255e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  AssignSectionStr(&hash_builder_, &shstrtab_);
256e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  hash_builder_.section_index_ = section_index_++;
257b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
258b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup .rodata
259e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&rodata_builder_.section_);
260e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  AssignSectionStr(&rodata_builder_, &shstrtab_);
261e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  rodata_builder_.section_index_ = section_index_++;
262b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
263b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup .text
264e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&text_builder_.section_);
265e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  AssignSectionStr(&text_builder_, &shstrtab_);
266e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  text_builder_.section_index_ = section_index_++;
267b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
268b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup .dynamic
269e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&dynamic_builder_.section_);
270e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  AssignSectionStr(&dynamic_builder_, &shstrtab_);
271e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynamic_builder_.section_index_ = section_index_++;
272b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
273b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Fill in the hash section.
274e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  hash_ = dynsym_builder_.GenerateHashContents();
275b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
276b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (debug_logging_) {
277e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf32_Word)
278e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << std::hex << " " << hash_.size() * sizeof(Elf32_Word);
279b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
280b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
281e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  Elf32_Word base_offset = sizeof(Elf32_Ehdr) + sizeof(program_headers_);
282b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
283b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout in the sections.
284b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //
285b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the dynsym section.
286b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign);
287b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset;
2888758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom  dynsym_builder_.section_.sh_size = dynsym_builder_.GetSize() * sizeof(Elf32_Sym);
289b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink();
290b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
291b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the dynstr section.
292b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.strtab_.section_.sh_offset = NextOffset(dynsym_builder_.strtab_.section_,
293b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                                          dynsym_builder_.section_);
294b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.strtab_.section_.sh_addr = dynsym_builder_.strtab_.section_.sh_offset;
295e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  dynsym_builder_.strtab_.section_.sh_size = dynstr_.size();
296b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.strtab_.section_.sh_link = dynsym_builder_.strtab_.GetLink();
297b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
298b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the hash section
299b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  hash_builder_.section_.sh_offset = NextOffset(hash_builder_.section_,
300b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                                dynsym_builder_.strtab_.section_);
301b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset;
302e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  hash_builder_.section_.sh_size = hash_.size() * sizeof(Elf32_Word);
303b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  hash_builder_.section_.sh_link = hash_builder_.GetLink();
304b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
305b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the rodata section.
306b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  rodata_builder_.section_.sh_offset = NextOffset(rodata_builder_.section_,
307b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                                  hash_builder_.section_);
308b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset;
309b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  rodata_builder_.section_.sh_size = rodata_builder_.size_;
310b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  rodata_builder_.section_.sh_link = rodata_builder_.GetLink();
311b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
312b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the text section.
313b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  text_builder_.section_.sh_offset = NextOffset(text_builder_.section_, rodata_builder_.section_);
314b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  text_builder_.section_.sh_addr = text_builder_.section_.sh_offset;
315b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  text_builder_.section_.sh_size = text_builder_.size_;
316b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  text_builder_.section_.sh_link = text_builder_.GetLink();
317b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize);
318b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
319b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the dynamic section.
320b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamic_builder_.section_.sh_offset = NextOffset(dynamic_builder_.section_,
321b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                                   text_builder_.section_);
322b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset;
3238758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom  dynamic_builder_.section_.sh_size = dynamic_builder_.GetSize() * sizeof(Elf32_Dyn);
324b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink();
325b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
326e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (debug_logging_) {
327e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset
328e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << " dynsym size=" << dynsym_builder_.section_.sh_size;
329e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "dynstr off=" << dynsym_builder_.strtab_.section_.sh_offset
330e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << " dynstr size=" << dynsym_builder_.strtab_.section_.sh_size;
331e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset
332e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << " hash size=" << hash_builder_.section_.sh_size;
333e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset
334e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << " rodata size=" << rodata_builder_.section_.sh_size;
335e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "text off=" << text_builder_.section_.sh_offset
336e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << " text size=" << text_builder_.section_.sh_size;
337e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset
338e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << " dynamic size=" << dynamic_builder_.section_.sh_size;
339e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
340e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
341e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  return true;
342e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban}
343e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
344e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanbool ElfWriterQuick::ElfBuilder::Write() {
345e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  std::vector<ElfFilePiece> pieces;
346b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Shdr prev = dynamic_builder_.section_;
347e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  std::string strtab;
348e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
349e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (IncludingDebugSymbols()) {
350e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // Setup .symtab
351e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    section_ptrs_.push_back(&symtab_builder_.section_);
352e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    AssignSectionStr(&symtab_builder_, &shstrtab_);
353e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    symtab_builder_.section_index_ = section_index_++;
354e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
355e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // Setup .strtab
356e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    section_ptrs_.push_back(&symtab_builder_.strtab_.section_);
357e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    AssignSectionStr(&symtab_builder_.strtab_, &shstrtab_);
358e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    symtab_builder_.strtab_.section_index_ = section_index_++;
359e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
360e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    strtab = symtab_builder_.GenerateStrtab();
361e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (debug_logging_) {
362e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      LOG(INFO) << "strtab size (bytes)    =" << strtab.size()
363e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                << std::hex << " " << strtab.size();
364e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
365e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                << std::hex << " " << symtab_builder_.GetSize();
366e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
367e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
368e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
369e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // Setup all the other sections.
370e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  for (ElfRawSectionBuilder *builder = other_builders_.data(),
371e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                            *end = builder + other_builders_.size();
372e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban       builder != end; ++builder) {
373e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    section_ptrs_.push_back(&builder->section_);
374e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    AssignSectionStr(builder, &shstrtab_);
375e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    builder->section_index_ = section_index_++;
376e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
377e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
378e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // Setup shstrtab
379e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  section_ptrs_.push_back(&shstrtab_builder_.section_);
380e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  AssignSectionStr(&shstrtab_builder_, &shstrtab_);
381e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  shstrtab_builder_.section_index_ = section_index_++;
382e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
383e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (debug_logging_) {
384e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << ".shstrtab size    (bytes)   =" << shstrtab_.size()
385e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << std::hex << " " << shstrtab_.size();
386e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
387e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban              << std::hex << " " << section_ptrs_.size();
388e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
389e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
390b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (IncludingDebugSymbols()) {
391b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // Get the layout of the symtab section.
392b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab_builder_.section_.sh_offset = NextOffset(symtab_builder_.section_,
393b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                                    dynamic_builder_.section_);
394b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab_builder_.section_.sh_addr = 0;
395b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // Add to leave space for the null symbol.
3968758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom    symtab_builder_.section_.sh_size = symtab_builder_.GetSize() * sizeof(Elf32_Sym);
397b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab_builder_.section_.sh_link = symtab_builder_.GetLink();
398b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
399b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // Get the layout of the dynstr section.
400b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab_builder_.strtab_.section_.sh_offset = NextOffset(symtab_builder_.strtab_.section_,
401b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                                            symtab_builder_.section_);
402b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab_builder_.strtab_.section_.sh_addr = 0;
403b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab_builder_.strtab_.section_.sh_size = strtab.size();
404b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab_builder_.strtab_.section_.sh_link = symtab_builder_.strtab_.GetLink();
405b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
406b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    prev = symtab_builder_.strtab_.section_;
407e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (debug_logging_) {
408b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset
409b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                << " symtab size=" << symtab_builder_.section_.sh_size;
410b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      LOG(INFO) << "strtab off=" << symtab_builder_.strtab_.section_.sh_offset
411b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                << " strtab size=" << symtab_builder_.strtab_.section_.sh_size;
412b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    }
4136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
414e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
415b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the extra sections. (This will deal with the debug
416b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // sections if they are there)
417b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
418b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    it->section_.sh_offset = NextOffset(it->section_, prev);
419b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    it->section_.sh_addr = 0;
420b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    it->section_.sh_size = it->GetBuffer()->size();
421b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    it->section_.sh_link = it->GetLink();
422b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    pieces.push_back(ElfFilePiece(it->name_, it->section_.sh_offset,
423b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                  it->GetBuffer()->data(), it->GetBuffer()->size()));
424b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    prev = it->section_;
425b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    if (debug_logging_) {
426b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset
427b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                << " " << it->name_ << " size=" << it->section_.sh_size;
428b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    }
4296a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
430e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
431b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Get the layout of the shstrtab section
432b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  shstrtab_builder_.section_.sh_offset = NextOffset(shstrtab_builder_.section_, prev);
433b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  shstrtab_builder_.section_.sh_addr = 0;
434e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  shstrtab_builder_.section_.sh_size = shstrtab_.size();
435b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink();
436b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (debug_logging_) {
437b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset
438b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                << " shstrtab size=" << shstrtab_builder_.section_.sh_size;
439b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
440b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
441b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // The section list comes after come after.
442b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word sections_offset = RoundUp(
443b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size,
444b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      sizeof(Elf32_Word));
445b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
446b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup the actual symbol arrays.
447b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::vector<Elf32_Sym> dynsym = dynsym_builder_.GenerateSymtab();
4488758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom  CHECK_EQ(dynsym.size() * sizeof(Elf32_Sym), dynsym_builder_.section_.sh_size);
449b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::vector<Elf32_Sym> symtab;
450b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (IncludingDebugSymbols()) {
451b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    symtab = symtab_builder_.GenerateSymtab();
4528758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom    CHECK_EQ(symtab.size() * sizeof(Elf32_Sym), symtab_builder_.section_.sh_size);
453b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
454b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
455b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Setup the dynamic section.
456b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // This will add the 2 values we cannot know until now time, namely the size
457b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // and the soname_offset.
458e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  std::vector<Elf32_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
459e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                                                dynstr_soname_offset_);
4608758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom  CHECK_EQ(dynamic.size() * sizeof(Elf32_Dyn), dynamic_builder_.section_.sh_size);
461b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
462b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Finish setup of the program headers now that we know the layout of the
463b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // whole file.
464b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size;
465e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
466e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_memsz =  load_r_size;
467e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R__].p_align =  rodata_builder_.section_.sh_addralign;
468b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
469b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word load_rx_size = text_builder_.section_.sh_size;
470e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset;
471e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_vaddr  = text_builder_.section_.sh_offset;
472e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_paddr  = text_builder_.section_.sh_offset;
473e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
474e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_memsz  = load_rx_size;
475e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_R_X].p_align  = text_builder_.section_.sh_addralign;
476e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
477e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset;
478e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_vaddr  = dynamic_builder_.section_.sh_offset;
479e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_paddr  = dynamic_builder_.section_.sh_offset;
480e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size;
481e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_memsz  = dynamic_builder_.section_.sh_size;
482e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_LOAD_RW_].p_align  = dynamic_builder_.section_.sh_addralign;
483e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
484e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset;
485e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_vaddr  = dynamic_builder_.section_.sh_offset;
486e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_paddr  = dynamic_builder_.section_.sh_offset;
487e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size;
488e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_memsz  = dynamic_builder_.section_.sh_size;
489e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  program_headers_[PH_DYNAMIC].p_align  = dynamic_builder_.section_.sh_addralign;
490b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
491b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Finish setup of the Ehdr values.
492e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  elf_header_.e_phoff = PHDR_OFFSET;
493b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_shoff = sections_offset;
494b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_phnum = PH_NUM;
495e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  elf_header_.e_shnum = section_ptrs_.size();
496b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_shstrndx = shstrtab_builder_.section_index_;
497b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
498b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Add the rest of the pieces to the list.
499b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece("Elf Header", 0, &elf_header_, sizeof(elf_header_)));
500e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  pieces.push_back(ElfFilePiece("Program headers", PHDR_OFFSET,
501e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                &program_headers_, sizeof(program_headers_)));
502b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece(".dynamic", dynamic_builder_.section_.sh_offset,
503b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                dynamic.data(), dynamic_builder_.section_.sh_size));
504b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece(".dynsym", dynsym_builder_.section_.sh_offset,
5058758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom                                dynsym.data(), dynsym.size() * sizeof(Elf32_Sym)));
506b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece(".dynstr", dynsym_builder_.strtab_.section_.sh_offset,
507e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                dynstr_.c_str(), dynstr_.size()));
508b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece(".hash", hash_builder_.section_.sh_offset,
509e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                hash_.data(), hash_.size() * sizeof(Elf32_Word)));
510b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece(".rodata", rodata_builder_.section_.sh_offset,
5113470ab4011b5e18d590d5375e2f13a1e3bd69222Alex Light                                nullptr, rodata_builder_.section_.sh_size));
512b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece(".text", text_builder_.section_.sh_offset,
5133470ab4011b5e18d590d5375e2f13a1e3bd69222Alex Light                                nullptr, text_builder_.section_.sh_size));
514b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (IncludingDebugSymbols()) {
515b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    pieces.push_back(ElfFilePiece(".symtab", symtab_builder_.section_.sh_offset,
516b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                  symtab.data(), symtab.size() * sizeof(Elf32_Sym)));
517b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    pieces.push_back(ElfFilePiece(".strtab", symtab_builder_.strtab_.section_.sh_offset,
518b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                  strtab.c_str(), strtab.size()));
519b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
520b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  pieces.push_back(ElfFilePiece(".shstrtab", shstrtab_builder_.section_.sh_offset,
521e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                &shstrtab_[0], shstrtab_.size()));
522e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
523b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // Just add all the sections in induvidually since they are all over the
524b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // place on the heap/stack.
525b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    Elf32_Word cur_off = sections_offset + i * sizeof(Elf32_Shdr);
526b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    pieces.push_back(ElfFilePiece("section table piece", cur_off,
527e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                  section_ptrs_[i], sizeof(Elf32_Shdr)));
528b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
529b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
530b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (!WriteOutFile(pieces)) {
531b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
5326a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return false;
5336a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
534b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // write out the actual oat file data.
535b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word oat_data_offset = rodata_builder_.section_.sh_offset;
536b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (static_cast<off_t>(oat_data_offset) != lseek(elf_file_->Fd(), oat_data_offset, SEEK_SET)) {
537b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    PLOG(ERROR) << "Failed to seek to .rodata offset " << oat_data_offset
5386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                << " for " << elf_file_->GetPath();
5396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return false;
5406a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
541b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::unique_ptr<BufferedOutputStream> output_stream(
542b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      new BufferedOutputStream(new FileOutputStream(elf_file_)));
543b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (!oat_writer_->Write(output_stream.get())) {
544b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file_->GetPath();
5456a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return false;
5466a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
5476a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
548b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return true;
549b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
5506a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
551b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrombool ElfWriterQuick::ElfBuilder::WriteOutFile(const std::vector<ElfFilePiece>& pieces) {
552b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // TODO It would be nice if this checked for overlap.
553b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  for (auto it = pieces.begin(); it != pieces.end(); ++it) {
554b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    if (it->data_) {
555b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      if (static_cast<off_t>(it->offset_) != lseek(elf_file_->Fd(), it->offset_, SEEK_SET)) {
556b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom        PLOG(ERROR) << "Failed to seek to " << it->dbg_name_ << " offset location "
557b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                    << it->offset_ << " for " << elf_file_->GetPath();
558b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom        return false;
559b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      }
560b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      if (!elf_file_->WriteFully(it->data_, it->size_)) {
561b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom        PLOG(ERROR) << "Failed to write " << it->dbg_name_ << " for " << elf_file_->GetPath();
562b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom        return false;
563b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      }
564b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    }
5656a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
566b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return true;
567b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
568b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
569b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromvoid ElfWriterQuick::ElfBuilder::SetupDynamic() {
570b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
571b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, &dynsym_builder_.strtab_);
572b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
573b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf32_Sym));
574b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
575b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
576b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromvoid ElfWriterQuick::ElfBuilder::SetupRequiredSymbols() {
577b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
578b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            rodata_builder_.size_, STB_GLOBAL, STT_OBJECT);
579b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
580b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            text_builder_.size_, STB_GLOBAL, STT_OBJECT);
581b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.size_ - 4,
582b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            true, 4, STB_GLOBAL, STT_OBJECT);
583b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
584b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
5858758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstromvoid ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un) {
586b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (tag == DT_NULL) {
587b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    return;
5886a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
5893470ab4011b5e18d590d5375e2f13a1e3bd69222Alex Light  dynamics_.push_back({nullptr, tag, d_un});
590b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
5916a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
5928758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstromvoid ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un,
593b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                                      ElfSectionBuilder* section) {
594b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (tag == DT_NULL) {
595b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    return;
5966a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
597b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  dynamics_.push_back({section, tag, d_un});
598b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
599b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
6008758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstromstd::vector<Elf32_Dyn> ElfWriterQuick::ElfDynamicBuilder::GetDynamics(Elf32_Word strsz,
6018758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom                                                                      Elf32_Word soname) {
602b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::vector<Elf32_Dyn> ret;
603b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
604b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    if (it->section_) {
605b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      // We are adding an address relative to a section.
606b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      ret.push_back(
6078758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom          {it->tag_, {it->off_ + it->section_->section_.sh_addr}});
608b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    } else {
609b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      ret.push_back({it->tag_, {it->off_}});
610b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    }
6116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
612b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ret.push_back({DT_STRSZ, {strsz}});
613b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ret.push_back({DT_SONAME, {soname}});
614b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ret.push_back({DT_NULL, {0}});
615b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return ret;
616b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
6176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
618b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromstd::vector<Elf32_Sym> ElfWriterQuick::ElfSymtabBuilder::GenerateSymtab() {
619b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::vector<Elf32_Sym> ret;
620b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Sym undef_sym;
621b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  memset(&undef_sym, 0, sizeof(undef_sym));
622b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  undef_sym.st_shndx = SHN_UNDEF;
623b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ret.push_back(undef_sym);
624b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
625b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
626b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    Elf32_Sym sym;
627b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    memset(&sym, 0, sizeof(sym));
628b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    sym.st_name = it->name_idx_;
629b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    if (it->is_relative_) {
630b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      sym.st_value = it->addr_ + it->section_->section_.sh_offset;
631b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    } else {
632b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      sym.st_value = it->addr_;
633b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    }
634b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    sym.st_size = it->size_;
635b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    sym.st_other = it->other_;
636b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    sym.st_shndx = it->section_->section_index_;
637b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    sym.st_info = it->info_;
638b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
639b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    ret.push_back(sym);
6406a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
641b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return ret;
642b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
643b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
644b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromstd::string ElfWriterQuick::ElfSymtabBuilder::GenerateStrtab() {
645b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::string tab;
646b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  tab += '\0';
647b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
648b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    it->name_idx_ = tab.size();
649b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    tab += it->name_;
650b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    tab += '\0';
6516a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
652b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  strtab_.section_.sh_size = tab.size();
653b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return tab;
654b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
6556a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
656b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromvoid ElfWriterQuick::ElfBuilder::AssignSectionStr(
657b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    ElfSectionBuilder* builder, std::string* strtab) {
658b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  builder->section_.sh_name = strtab->size();
659b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  *strtab += builder->name_;
660b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  *strtab += '\0';
661b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (debug_logging_) {
662b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    LOG(INFO) << "adding section name \"" << builder->name_ << "\" "
663b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom              << "to shstrtab at offset " << builder->section_.sh_name;
66435f72251e722cad03a08e8ceacbd5c244eab5c29Brian Carlstrom  }
665b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
666b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
667b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom// from bionic
668b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromstatic unsigned elfhash(const char *_name) {
669b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  const unsigned char *name = (const unsigned char *) _name;
670b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  unsigned h = 0, g;
671b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
672b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  while (*name) {
673b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    h = (h << 4) + *name++;
674b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    g = h & 0xf0000000;
675b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    h ^= g;
676b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    h ^= g >> 24;
677ad13cb2db8c4a64298ed85c82ae7366ee73f7640Alex Light  }
678b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return h;
679b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
680ad13cb2db8c4a64298ed85c82ae7366ee73f7640Alex Light
681b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
682b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromstd::vector<Elf32_Word> ElfWriterQuick::ElfSymtabBuilder::GenerateHashContents() {
683b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Here is how The ELF hash table works.
684b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // There are 3 arrays to worry about.
685b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // * The symbol table where the symbol information is.
686b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // * The bucket array which is an array of indexes into the symtab and chain.
687b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // * The chain array which is also an array of indexes into the symtab and chain.
688b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //
689b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Lets say the state is something like this.
690b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // +--------+       +--------+      +-----------+
691b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | symtab |       | bucket |      |   chain   |
692e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // |  null  |       | 1      |      | STN_UNDEF |
693b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | <sym1> |       | 4      |      | 2         |
694b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | <sym2> |       |        |      | 5         |
695b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | <sym3> |       |        |      | STN_UNDEF |
696b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | <sym4> |       |        |      | 3         |
697b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // | <sym5> |       |        |      | STN_UNDEF |
698b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // +--------+       +--------+      +-----------+
699b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //
700b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // The lookup process (in python psudocode) is
701b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //
702b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // def GetSym(name):
703b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //     # NB STN_UNDEF == 0
704b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //     indx = bucket[elfhash(name) % num_buckets]
705b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //     while indx != STN_UNDEF:
706b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //         if GetSymbolName(symtab[indx]) == name:
707b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //             return symtab[indx]
708b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //         indx = chain[indx]
709b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //     return SYMBOL_NOT_FOUND
710b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  //
711b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Between bucket and chain arrays every symtab index must be present exactly
712b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
713b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
714b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Select number of buckets.
715b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // This is essentially arbitrary.
716b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word nbuckets;
7178758c64a40e74ebb492a348556ec7b25a89c1491Brian Carlstrom  Elf32_Word chain_size = GetSize();
718b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  if (symbols_.size() < 8) {
719b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    nbuckets = 2;
720b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  } else if (symbols_.size() < 32) {
721b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    nbuckets = 4;
722b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  } else if (symbols_.size() < 256) {
723b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    nbuckets = 16;
724b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  } else {
725b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // Have about 32 ids per bucket.
726b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    nbuckets = RoundUp(symbols_.size()/32, 2);
727b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
728b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  std::vector<Elf32_Word> hash;
729b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  hash.push_back(nbuckets);
730b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  hash.push_back(chain_size);
731b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  uint32_t bucket_offset = hash.size();
732b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  uint32_t chain_offset = bucket_offset + nbuckets;
733b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  hash.resize(hash.size() + nbuckets + chain_size, 0);
734b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
735b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word* buckets = hash.data() + bucket_offset;
736b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word* chain   = hash.data() + chain_offset;
737b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
738b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  // Set up the actual hash table.
739b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  for (Elf32_Word i = 0; i < symbols_.size(); i++) {
740b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // Add 1 since we need to have the null symbol that is not in the symbols
741b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    // list.
742b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    Elf32_Word index = i + 1;
743b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    Elf32_Word hash_val = static_cast<Elf32_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
744b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    if (buckets[hash_val] == 0) {
745b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      buckets[hash_val] = index;
746b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    } else {
747b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      hash_val = buckets[hash_val];
748b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      CHECK_LT(hash_val, chain_size);
749b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      while (chain[hash_val] != 0) {
750b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom        hash_val = chain[hash_val];
751b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom        CHECK_LT(hash_val, chain_size);
752b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      }
753b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      chain[hash_val] = index;
754b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      // Check for loops. Works because if this is non-empty then there must be
755b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      // another cell which already contains the same symbol index as this one,
756b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      // which means some symbol has more then one name, which isn't allowed.
757b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      CHECK_EQ(chain[index], static_cast<Elf32_Word>(0));
75835f72251e722cad03a08e8ceacbd5c244eab5c29Brian Carlstrom    }
759b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  }
760b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
761b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return hash;
762b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
763b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
764b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromvoid ElfWriterQuick::ElfBuilder::SetupEhdr() {
765b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  memset(&elf_header_, 0, sizeof(elf_header_));
766b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_MAG0]       = ELFMAG0;
767b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_MAG1]       = ELFMAG1;
768b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_MAG2]       = ELFMAG2;
769b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_MAG3]       = ELFMAG3;
770b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_CLASS]      = ELFCLASS32;
771b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_DATA]       = ELFDATA2LSB;
772b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_VERSION]    = EV_CURRENT;
773b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_OSABI]      = ELFOSABI_LINUX;
774b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ident[EI_ABIVERSION] = 0;
775b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_type = ET_DYN;
776b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_version = 1;
777b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_entry = 0;
778b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_ehsize = sizeof(Elf32_Ehdr);
779b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_phentsize = sizeof(Elf32_Phdr);
780b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_shentsize = sizeof(Elf32_Shdr);
781b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  elf_header_.e_phoff = sizeof(Elf32_Ehdr);
782b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
783ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
784b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromvoid ElfWriterQuick::ElfBuilder::SetISA(InstructionSet isa) {
785b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  switch (isa) {
786b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    case kArm:
787b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      // Fall through.
788b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    case kThumb2: {
789b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_machine = EM_ARM;
790b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_flags = EF_ARM_EABI_VER5;
791b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      break;
792ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
793b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    case kArm64: {
794b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_machine = EM_AARCH64;
795b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_flags = 0;
796b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      break;
797ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
798b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    case kX86: {
799b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_machine = EM_386;
800b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_flags = 0;
801b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      break;
802ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
803b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    case kX86_64: {
804b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_machine = EM_X86_64;
805b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_flags = 0;
806b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      break;
807ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
808b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    case kMips: {
809b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_machine = EM_MIPS;
810b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      elf_header_.e_flags = (EF_MIPS_NOREORDER |
811b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                             EF_MIPS_PIC       |
812b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                             EF_MIPS_CPIC      |
813b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                             EF_MIPS_ABI_O32   |
814b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                             EF_MIPS_ARCH_32R2);
815b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      break;
816ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
817b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    default: {
818b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      fatal_error_ = true;
819b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      LOG(FATAL) << "Unknown instruction set: " << isa;
820b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom      break;
821ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
822ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
823b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
824ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
825b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstromvoid ElfWriterQuick::ElfSymtabBuilder::AddSymbol(
826b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    const std::string& name, const ElfSectionBuilder* section, Elf32_Addr addr,
827b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom    bool is_relative, Elf32_Word size, uint8_t binding, uint8_t type, uint8_t other) {
828b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  CHECK(section);
829b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
830b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                                          MakeStInfo(binding, type), other, 0};
831b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  symbols_.push_back(state);
832b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
833b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
834b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrombool ElfWriterQuick::Create(File* elf_file,
835b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            OatWriter* oat_writer,
836b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            const std::vector<const DexFile*>& dex_files,
837b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            const std::string& android_root,
838b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            bool is_host,
839b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                            const CompilerDriver& driver) {
840b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ElfWriterQuick elf_writer(driver, elf_file);
841b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
842b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
843b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
84453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light// Add patch information to this section. Each patch is a Elf32_Word that
84553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light// identifies an offset from the start of the text section
84653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid ElfWriterQuick::ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug) {
84753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  size_t size =
84853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light      compiler_driver_->GetCodeToPatch().size() +
84953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light      compiler_driver_->GetMethodsToPatch().size() +
85053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light      compiler_driver_->GetClassesToPatch().size();
85153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (size == 0) {
85253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    if (debug) {
85353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light      LOG(INFO) << "No patches to record";
85453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    }
85553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    return;
85653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
85753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  buffer->resize(size * sizeof(uintptr_t));
85853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (debug) {
85953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    LOG(INFO) << "Patches reserved for " << size;
86053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
86153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light}
86253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light
86379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestd::vector<uint8_t>* ConstructCIEFrameX86(bool is_x86_64) {
864e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>;
86579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
86679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Length (will be filled in later in this routine).
867e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (is_x86_64) {
868e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(cfi_info, 0xffffffff);  // Indicates 64bit
869e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(cfi_info, 0);
870e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(cfi_info, 0);
871e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  } else {
872e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(cfi_info, 0);
873e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
87479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
87579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // CIE id: always 0.
876e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (is_x86_64) {
877e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(cfi_info, 0);
878e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(cfi_info, 0);
879e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  } else {
880e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(cfi_info, 0);
881e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
88279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
88379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Version: always 1.
88479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  cfi_info->push_back(0x01);
88579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
88679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Augmentation: 'zR\0'
88779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  cfi_info->push_back(0x7a);
88879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  cfi_info->push_back(0x52);
88979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  cfi_info->push_back(0x0);
89079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
89179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Code alignment: 1.
89279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  EncodeUnsignedLeb128(1, cfi_info);
89379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
89479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Data alignment.
89579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  if (is_x86_64) {
89679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    EncodeSignedLeb128(-8, cfi_info);
89779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  } else {
89879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    EncodeSignedLeb128(-4, cfi_info);
89979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  }
90079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
90179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Return address register.
90279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  if (is_x86_64) {
90379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // R16(RIP)
90479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x10);
90579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  } else {
90679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // R8(EIP)
90779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x08);
90879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  }
90979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
91079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Augmentation length: 1.
91179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  cfi_info->push_back(1);
91279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
913e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // Augmentation data.
914e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (is_x86_64) {
915e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // 0x04 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
916e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    cfi_info->push_back(0x04);
917e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  } else {
918e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
919e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    cfi_info->push_back(0x03);
920e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
92179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
92279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Initial instructions.
92379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  if (is_x86_64) {
92479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // DW_CFA_def_cfa R7(RSP) 8.
92579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x0c);
92679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x07);
92779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x08);
92879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
92979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // DW_CFA_offset R16(RIP) 1 (* -8).
93079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x90);
93179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x01);
93279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  } else {
93379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // DW_CFA_def_cfa R4(ESP) 4.
93479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x0c);
93579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x04);
93679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x04);
93779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
93879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // DW_CFA_offset R8(EIP) 1 (* -4).
93979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x88);
94079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0x01);
94179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  }
94279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
94379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Padding to a multiple of 4
94479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  while ((cfi_info->size() & 3) != 0) {
94579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // DW_CFA_nop is encoded as 0.
94679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    cfi_info->push_back(0);
94779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  }
94879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
94979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Set the length of the CIE inside the generated bytes.
950e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (is_x86_64) {
951e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    uint32_t length = cfi_info->size() - 12;
952e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    UpdateWord(cfi_info, 4, length);
953e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  } else {
954e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    uint32_t length = cfi_info->size() - 4;
955e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    UpdateWord(cfi_info, 0, length);
956e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
95779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  return cfi_info;
95879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe}
95979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
96079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestd::vector<uint8_t>* ConstructCIEFrame(InstructionSet isa) {
96179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  switch (isa) {
96279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    case kX86:
96379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      return ConstructCIEFrameX86(false);
96479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    case kX86_64:
96579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      return ConstructCIEFrameX86(true);
96679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
96779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    default:
96879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      // Not implemented.
96979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      return nullptr;
97079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  }
97179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe}
97279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
973b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrombool ElfWriterQuick::Write(OatWriter* oat_writer,
974b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                           const std::vector<const DexFile*>& dex_files_unused,
975b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                           const std::string& android_root_unused,
976b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom                           bool is_host_unused) {
97779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  constexpr bool debug = false;
978b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  const OatHeader& oat_header = oat_writer->GetOatHeader();
979b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  Elf32_Word oat_data_size = oat_header.GetExecutableOffset();
980b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
981b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
982b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ElfBuilder builder(oat_writer, elf_file_, compiler_driver_->GetInstructionSet(), 0,
98379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe                     oat_data_size, oat_data_size, oat_exec_size,
98479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe                     compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
98579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe                     debug);
98678382fa44ee505cf16835e4d22515e7252a90864Alex Light
987e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (!builder.Init()) {
988e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    return false;
989e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
990e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
99179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
992e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    WriteDebugSymbols(&builder, oat_writer);
9936a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
9946a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
99553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
99653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    ElfRawSectionBuilder oat_patches(".oat_patches", SHT_OAT_PATCH, 0, NULL, 0,
9974b0d2d99b596eebd6da45679896d3af54bc5a935Alex Light                                     sizeof(uintptr_t), sizeof(uintptr_t));
99853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    ReservePatchSpace(oat_patches.GetBuffer(), debug);
99953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    builder.RegisterRawSection(oat_patches);
100053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
100153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light
1002b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return builder.Write();
1003b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
1004ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1005e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanvoid ElfWriterQuick::WriteDebugSymbols(ElfBuilder* builder, OatWriter* oat_writer) {
100679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  std::unique_ptr<std::vector<uint8_t>> cfi_info(
100779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      ConstructCIEFrame(compiler_driver_->GetInstructionSet()));
100879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
1009e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  Elf32_Addr text_section_address = builder->text_builder_.section_.sh_addr;
1010e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
101179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  // Iterate over the compiled methods.
101278382fa44ee505cf16835e4d22515e7252a90864Alex Light  const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
1013e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  ElfSymtabBuilder* symtab = &builder->symtab_builder_;
101478382fa44ee505cf16835e4d22515e7252a90864Alex Light  for (auto it = method_info.begin(); it != method_info.end(); ++it) {
1015e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    symtab->AddSymbol(it->method_name_, &builder->text_builder_, it->low_pc_, true,
101678382fa44ee505cf16835e4d22515e7252a90864Alex Light                      it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
101778382fa44ee505cf16835e4d22515e7252a90864Alex Light
101879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    // Include CFI for compiled method, if possible.
101979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    if (cfi_info.get() != nullptr) {
102079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      DCHECK(it->compiled_method_ != nullptr);
102179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
102279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      // Copy in the FDE, if present
102379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      const std::vector<uint8_t>* fde = it->compiled_method_->GetCFIInfo();
102479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      if (fde != nullptr) {
102579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe        // Copy the information into cfi_info and then fix the address in the new copy.
102679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe        int cur_offset = cfi_info->size();
102779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe        cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
102879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe
1029e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        bool is_64bit = *(reinterpret_cast<const uint32_t*>(fde->data())) == 0xffffffff;
1030e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1031e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        // Set the 'CIE_pointer' field.
1032e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        uint64_t CIE_pointer = cur_offset + (is_64bit ? 12 : 4);
1033e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        uint64_t offset_to_update = CIE_pointer;
1034e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        if (is_64bit) {
1035e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+0] = CIE_pointer;
1036e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1037e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1038e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1039e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+4] = CIE_pointer >> 32;
1040e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+5] = CIE_pointer >> 40;
1041e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+6] = CIE_pointer >> 48;
1042e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+7] = CIE_pointer >> 56;
1043e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        } else {
1044e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+0] = CIE_pointer;
1045e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
1046e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
1047e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
1048e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        }
1049e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1050e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        // Set the 'initial_location' field.
1051e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        offset_to_update += is_64bit ? 8 : 4;
1052e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        if (is_64bit) {
1053e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          const uint64_t quick_code_start = it->low_pc_ + text_section_address;
1054e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+0] = quick_code_start;
1055e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1056e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1057e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1058e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+4] = quick_code_start >> 32;
1059e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+5] = quick_code_start >> 40;
1060e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+6] = quick_code_start >> 48;
1061e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+7] = quick_code_start >> 56;
1062e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        } else {
1063e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          const uint32_t quick_code_start = it->low_pc_ + text_section_address;
1064e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+0] = quick_code_start;
1065e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
1066e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
1067e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
1068e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        }
106979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe      }
107079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    }
107179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  }
1072ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1073e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  bool hasCFI = (cfi_info.get() != nullptr);
1074e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  bool hasLineInfo = false;
1075e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) {
1076e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (dbg_info.dbgstream_ != nullptr &&
1077e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        !dbg_info.compiled_method_->GetSrcMappingTable().empty()) {
1078e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      hasLineInfo = true;
1079e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1080e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1081e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1082e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1083e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (hasLineInfo || hasCFI) {
1084e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    ElfRawSectionBuilder debug_info(".debug_info",     SHT_PROGBITS, 0, nullptr, 0, 1, 0);
108579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe    ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1086e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    ElfRawSectionBuilder debug_str(".debug_str",       SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1087e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    ElfRawSectionBuilder debug_line(".debug_line",     SHT_PROGBITS, 0, nullptr, 0, 1, 0);
1088e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1089e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
1090e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                         debug_abbrev.GetBuffer(), debug_str.GetBuffer(),
1091e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                         hasLineInfo ? debug_line.GetBuffer() : nullptr,
1092e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                         text_section_address);
1093e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1094e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    builder->RegisterRawSection(debug_info);
1095e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    builder->RegisterRawSection(debug_abbrev);
1096e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1097e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (hasCFI) {
1098e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      ElfRawSectionBuilder eh_frame(".eh_frame",  SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
1099e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      eh_frame.SetBuffer(std::move(*cfi_info.get()));
1100e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      builder->RegisterRawSection(eh_frame);
1101e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1102e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1103e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (hasLineInfo) {
1104e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      builder->RegisterRawSection(debug_line);
1105e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1106e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1107e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    builder->RegisterRawSection(debug_str);
1108e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1109e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban}
1110e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1111e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanclass LineTableGenerator FINAL : public Leb128Encoder {
1112e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban public:
1113e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  LineTableGenerator(int line_base, int line_range, int opcode_base,
1114e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                     std::vector<uint8_t>* data, uintptr_t current_address,
1115e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                     size_t current_line)
1116e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    : Leb128Encoder(data), line_base_(line_base), line_range_(line_range),
1117e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      opcode_base_(opcode_base), current_address_(current_address),
1118e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      current_line_(current_line) {}
1119e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1120e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  void PutDelta(unsigned delta_addr, int delta_line) {
1121e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    current_line_ += delta_line;
1122e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    current_address_ += delta_addr;
1123e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1124e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) {
1125e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      unsigned special_opcode = (delta_line - line_base_) +
1126e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                (line_range_ * delta_addr) + opcode_base_;
1127e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      if (special_opcode <= 255) {
1128e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        PushByte(data_, special_opcode);
1129e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        return;
1130e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      }
1131e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1132e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1133e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // generate standart opcode for address advance
1134e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (delta_addr != 0) {
1135e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushByte(data_, DW_LNS_advance_pc);
1136e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushBackUnsigned(delta_addr);
1137e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1138e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1139e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // generate standart opcode for line delta
1140e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (delta_line != 0) {
1141e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushByte(data_, DW_LNS_advance_line);
1142e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushBackSigned(delta_line);
1143e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1144e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1145e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // generate standart opcode for new LTN entry
1146e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, DW_LNS_copy);
1147e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1148e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1149e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  void SetAddr(uintptr_t addr) {
1150e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (current_address_ == addr) {
1151e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      return;
1152e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1153e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1154e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    current_address_ = addr;
1155e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1156e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, 0);  // extended opcode:
1157e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, 1 + 4);  // length: opcode_size + address_size
1158e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, DW_LNE_set_address);
1159e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(data_, addr);
1160e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1161e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1162e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  void SetLine(unsigned line) {
1163e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    int delta_line = line - current_line_;
1164e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    if (delta_line) {
1165e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      current_line_ = line;
1166e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushByte(data_, DW_LNS_advance_line);
1167e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushBackSigned(delta_line);
1168e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1169e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1170e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1171e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  void SetFile(unsigned file_index) {
1172e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, DW_LNS_set_file);
1173e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushBackUnsigned(file_index);
1174e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1175e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1176e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  void EndSequence() {
1177e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // End of Line Table Program
1178e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // 0(=ext), 1(len), DW_LNE_end_sequence
1179e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, 0);
1180e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, 1);
1181e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(data_, DW_LNE_end_sequence);
1182e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1183e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1184e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban private:
1185e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  const int line_base_;
1186e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  const int line_range_;
1187e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  const int opcode_base_;
1188e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uintptr_t current_address_;
1189e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  size_t current_line_;
1190e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1191e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  DISALLOW_COPY_AND_ASSIGN(LineTableGenerator);
1192e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban};
1193e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1194e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
1195e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic void GetLineInfoForJava(const uint8_t* dbgstream, const SrcMap& pc2dex,
1196e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                               SrcMap* result, uint32_t start_pc = 0) {
1197e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (dbgstream == nullptr) {
1198e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    return;
1199e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1200e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1201e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  int adjopcode;
1202e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uint32_t dex_offset = 0;
1203e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uint32_t java_line = DecodeUnsignedLeb128(&dbgstream);
1204e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1205e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // skip parameters
1206e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) {
1207e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    DecodeUnsignedLeb128(&dbgstream);
1208e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1209e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1210e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  for (bool is_end = false; is_end == false; ) {
1211e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    uint8_t opcode = *dbgstream;
1212e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    dbgstream++;
1213e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    switch (opcode) {
1214e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_END_SEQUENCE:
1215e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      is_end = true;
1216e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1217e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1218e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_ADVANCE_PC:
1219e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      dex_offset += DecodeUnsignedLeb128(&dbgstream);
1220e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1221e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1222e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_ADVANCE_LINE:
1223e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      java_line += DecodeSignedLeb128(&dbgstream);
1224e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1225e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1226e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_START_LOCAL:
1227e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_START_LOCAL_EXTENDED:
1228e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      DecodeUnsignedLeb128(&dbgstream);
1229e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      DecodeUnsignedLeb128(&dbgstream);
1230e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      DecodeUnsignedLeb128(&dbgstream);
1231e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1232e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) {
1233e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        DecodeUnsignedLeb128(&dbgstream);
1234e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      }
1235e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1236e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1237e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_END_LOCAL:
1238e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_RESTART_LOCAL:
1239e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      DecodeUnsignedLeb128(&dbgstream);
1240e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1241e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1242e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_SET_PROLOGUE_END:
1243e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_SET_EPILOGUE_BEGIN:
1244e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    case DexFile::DBG_SET_FILE:
1245e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1246e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1247e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    default:
1248e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
1249e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
1250e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
1251e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1252e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      for (SrcMap::const_iterator found = pc2dex.FindByTo(dex_offset);
1253e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset);
1254e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban          found++) {
1255e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)});
1256e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      }
1257e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      break;
1258e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
125979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe  }
1260ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1261ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1262ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellvoid ElfWriterQuick::FillInCFIInformation(OatWriter* oat_writer,
1263ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell                                          std::vector<uint8_t>* dbg_info,
1264ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell                                          std::vector<uint8_t>* dbg_abbrev,
1265e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                          std::vector<uint8_t>* dbg_str,
1266e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                          std::vector<uint8_t>* dbg_line,
1267e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                          uint32_t text_section_offset) {
1268e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
1269e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1270e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
1271e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1272ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Create the debug_abbrev section with boilerplate information.
1273ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // We only care about low_pc and high_pc right now for the compilation
1274ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // unit and methods.
1275ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1276ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Tag 1: Compilation unit: DW_TAG_compile_unit.
1277e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, 1);
1278e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_TAG_compile_unit);
1279ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1280ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // There are children (the methods).
1281e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_CHILDREN_yes);
1282e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1283e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // DW_AT_producer DW_FORM_data1.
1284e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // REVIEW: we can get rid of dbg_str section if
1285e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // DW_FORM_string (immediate string) was used everywhere instead of
1286e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // DW_FORM_strp (ref to string from .debug_str section).
1287e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // DW_FORM_strp makes sense only if we reuse the strings.
1288e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_AT_producer);
1289e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_FORM_strp);
1290ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1291ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // DW_LANG_Java DW_FORM_data1.
1292e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_AT_language);
1293e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_FORM_data1);
1294ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1295ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // DW_AT_low_pc DW_FORM_addr.
1296e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_AT_low_pc);
1297e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_FORM_addr);
1298ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1299ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // DW_AT_high_pc DW_FORM_addr.
1300e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_AT_high_pc);
1301e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_FORM_addr);
1302e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1303e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (dbg_line != nullptr) {
1304e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // DW_AT_stmt_list DW_FORM_sec_offset.
1305e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_abbrev, DW_AT_stmt_list);
1306e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_abbrev, DW_FORM_sec_offset);
1307e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  }
1308ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1309ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // End of DW_TAG_compile_unit.
1310ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushHalf(dbg_abbrev, 0);
1311ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1312ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Tag 2: Compilation unit: DW_TAG_subprogram.
1313e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, 2);
1314e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_TAG_subprogram);
1315ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1316ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // There are no children.
1317e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_CHILDREN_no);
1318ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1319ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Name of the method.
1320e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_AT_name);
1321e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_FORM_strp);
1322ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1323ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // DW_AT_low_pc DW_FORM_addr.
1324e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_AT_low_pc);
1325e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_FORM_addr);
1326ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1327ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // DW_AT_high_pc DW_FORM_addr.
1328e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_AT_high_pc);
1329e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_abbrev, DW_FORM_addr);
1330ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1331ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // End of DW_TAG_subprogram.
1332ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushHalf(dbg_abbrev, 0);
1333ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1334ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Start the debug_info section with the header information
1335ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // 'unit_length' will be filled in later.
1336e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  int cunit_length = dbg_info->size();
1337ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(dbg_info, 0);
1338ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1339ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // 'version' - 3.
1340ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushHalf(dbg_info, 3);
1341ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1342ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Offset into .debug_abbrev section (always 0).
1343ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(dbg_info, 0);
1344ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1345ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Address size: 4.
1346e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_info, 4);
1347ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1348ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Start the description for the compilation unit.
1349ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // This uses tag 1.
1350e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_info, 1);
1351e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1352e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // The producer is Android dex2oat.
1353e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushWord(dbg_info, producer_str_offset);
1354ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1355ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // The language is Java.
1356e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_info, DW_LANG_Java);
1357ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1358e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // low_pc and high_pc.
1359e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uint32_t cunit_low_pc = 0 - 1;
1360e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  uint32_t cunit_high_pc = 0;
1361e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  int cunit_low_pc_pos = dbg_info->size();
1362ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(dbg_info, 0);
1363ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(dbg_info, 0);
1364ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1365e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  if (dbg_line == nullptr) {
1366e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    for (size_t i = 0; i < method_info.size(); ++i) {
1367e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      const OatWriter::DebugInfo &dbg = method_info[i];
1368e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1369e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1370e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1371e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1372e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      // Start a new TAG: subroutine (2).
1373e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushByte(dbg_info, 2);
1374ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1375e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      // Enter name, low_pc, high_pc.
1376e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1377e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1378e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
1379ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
1380e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  } else {
1381e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // TODO: in gdb info functions <regexp> - reports Java functions, but
1382e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // source file is <unknown> because .debug_line is formed as one
1383e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // compilation unit. To fix this it is possible to generate
1384e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // a separate compilation unit for every distinct Java source.
1385e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // Each of the these compilation units can have several non-adjacent
1386e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // method ranges.
1387e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1388e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // Line number table offset
1389e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(dbg_info, dbg_line->size());
1390e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1391e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    size_t lnt_length = dbg_line->size();
1392e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(dbg_line, 0);
1393e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1394e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushHalf(dbg_line, 4);  // LNT Version DWARF v4 => 4
1395e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1396e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    size_t lnt_hdr_length = dbg_line->size();
1397e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushWord(dbg_line, 0);  // TODO: 64-bit uses 8-byte here
1398e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1399e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 1);  // minimum_instruction_length (ubyte)
1400e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 1);  // maximum_operations_per_instruction (ubyte) = always 1
1401e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 1);  // default_is_stmt (ubyte)
1402e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1403e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    const int8_t LINE_BASE = -5;
1404e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, LINE_BASE);  // line_base (sbyte)
1405e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1406e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    const uint8_t LINE_RANGE = 14;
1407e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, LINE_RANGE);  // line_range (ubyte)
1408e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1409e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    const uint8_t OPCODE_BASE = 13;
1410e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, OPCODE_BASE);  // opcode_base (ubyte)
1411e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1412e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // Standard_opcode_lengths (array of ubyte).
1413e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1);
1414e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0);
1415e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1416e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
1417e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1418e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 0);  // include_directories (sequence of path names) = EMPTY
1419e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1420e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // File_names (sequence of file entries).
1421e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    std::unordered_map<const char*, size_t> files;
1422e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    for (size_t i = 0; i < method_info.size(); ++i) {
1423e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      const OatWriter::DebugInfo &dbg = method_info[i];
1424e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      // TODO: add package directory to the file name
1425e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_;
1426e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      auto found = files.find(file_name);
1427e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      if (found == files.end()) {
1428e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        size_t file_index = 1 + files.size();
1429e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        files[file_name] = file_index;
1430e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        PushStr(dbg_line, file_name);
1431e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        PushByte(dbg_line, 0);  // include directory index = LEB128(0) - no directory
1432e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        PushByte(dbg_line, 0);  // modification time = LEB128(0) - NA
1433e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        PushByte(dbg_line, 0);  // file length = LEB128(0) - NA
1434e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      }
1435e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    }
1436e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    PushByte(dbg_line, 0);  // End of file_names.
1437e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1438e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // Set lnt header length.
1439e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4);
1440e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1441e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // Generate Line Number Program code, one long program for all methods.
1442e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE,
1443e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                                            dbg_line, 0, 1);
1444e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1445e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    SrcMap pc2java_map;
1446e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    for (size_t i = 0; i < method_info.size(); ++i) {
1447e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      const OatWriter::DebugInfo &dbg = method_info[i];
1448e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_;
1449e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      size_t file_index = files[file_name];
1450e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      DCHECK_NE(file_index, 0U) << file_name;
1451e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1452e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
1453e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
1454e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1455e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      // Start a new TAG: subroutine (2).
1456e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushByte(dbg_info, 2);
1457e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1458e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      // Enter name, low_pc, high_pc.
1459e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_));
1460e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushWord(dbg_info, dbg.low_pc_ + text_section_offset);
1461e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      PushWord(dbg_info, dbg.high_pc_ + text_section_offset);
1462e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1463e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      pc2java_map.clear();
1464e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(),
1465e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban                         &pc2java_map, dbg.low_pc_);
1466e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_);
1467e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1468e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      line_table_generator.SetFile(file_index);
1469e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset);
1470e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      line_table_generator.SetLine(1);
1471e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      for (auto& src_map_elem : pc2java_map) {
1472e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban        line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_);
1473e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban      }
1474ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
1475ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1476e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // End Sequence should have the highest address set.
1477e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    line_table_generator.SetAddr(cunit_high_pc + text_section_offset);
1478e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    line_table_generator.EndSequence();
1479ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1480e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    // set lnt length
1481e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban    UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4);
1482ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1483ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1484ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // One byte terminator
1485e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  PushByte(dbg_info, 0);
1486e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
1487e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // Fill in cunit's low_pc and high_pc.
1488e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset);
1489e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset);
1490ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1491e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  // We have now walked all the methods.  Fill in lengths.
1492e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban  UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
14936a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
14946a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
14956a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}  // namespace art
1496