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