elf_writer_quick.cc revision 54fc26c7350beb782d042ba61cb06284b3a367e4
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" 2654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe#include "elf_builder.h" 27e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban#include "elf_file.h" 2850cfe74daaece80853cb3b45d4338329b7d0345bNicolas Geoffray#include "elf_utils.h" 29c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom#include "file_output_stream.h" 306a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "globals.h" 3179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe#include "leb128.h" 326a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "oat.h" 33c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom#include "oat_writer.h" 346a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "utils.h" 356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom 366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromnamespace art { 376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom 38e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic void PushByte(std::vector<uint8_t>* buf, int data) { 39e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban buf->push_back(data & 0xff); 40e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban} 41e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 42e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic uint32_t PushStr(std::vector<uint8_t>* buf, const char* str, const char* def = nullptr) { 43e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (str == nullptr) { 44e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban str = def; 45e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 46e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 47e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t offset = buf->size(); 48e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban for (size_t i = 0; str[i] != '\0'; ++i) { 49e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban buf->push_back(str[i]); 50e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 51e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban buf->push_back('\0'); 52e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return offset; 53e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban} 54e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 55e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic uint32_t PushStr(std::vector<uint8_t>* buf, const std::string &str) { 56e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t offset = buf->size(); 57e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban buf->insert(buf->end(), str.begin(), str.end()); 58e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban buf->push_back('\0'); 59e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return offset; 60e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban} 61e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 6279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestatic void UpdateWord(std::vector<uint8_t>* buf, int offset, int data) { 6379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe (*buf)[offset+0] = data; 6479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe (*buf)[offset+1] = data >> 8; 6579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe (*buf)[offset+2] = data >> 16; 6679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe (*buf)[offset+3] = data >> 24; 6779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe} 6879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 6979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestatic void PushHalf(std::vector<uint8_t>* buf, int data) { 7079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe buf->push_back(data & 0xff); 7179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe buf->push_back((data >> 8) & 0xff); 7279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe} 7379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 74f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffraytemplate <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 75f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 76f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray typename Elf_Phdr, typename Elf_Shdr> 77f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffraybool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 78f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Create(File* elf_file, 79b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom OatWriter* oat_writer, 80b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom const std::vector<const DexFile*>& dex_files, 81b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom const std::string& android_root, 82b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom bool is_host, 83b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom const CompilerDriver& driver) { 84b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom ElfWriterQuick elf_writer(driver, elf_file); 85b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom return elf_writer.Write(oat_writer, dex_files, android_root, is_host); 86b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom} 87b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom 88f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray// Add patch information to this section. Each patch is a Elf_Word that 8953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light// identifies an offset from the start of the text section 9054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampestatic void ReservePatchSpace(const CompilerDriver* compiler_driver, std::vector<uint8_t>* buffer, 9154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe bool debug) { 9253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light size_t size = 9354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe compiler_driver->GetCodeToPatch().size() + 9454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe compiler_driver->GetMethodsToPatch().size() + 9554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe compiler_driver->GetClassesToPatch().size(); 9653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (size == 0) { 9753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 9853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "No patches to record"; 9953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 10053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return; 10153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 10253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light buffer->resize(size * sizeof(uintptr_t)); 10353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (debug) { 10453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light LOG(INFO) << "Patches reserved for " << size; 10553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 10653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light} 10753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 10879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestd::vector<uint8_t>* ConstructCIEFrameX86(bool is_x86_64) { 109e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>; 11079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 11179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Length (will be filled in later in this routine). 112e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (is_x86_64) { 113e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(cfi_info, 0xffffffff); // Indicates 64bit 114e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(cfi_info, 0); 115e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(cfi_info, 0); 116e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } else { 117e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(cfi_info, 0); 118e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 11979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 12079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // CIE id: always 0. 121e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (is_x86_64) { 122e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(cfi_info, 0); 123e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(cfi_info, 0); 124e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } else { 125e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(cfi_info, 0); 126e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 12779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 12879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Version: always 1. 12979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x01); 13079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 13179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Augmentation: 'zR\0' 13279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x7a); 13379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x52); 13479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x0); 13579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 13679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Code alignment: 1. 13779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe EncodeUnsignedLeb128(1, cfi_info); 13879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 13979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Data alignment. 14079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe if (is_x86_64) { 14179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe EncodeSignedLeb128(-8, cfi_info); 14279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } else { 14379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe EncodeSignedLeb128(-4, cfi_info); 14479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } 14579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 14679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Return address register. 14779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe if (is_x86_64) { 14879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // R16(RIP) 14979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x10); 15079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } else { 15179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // R8(EIP) 15279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x08); 15379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } 15479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 15579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Augmentation length: 1. 15679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(1); 15779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 158e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Augmentation data. 159e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (is_x86_64) { 160e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // 0x04 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8). 161e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban cfi_info->push_back(0x04); 162e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } else { 163e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4). 164e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban cfi_info->push_back(0x03); 165e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 16679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 16779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Initial instructions. 16879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe if (is_x86_64) { 16979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // DW_CFA_def_cfa R7(RSP) 8. 17079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x0c); 17179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x07); 17279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x08); 17379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 17479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // DW_CFA_offset R16(RIP) 1 (* -8). 17579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x90); 17679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x01); 17779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } else { 17879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // DW_CFA_def_cfa R4(ESP) 4. 17979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x0c); 18079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x04); 18179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x04); 18279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 18379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // DW_CFA_offset R8(EIP) 1 (* -4). 18479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x88); 18579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0x01); 18679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } 18779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 18879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Padding to a multiple of 4 18979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe while ((cfi_info->size() & 3) != 0) { 19079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // DW_CFA_nop is encoded as 0. 19179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe cfi_info->push_back(0); 19279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } 19379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 19479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Set the length of the CIE inside the generated bytes. 195e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (is_x86_64) { 196e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t length = cfi_info->size() - 12; 197e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban UpdateWord(cfi_info, 4, length); 198e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } else { 199e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t length = cfi_info->size() - 4; 200e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban UpdateWord(cfi_info, 0, length); 201e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 20279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe return cfi_info; 20379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe} 20479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 20579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampestd::vector<uint8_t>* ConstructCIEFrame(InstructionSet isa) { 20679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe switch (isa) { 20779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe case kX86: 20879273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe return ConstructCIEFrameX86(false); 20979273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe case kX86_64: 21079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe return ConstructCIEFrameX86(true); 21179273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 21279273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe default: 21379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe // Not implemented. 21479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe return nullptr; 21579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } 21679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe} 21779273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe 21854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampeclass OatWriterWrapper : public CodeOutput { 21954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe public: 22054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {} 22154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 22254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe bool Write(OutputStream* out) OVERRIDE { 22354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe return oat_writer_->Write(out); 22454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 22554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe private: 22654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe OatWriter* oat_writer_; 22754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe}; 22854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 22954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampetemplate <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 23054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 23154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe typename Elf_Phdr, typename Elf_Shdr> 23254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampestatic void WriteDebugSymbols(const CompilerDriver* compiler_driver, 23354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 23454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder, 23554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe OatWriter* oat_writer); 23654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 237f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffraytemplate <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 238f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 239f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray typename Elf_Phdr, typename Elf_Shdr> 240f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffraybool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 241f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Write(OatWriter* oat_writer, 242b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom const std::vector<const DexFile*>& dex_files_unused, 243b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom const std::string& android_root_unused, 244b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom bool is_host_unused) { 24579273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe constexpr bool debug = false; 246b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom const OatHeader& oat_header = oat_writer->GetOatHeader(); 247f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray Elf_Word oat_data_size = oat_header.GetExecutableOffset(); 248b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size; 249b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom 25054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe OatWriterWrapper wrapper(oat_writer); 25154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 25254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe std::unique_ptr<ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 25354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> > builder( 25454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe new ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 25554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>( 25654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe &wrapper, 25754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe elf_file_, 25854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe compiler_driver_->GetInstructionSet(), 25954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 0, 26054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe oat_data_size, 26154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe oat_data_size, 26254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe oat_exec_size, 26354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(), 26454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe debug)); 26518a49cc2f956dec648e0a13186d42374023d47a7Brian Carlstrom 26618a49cc2f956dec648e0a13186d42374023d47a7Brian Carlstrom if (!builder->Init()) { 267e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return false; 268e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 269e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 27079273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) { 27154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer); 2726a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom } 2736a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom 27453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) { 27554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches( 27654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, sizeof(uintptr_t), sizeof(uintptr_t)); 27754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ReservePatchSpace(compiler_driver_, oat_patches.GetBuffer(), debug); 27818a49cc2f956dec648e0a13186d42374023d47a7Brian Carlstrom builder->RegisterRawSection(oat_patches); 27953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 28053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 28118a49cc2f956dec648e0a13186d42374023d47a7Brian Carlstrom return builder->Write(); 282b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom} 283ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 284e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanclass LineTableGenerator FINAL : public Leb128Encoder { 285e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban public: 286e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban LineTableGenerator(int line_base, int line_range, int opcode_base, 287e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban std::vector<uint8_t>* data, uintptr_t current_address, 288e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban size_t current_line) 289e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban : Leb128Encoder(data), line_base_(line_base), line_range_(line_range), 290e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban opcode_base_(opcode_base), current_address_(current_address), 29133ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban current_line_(current_line), current_file_index_(0) {} 292e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 293e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban void PutDelta(unsigned delta_addr, int delta_line) { 294e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban current_line_ += delta_line; 295e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban current_address_ += delta_addr; 296e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 297e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) { 298e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban unsigned special_opcode = (delta_line - line_base_) + 299e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban (line_range_ * delta_addr) + opcode_base_; 300e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (special_opcode <= 255) { 301e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, special_opcode); 302e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return; 303e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 304e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 305e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 306e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // generate standart opcode for address advance 307e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (delta_addr != 0) { 308e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, DW_LNS_advance_pc); 309e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushBackUnsigned(delta_addr); 310e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 311e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 312e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // generate standart opcode for line delta 313e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (delta_line != 0) { 314e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, DW_LNS_advance_line); 315e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushBackSigned(delta_line); 316e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 317e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 318e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // generate standart opcode for new LTN entry 319e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, DW_LNS_copy); 320e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 321e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 322e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban void SetAddr(uintptr_t addr) { 323e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (current_address_ == addr) { 324e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return; 325e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 326e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 327e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban current_address_ = addr; 328e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 329e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, 0); // extended opcode: 330e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, 1 + 4); // length: opcode_size + address_size 331e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, DW_LNE_set_address); 332e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(data_, addr); 333e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 334e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 335e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban void SetLine(unsigned line) { 336e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban int delta_line = line - current_line_; 337e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (delta_line) { 338e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban current_line_ = line; 339e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, DW_LNS_advance_line); 340e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushBackSigned(delta_line); 341e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 342e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 343e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 344e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban void SetFile(unsigned file_index) { 34533ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban if (current_file_index_ != file_index) { 34633ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban current_file_index_ = file_index; 34733ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban PushByte(data_, DW_LNS_set_file); 34833ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban PushBackUnsigned(file_index); 34933ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban } 350e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 351e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 352e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban void EndSequence() { 353e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // End of Line Table Program 354e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // 0(=ext), 1(len), DW_LNE_end_sequence 355e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, 0); 356e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, 1); 357e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(data_, DW_LNE_end_sequence); 358e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 359e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 360e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban private: 361e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const int line_base_; 362e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const int line_range_; 363e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const int opcode_base_; 364e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uintptr_t current_address_; 365e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban size_t current_line_; 36633ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban unsigned current_file_index_; 367e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 368e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DISALLOW_COPY_AND_ASSIGN(LineTableGenerator); 369e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban}; 370e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 371e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban// TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff. 372e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanstatic void GetLineInfoForJava(const uint8_t* dbgstream, const SrcMap& pc2dex, 373e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban SrcMap* result, uint32_t start_pc = 0) { 374e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (dbgstream == nullptr) { 375e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban return; 376e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 377e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 378e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban int adjopcode; 379e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t dex_offset = 0; 380e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t java_line = DecodeUnsignedLeb128(&dbgstream); 381e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 382e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // skip parameters 383e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban for (uint32_t param_count = DecodeUnsignedLeb128(&dbgstream); param_count != 0; --param_count) { 384e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DecodeUnsignedLeb128(&dbgstream); 385e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 386e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 387e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban for (bool is_end = false; is_end == false; ) { 388e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint8_t opcode = *dbgstream; 389e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban dbgstream++; 390e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban switch (opcode) { 391e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_END_SEQUENCE: 392e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban is_end = true; 393e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban break; 394e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 395e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_ADVANCE_PC: 396e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban dex_offset += DecodeUnsignedLeb128(&dbgstream); 397e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban break; 398e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 399e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_ADVANCE_LINE: 400e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban java_line += DecodeSignedLeb128(&dbgstream); 401e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban break; 402e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 403e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_START_LOCAL: 404e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_START_LOCAL_EXTENDED: 405e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DecodeUnsignedLeb128(&dbgstream); 406e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DecodeUnsignedLeb128(&dbgstream); 407e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DecodeUnsignedLeb128(&dbgstream); 408e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 409e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (opcode == DexFile::DBG_START_LOCAL_EXTENDED) { 410e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DecodeUnsignedLeb128(&dbgstream); 411e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 412e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban break; 413e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 414e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_END_LOCAL: 415e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_RESTART_LOCAL: 416e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DecodeUnsignedLeb128(&dbgstream); 417e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban break; 418e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 419e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_SET_PROLOGUE_END: 420e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_SET_EPILOGUE_BEGIN: 421e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban case DexFile::DBG_SET_FILE: 422e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban break; 423e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 424e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban default: 425e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL; 426e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban dex_offset += adjopcode / DexFile::DBG_LINE_RANGE; 427e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE); 428e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 429e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban for (SrcMap::const_iterator found = pc2dex.FindByTo(dex_offset); 430e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset); 431e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban found++) { 432e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)}); 433e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 434e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban break; 435e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 43679273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe } 437ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 438ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 43954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe/* 44054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe * @brief Generate the DWARF debug_info and debug_abbrev sections 44154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe * @param oat_writer The Oat file Writer. 44254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe * @param dbg_info Compilation unit information. 44354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe * @param dbg_abbrev Abbreviations used to generate dbg_info. 44454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe * @param dbg_str Debug strings. 44554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe */ 44654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampestatic void FillInCFIInformation(OatWriter* oat_writer, 44754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe std::vector<uint8_t>* dbg_info, 44854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe std::vector<uint8_t>* dbg_abbrev, 44954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe std::vector<uint8_t>* dbg_str, 45054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe std::vector<uint8_t>* dbg_line, 45154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe uint32_t text_section_offset) { 452e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo(); 453e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 454e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat"); 455e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 456ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Create the debug_abbrev section with boilerplate information. 457ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We only care about low_pc and high_pc right now for the compilation 458ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // unit and methods. 459ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 460ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Tag 1: Compilation unit: DW_TAG_compile_unit. 461e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, 1); 462e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_TAG_compile_unit); 463ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 464ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // There are children (the methods). 465e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_CHILDREN_yes); 466e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 467e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // DW_AT_producer DW_FORM_data1. 468e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // REVIEW: we can get rid of dbg_str section if 469e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // DW_FORM_string (immediate string) was used everywhere instead of 470e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // DW_FORM_strp (ref to string from .debug_str section). 471e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // DW_FORM_strp makes sense only if we reuse the strings. 472e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_producer); 473e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_strp); 474ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 475ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // DW_LANG_Java DW_FORM_data1. 476e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_language); 477e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_data1); 478ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 479ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // DW_AT_low_pc DW_FORM_addr. 480e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_low_pc); 481e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_addr); 482ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 483ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // DW_AT_high_pc DW_FORM_addr. 484e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_high_pc); 485e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_addr); 486e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 487e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (dbg_line != nullptr) { 488e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // DW_AT_stmt_list DW_FORM_sec_offset. 489e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_stmt_list); 490e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_sec_offset); 491e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 492ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 493ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // End of DW_TAG_compile_unit. 494ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushHalf(dbg_abbrev, 0); 495ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 496ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Tag 2: Compilation unit: DW_TAG_subprogram. 497e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, 2); 498e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_TAG_subprogram); 499ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 500ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // There are no children. 501e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_CHILDREN_no); 502ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 503ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Name of the method. 504e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_name); 505e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_strp); 506ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 507ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // DW_AT_low_pc DW_FORM_addr. 508e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_low_pc); 509e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_addr); 510ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 511ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // DW_AT_high_pc DW_FORM_addr. 512e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_AT_high_pc); 513e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_abbrev, DW_FORM_addr); 514ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 515ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // End of DW_TAG_subprogram. 516ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushHalf(dbg_abbrev, 0); 517ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 518ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Start the debug_info section with the header information 519ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // 'unit_length' will be filled in later. 520e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban int cunit_length = dbg_info->size(); 521ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(dbg_info, 0); 522ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 523ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // 'version' - 3. 524ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushHalf(dbg_info, 3); 525ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 526ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Offset into .debug_abbrev section (always 0). 527ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(dbg_info, 0); 528ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 529ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Address size: 4. 530e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_info, 4); 531ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 532ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Start the description for the compilation unit. 533ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // This uses tag 1. 534e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_info, 1); 535e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 536e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // The producer is Android dex2oat. 537e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, producer_str_offset); 538ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 539ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // The language is Java. 540e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_info, DW_LANG_Java); 541ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 542e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // low_pc and high_pc. 543e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t cunit_low_pc = 0 - 1; 544e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban uint32_t cunit_high_pc = 0; 545e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban int cunit_low_pc_pos = dbg_info->size(); 546ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(dbg_info, 0); 547ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(dbg_info, 0); 548ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 549e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (dbg_line == nullptr) { 550e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban for (size_t i = 0; i < method_info.size(); ++i) { 551e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const OatWriter::DebugInfo &dbg = method_info[i]; 552e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 553e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_); 554e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_); 555e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 556e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Start a new TAG: subroutine (2). 557e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_info, 2); 558ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 559e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Enter name, low_pc, high_pc. 560e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_)); 561e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, dbg.low_pc_ + text_section_offset); 562e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, dbg.high_pc_ + text_section_offset); 563ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 564e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } else { 565e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // TODO: in gdb info functions <regexp> - reports Java functions, but 566e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // source file is <unknown> because .debug_line is formed as one 567e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // compilation unit. To fix this it is possible to generate 568e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // a separate compilation unit for every distinct Java source. 569e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Each of the these compilation units can have several non-adjacent 570e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // method ranges. 571e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 572e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Line number table offset 573e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, dbg_line->size()); 574e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 575e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban size_t lnt_length = dbg_line->size(); 576e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_line, 0); 577e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 578e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushHalf(dbg_line, 4); // LNT Version DWARF v4 => 4 579e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 580e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban size_t lnt_hdr_length = dbg_line->size(); 581e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_line, 0); // TODO: 64-bit uses 8-byte here 582e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 583e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 1); // minimum_instruction_length (ubyte) 584e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 1); // maximum_operations_per_instruction (ubyte) = always 1 585e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 1); // default_is_stmt (ubyte) 586e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 587e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const int8_t LINE_BASE = -5; 588e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, LINE_BASE); // line_base (sbyte) 589e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 590e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const uint8_t LINE_RANGE = 14; 591e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, LINE_RANGE); // line_range (ubyte) 592e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 593e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const uint8_t OPCODE_BASE = 13; 594e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, OPCODE_BASE); // opcode_base (ubyte) 595e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 596e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Standard_opcode_lengths (array of ubyte). 597e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1); 598e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0); 599e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1); 600e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1); 601e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 602e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); // include_directories (sequence of path names) = EMPTY 603e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 604e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // File_names (sequence of file entries). 605e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban std::unordered_map<const char*, size_t> files; 606e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban for (size_t i = 0; i < method_info.size(); ++i) { 607e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const OatWriter::DebugInfo &dbg = method_info[i]; 608e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // TODO: add package directory to the file name 609e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_; 610e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban auto found = files.find(file_name); 611e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban if (found == files.end()) { 612e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban size_t file_index = 1 + files.size(); 613e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban files[file_name] = file_index; 614e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushStr(dbg_line, file_name); 615e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); // include directory index = LEB128(0) - no directory 616e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); // modification time = LEB128(0) - NA 617e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); // file length = LEB128(0) - NA 618e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 619e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 620e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_line, 0); // End of file_names. 621e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 622e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Set lnt header length. 623e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4); 624e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 625e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Generate Line Number Program code, one long program for all methods. 626e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE, 627e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban dbg_line, 0, 1); 628e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 629e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban SrcMap pc2java_map; 630e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban for (size_t i = 0; i < method_info.size(); ++i) { 631e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const OatWriter::DebugInfo &dbg = method_info[i]; 632e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_; 633e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban size_t file_index = files[file_name]; 634e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban DCHECK_NE(file_index, 0U) << file_name; 635e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 636e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_); 637e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_); 638e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 639e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Start a new TAG: subroutine (2). 640e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_info, 2); 641e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 642e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Enter name, low_pc, high_pc. 643e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, PushStr(dbg_str, dbg.method_name_)); 644e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, dbg.low_pc_ + text_section_offset); 645e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushWord(dbg_info, dbg.high_pc_ + text_section_offset); 646e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 647e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(), 648e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban &pc2java_map, dbg.low_pc_); 649e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_); 65033ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban if (!pc2java_map.empty()) { 65133ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban line_table_generator.SetFile(file_index); 65233ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset); 65333ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban line_table_generator.SetLine(1); 65433ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban for (auto& src_map_elem : pc2java_map) { 65533ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_); 65633ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban } 65733ac819bd13c6e9d42b36ae8393c37cfb1bb4cdeYevgeny Rouban pc2java_map.clear(); 658e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban } 659ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 660ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 661e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // End Sequence should have the highest address set. 662e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban line_table_generator.SetAddr(cunit_high_pc + text_section_offset); 663e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban line_table_generator.EndSequence(); 664ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 665e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // set lnt length 666e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4); 667ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 668ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 669ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // One byte terminator 670e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban PushByte(dbg_info, 0); 671e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban 672e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // Fill in cunit's low_pc and high_pc. 673e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset); 674e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset); 675ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 676e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban // We have now walked all the methods. Fill in lengths. 677e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4); 6786a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom} 6796a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom 68054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampetemplate <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 68154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 68254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe typename Elf_Phdr, typename Elf_Shdr> 68354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampestatic void WriteDebugSymbols(const CompilerDriver* compiler_driver, 68454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 68554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder, 68654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe OatWriter* oat_writer) { 68754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe std::unique_ptr<std::vector<uint8_t>> cfi_info( 68854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ConstructCIEFrame(compiler_driver->GetInstructionSet())); 68954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 69054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe Elf_Addr text_section_address = builder->text_builder_.section_.sh_addr; 69154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 69254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe // Iterate over the compiled methods. 69354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo(); 69454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, 69554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe Elf_Sym, Elf_Shdr>* symtab = &builder->symtab_builder_; 69654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe for (auto it = method_info.begin(); it != method_info.end(); ++it) { 69754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe symtab->AddSymbol(it->method_name_, &builder->text_builder_, it->low_pc_, true, 69854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC); 69954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 70054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe // Include CFI for compiled method, if possible. 70154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (cfi_info.get() != nullptr) { 70254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe DCHECK(it->compiled_method_ != nullptr); 70354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 70454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe // Copy in the FDE, if present 70554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe const std::vector<uint8_t>* fde = it->compiled_method_->GetCFIInfo(); 70654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (fde != nullptr) { 70754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe // Copy the information into cfi_info and then fix the address in the new copy. 70854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe int cur_offset = cfi_info->size(); 70954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe cfi_info->insert(cfi_info->end(), fde->begin(), fde->end()); 71054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 71154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe bool is_64bit = *(reinterpret_cast<const uint32_t*>(fde->data())) == 0xffffffff; 71254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 71354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe // Set the 'CIE_pointer' field. 71454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe uint64_t CIE_pointer = cur_offset + (is_64bit ? 12 : 4); 71554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe uint64_t offset_to_update = CIE_pointer; 71654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (is_64bit) { 71754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+0] = CIE_pointer; 71854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8; 71954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16; 72054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24; 72154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+4] = CIE_pointer >> 32; 72254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+5] = CIE_pointer >> 40; 72354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+6] = CIE_pointer >> 48; 72454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+7] = CIE_pointer >> 56; 72554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } else { 72654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+0] = CIE_pointer; 72754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8; 72854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16; 72954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24; 73054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 73154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 73254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe // Set the 'initial_location' field. 73354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe offset_to_update += is_64bit ? 8 : 4; 73454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (is_64bit) { 73554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe const uint64_t quick_code_start = it->low_pc_ + text_section_address; 73654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+0] = quick_code_start; 73754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+1] = quick_code_start >> 8; 73854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+2] = quick_code_start >> 16; 73954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+3] = quick_code_start >> 24; 74054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+4] = quick_code_start >> 32; 74154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+5] = quick_code_start >> 40; 74254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+6] = quick_code_start >> 48; 74354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+7] = quick_code_start >> 56; 74454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } else { 74554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe const uint32_t quick_code_start = it->low_pc_ + text_section_address; 74654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+0] = quick_code_start; 74754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+1] = quick_code_start >> 8; 74854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+2] = quick_code_start >> 16; 74954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe (*cfi_info)[offset_to_update+3] = quick_code_start >> 24; 75054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 75154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 75254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 75354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 75454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 75554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe bool hasCFI = (cfi_info.get() != nullptr); 75654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe bool hasLineInfo = false; 75754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe for (auto& dbg_info : oat_writer->GetCFIMethodInfo()) { 75854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (dbg_info.dbgstream_ != nullptr && 75954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe !dbg_info.compiled_method_->GetSrcMappingTable().empty()) { 76054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe hasLineInfo = true; 76154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe break; 76254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 76354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 76454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 76554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (hasLineInfo || hasCFI) { 76654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_info(".debug_info", 76754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe SHT_PROGBITS, 76854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 0, nullptr, 0, 1, 0); 76954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_abbrev(".debug_abbrev", 77054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe SHT_PROGBITS, 77154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 0, nullptr, 0, 1, 0); 77254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_str(".debug_str", 77354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe SHT_PROGBITS, 77454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 0, nullptr, 0, 1, 0); 77554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> debug_line(".debug_line", 77654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe SHT_PROGBITS, 77754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 0, nullptr, 0, 1, 0); 77854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 77954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe FillInCFIInformation(oat_writer, debug_info.GetBuffer(), 78054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe debug_abbrev.GetBuffer(), debug_str.GetBuffer(), 78154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe hasLineInfo ? debug_line.GetBuffer() : nullptr, 78254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe text_section_address); 78354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 78454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe builder->RegisterRawSection(debug_info); 78554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe builder->RegisterRawSection(debug_abbrev); 78654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 78754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (hasCFI) { 78854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> eh_frame(".eh_frame", 78954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe SHT_PROGBITS, 79054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe SHF_ALLOC, 79154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe nullptr, 0, 4, 0); 79254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe eh_frame.SetBuffer(std::move(*cfi_info.get())); 79354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe builder->RegisterRawSection(eh_frame); 79454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 79554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 79654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe if (hasLineInfo) { 79754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe builder->RegisterRawSection(debug_line); 79854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 79954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 80054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe builder->RegisterRawSection(debug_str); 80154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 80254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe} 80354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 804f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray// Explicit instantiations 805f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffraytemplate class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn, 806f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>; 807f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffraytemplate class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn, 808f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>; 809f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray 8106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom} // namespace art 811