13958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris/* 23958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * Copyright (C) 2017 The Android Open Source Project 33958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * 43958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 53958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * you may not use this file except in compliance with the License. 63958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * You may obtain a copy of the License at 73958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * 83958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 93958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * 103958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * Unless required by applicable law or agreed to in writing, software 113958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 123958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * See the License for the specific language governing permissions and 143958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * limitations under the License. 153958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris */ 163958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 173958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <elf.h> 183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <stdint.h> 193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 203958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <memory> 213958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <string> 22beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris#include <utility> 233958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 24bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris#include <7zCrc.h> 25bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris#include <Xz.h> 26bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris#include <XzCrc64.h> 27bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 282fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris#include <unwindstack/DwarfError.h> 29d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/DwarfSection.h> 30d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/ElfInterface.h> 31d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Log.h> 32d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h> 33d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Regs.h> 34d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 3561d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris#include "DwarfDebugFrame.h" 3661d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris#include "DwarfEhFrame.h" 37c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris#include "DwarfEhFrameWithHdr.h" 388098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris#include "Symbols.h" 398098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 40d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisnamespace unwindstack { 41d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 428098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher FerrisElfInterface::~ElfInterface() { 438098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris for (auto symbol : symbols_) { 448098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris delete symbol; 458098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 468098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris} 473958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 48150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferrisbool ElfInterface::IsValidPc(uint64_t pc) { 49150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (!pt_loads_.empty()) { 50150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris for (auto& entry : pt_loads_) { 51150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris uint64_t start = entry.second.table_offset; 52150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris uint64_t end = start + entry.second.table_size; 53150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (pc >= start && pc < end) { 54150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return true; 55150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 56150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 57150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 58150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 59150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 60150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris // No PT_LOAD data, look for a fde for this pc in the section data. 61150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (debug_frame_ != nullptr && debug_frame_->GetFdeFromPc(pc) != nullptr) { 62150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return true; 63150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 64150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 65150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (eh_frame_ != nullptr && eh_frame_->GetFdeFromPc(pc) != nullptr) { 66150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return true; 67150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 68150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 69150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 70150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris} 71150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 72bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher FerrisMemory* ElfInterface::CreateGnuDebugdataMemory() { 73bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) { 74bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return nullptr; 75bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 76bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 77bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris // TODO: Only call these initialization functions once. 78bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris CrcGenerateTable(); 79bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris Crc64GenerateTable(); 80bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 81bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris std::vector<uint8_t> src(gnu_debugdata_size_); 82ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) { 83bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_offset_ = 0; 84bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_size_ = static_cast<uint64_t>(-1); 85bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return nullptr; 86bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 87bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 88bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris ISzAlloc alloc; 89bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris CXzUnpacker state; 90bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris alloc.Alloc = [](void*, size_t size) { return malloc(size); }; 91bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris alloc.Free = [](void*, void* ptr) { return free(ptr); }; 92bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 93bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris XzUnpacker_Construct(&state, &alloc); 94bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 95bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer); 96bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris int return_val; 97bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t src_offset = 0; 98bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t dst_offset = 0; 99bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris ECoderStatus status; 100bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst->Resize(5 * gnu_debugdata_size_); 101bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris do { 102bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t src_remaining = src.size() - src_offset; 103bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t dst_remaining = dst->Size() - dst_offset; 104bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (dst_remaining < 2 * gnu_debugdata_size_) { 105bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst->Resize(dst->Size() + 2 * gnu_debugdata_size_); 106bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst_remaining += 2 * gnu_debugdata_size_; 107bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 108bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset], 109bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris &src_remaining, CODER_FINISH_ANY, &status); 110bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris src_offset += src_remaining; 111bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst_offset += dst_remaining; 112bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED); 113bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris XzUnpacker_Free(&state); 114bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) { 115bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_offset_ = 0; 116bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_size_ = static_cast<uint64_t>(-1); 117bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return nullptr; 118bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 119bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 120bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris // Shrink back down to the exact size. 121bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst->Resize(dst_offset); 122bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 123bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return dst.release(); 124bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris} 125bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 12661d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferristemplate <typename AddressType> 12761d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferrisvoid ElfInterface::InitHeadersWithTemplate() { 128c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris if (eh_frame_hdr_offset_ != 0) { 129c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_)); 130c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) { 131c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_.reset(nullptr); 132c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris } 1331a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris } 1341a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris 1351a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris if (eh_frame_.get() == nullptr && eh_frame_offset_ != 0) { 1361a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris // If there is an eh_frame section without an eh_frame_hdr section, 1371a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris // or using the frame hdr object failed to init. 13861d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_)); 13961d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) { 14061d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris eh_frame_.reset(nullptr); 14161d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 14261d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 14361d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris 1441a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris if (eh_frame_.get() == nullptr) { 1451a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris eh_frame_hdr_offset_ = 0; 1461a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris eh_frame_hdr_size_ = static_cast<uint64_t>(-1); 1471a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris eh_frame_offset_ = 0; 1481a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris eh_frame_size_ = static_cast<uint64_t>(-1); 1491a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris } 1501a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris 15161d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris if (debug_frame_offset_ != 0) { 15261d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_)); 15361d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_)) { 15461d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_.reset(nullptr); 15561d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_offset_ = 0; 15661d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_size_ = static_cast<uint64_t>(-1); 15761d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 15861d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 15961d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris} 16061d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris 1613958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename EhdrType, typename PhdrType, typename ShdrType> 162e69f470933f24977825bb34ee39d32650b75107fChristopher Ferrisbool ElfInterface::ReadAllHeaders(uint64_t* load_bias) { 1633958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris EhdrType ehdr; 164ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) { 1652fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 1662fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = 0; 1673958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1683958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1693958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 170e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias)) { 1713958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1723958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1738098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 1748098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // We could still potentially unwind without the section header 1758098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // information, so ignore any errors. 1768098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) { 1778098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris log(0, "Malformed section header found, ignoring..."); 1788098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 1798098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 1803958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 1813958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 1823958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename EhdrType, typename PhdrType> 183b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferrisuint64_t ElfInterface::GetLoadBias(Memory* memory) { 184b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris EhdrType ehdr; 185b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (!memory->Read(0, &ehdr, sizeof(ehdr))) { 186b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return false; 187b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 188b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 189b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris uint64_t offset = ehdr.e_phoff; 190b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { 191b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris PhdrType phdr; 192b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (!memory->Read(offset, &phdr, sizeof(phdr))) { 193b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return 0; 194b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 195b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) { 196b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return phdr.p_vaddr; 197b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 198b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 199b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return 0; 200b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris} 201b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 202b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferristemplate <typename EhdrType, typename PhdrType> 203e69f470933f24977825bb34ee39d32650b75107fChristopher Ferrisbool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) { 2043958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t offset = ehdr.e_phoff; 2053958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { 2063958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris PhdrType phdr; 207f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) { 2082fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2092fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = 2102fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris offset + reinterpret_cast<uintptr_t>(&phdr.p_type) - reinterpret_cast<uintptr_t>(&phdr); 2113958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2123958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2133958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 214e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (HandleType(offset, phdr.p_type, *load_bias)) { 2153958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris continue; 2163958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2173958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris switch (phdr.p_type) { 2193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris case PT_LOAD: 2203958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris { 2213958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Get the flags first, if this isn't an executable header, ignore it. 222f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) { 2232fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2242fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_flags) - 2252fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2263958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2273958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2283958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if ((phdr.p_flags & PF_X) == 0) { 2293958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris continue; 2303958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2313958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 232f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) { 2332fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2342fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) - 2352fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 238f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 2392fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2402fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) - 2412fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2423958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2433958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 244f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 2452fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2462fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) - 2472fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2483958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2493958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2503958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr, 2513958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris static_cast<size_t>(phdr.p_memsz)}; 2523958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (phdr.p_offset == 0) { 253e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris *load_bias = phdr.p_vaddr; 2543958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2553958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 2563958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2573958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2583958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris case PT_GNU_EH_FRAME: 259f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 2602fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2612fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) - 2622fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2633958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2643958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 265c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris // This is really the pointer to the .eh_frame_hdr section. 266c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_hdr_offset_ = phdr.p_offset; 267f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 2682fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2692fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) - 2702fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2713958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2723958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 273c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_hdr_size_ = phdr.p_memsz; 2743958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 2753958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2763958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris case PT_DYNAMIC: 277f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 2782fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2792fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) - 2802fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2813958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2823958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2833958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris dynamic_offset_ = phdr.p_offset; 284150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) { 2852fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2862fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) - 2872fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 288150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 289150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 290150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris dynamic_vaddr_ = phdr.p_vaddr; 291f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 2922fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 2932fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) - 2942fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris reinterpret_cast<uintptr_t>(&phdr); 2953958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2963958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2973958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris dynamic_size_ = phdr.p_memsz; 2983958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 2993958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3003958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3013958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 3023958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 3033958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3043958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename EhdrType, typename ShdrType> 3053958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferrisbool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { 3063958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t offset = ehdr.e_shoff; 3073958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t sec_offset = 0; 3083958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t sec_size = 0; 3093958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3103958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Get the location of the section header names. 3113958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // If something is malformed in the header table data, we aren't going 3123958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // to terminate, we'll simply ignore this part. 3133958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris ShdrType shdr; 3143958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (ehdr.e_shstrndx < ehdr.e_shnum) { 3153958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize; 316f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (memory_->ReadField(sh_offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && 317f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris memory_->ReadField(sh_offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) { 3183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris sec_offset = shdr.sh_offset; 3193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris sec_size = shdr.sh_size; 3203958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3213958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3223958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3233958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Skip the first header, it's always going to be NULL. 3248098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris offset += ehdr.e_shentsize; 3253958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { 326beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris if (!memory_->Read(offset, &shdr, sizeof(shdr))) { 3272fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 328beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris last_error_.address = offset; 3293958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 3303958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3313958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3328098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { 3338098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // Need to go get the information about the section that contains 3348098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // the string terminated names. 3358098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris ShdrType str_shdr; 3368098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (shdr.sh_link >= ehdr.e_shnum) { 3372fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_UNWIND_INFO; 3388098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 3398098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 3408098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize; 341beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) { 3422fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 343beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris last_error_.address = str_offset; 3448098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 3458098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 3468098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (str_shdr.sh_type != SHT_STRTAB) { 3472fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_UNWIND_INFO; 3488098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 3498098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 3508098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize, 3518098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris str_shdr.sh_offset, str_shdr.sh_size)); 3528098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) { 3533958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Look for the .debug_frame and .gnu_debugdata. 3543958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (shdr.sh_name < sec_size) { 3553958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris std::string name; 3563958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) { 3578098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t* offset_ptr = nullptr; 3588098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t* size_ptr = nullptr; 3593958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (name == ".debug_frame") { 3608098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris offset_ptr = &debug_frame_offset_; 3618098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris size_ptr = &debug_frame_size_; 3623958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (name == ".gnu_debugdata") { 3638098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris offset_ptr = &gnu_debugdata_offset_; 3648098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris size_ptr = &gnu_debugdata_size_; 365c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris } else if (name == ".eh_frame") { 366c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris offset_ptr = &eh_frame_offset_; 367c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris size_ptr = &eh_frame_size_; 368c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") { 369c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris offset_ptr = &eh_frame_hdr_offset_; 370c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris size_ptr = &eh_frame_hdr_size_; 3718098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 372beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris if (offset_ptr != nullptr) { 3738098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris *offset_ptr = shdr.sh_offset; 3748098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris *size_ptr = shdr.sh_size; 3753958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3763958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3773958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 378beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris } else if (shdr.sh_type == SHT_STRTAB) { 379beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris // In order to read soname, keep track of address to offset mapping. 380beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr), 381beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris static_cast<uint64_t>(shdr.sh_offset))); 3823958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3833958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3843958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 3853958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 3863958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3873958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename DynType> 3883958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferrisbool ElfInterface::GetSonameWithTemplate(std::string* soname) { 3893958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (soname_type_ == SONAME_INVALID) { 3903958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 3913958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3923958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (soname_type_ == SONAME_VALID) { 3933958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris *soname = soname_; 3943958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 3953958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3963958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3973958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris soname_type_ = SONAME_INVALID; 3983958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3993958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t soname_offset = 0; 400beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris uint64_t strtab_addr = 0; 4013958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t strtab_size = 0; 4023958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 4033958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Find the soname location from the dynamic headers section. 4043958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris DynType dyn; 4053958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t offset = dynamic_offset_; 4063958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t max_offset = offset + dynamic_size_; 4073958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) { 408ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) { 4092fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 4102fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = offset; 4113958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 4123958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 4133958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 4143958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (dyn.d_tag == DT_STRTAB) { 415beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris strtab_addr = dyn.d_un.d_ptr; 4163958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (dyn.d_tag == DT_STRSZ) { 4173958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris strtab_size = dyn.d_un.d_val; 4183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (dyn.d_tag == DT_SONAME) { 4193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris soname_offset = dyn.d_un.d_val; 4203958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (dyn.d_tag == DT_NULL) { 4213958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 4223958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 4233958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 4243958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 425beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris // Need to map the strtab address to the real offset. 426beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris for (const auto& entry : strtabs_) { 427beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris if (entry.first == strtab_addr) { 428beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris soname_offset = entry.second + soname_offset; 429beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris if (soname_offset >= entry.second + strtab_size) { 430beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris return false; 431beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris } 432beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris if (!memory_->ReadString(soname_offset, &soname_)) { 433beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris return false; 434beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris } 435beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris soname_type_ = SONAME_VALID; 436beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris *soname = soname_; 437beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris return true; 438beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris } 4393958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 440beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris return false; 4413958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 4423958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 4438098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferristemplate <typename SymType> 444e69f470933f24977825bb34ee39d32650b75107fChristopher Ferrisbool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name, 4458098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t* func_offset) { 4468098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (symbols_.empty()) { 4478098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 4488098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 4498098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 4508098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris for (const auto symbol : symbols_) { 451e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (symbol->GetName<SymType>(addr, load_bias, memory_, name, func_offset)) { 4528098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 4538098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 4548098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 4558098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 4568098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris} 4578098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 458150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferristemplate <typename SymType> 459150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferrisbool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address) { 460150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (symbols_.empty()) { 461150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 462150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 463150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 464150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris for (const auto symbol : symbols_) { 465150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (symbol->GetGlobal<SymType>(memory_, name, memory_address)) { 466150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return true; 467150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 468150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 469150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 470150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris} 471150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 472e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferrisbool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 473e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris bool* finished) { 4742fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_NONE; 4752fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = 0; 4762fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 477e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris // Adjust the load bias to get the real relative pc. 478e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris if (pc < load_bias) { 4792fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_UNWIND_INFO; 480e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris return false; 481e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris } 482e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris uint64_t adjusted_pc = pc - load_bias; 483e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris 4841a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris // Try the debug_frame first since it contains the most specific unwind 4851a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris // information. 4861a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris DwarfSection* debug_frame = debug_frame_.get(); 4871a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) { 4888098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 4898098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 4908098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 4911a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris // Try the eh_frame next. 4921a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris DwarfSection* eh_frame = eh_frame_.get(); 4931a141a09256bbb61ffd67a0f666711a92adf5726Christopher Ferris if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) { 494e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris return true; 495e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris } 496e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris 497e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris // Finally try the gnu_debugdata interface, but always use a zero load bias. 498e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris if (gnu_debugdata_interface_ != nullptr && 499e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) { 5008098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 5018098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 5022fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 5032fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris // Set the error code based on the first error encountered. 5042fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris DwarfSection* section = nullptr; 5052fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris if (debug_frame_ != nullptr) { 5062fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris section = debug_frame_.get(); 5072fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } else if (eh_frame_ != nullptr) { 5082fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris section = eh_frame_.get(); 5092fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } else if (gnu_debugdata_interface_ != nullptr) { 5102fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_ = gnu_debugdata_interface_->last_error(); 5112fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris return false; 5122fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } else { 5132fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris return false; 5142fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } 5152fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 5162fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris // Convert the DWARF ERROR to an external error. 5172fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris DwarfErrorCode code = section->LastErrorCode(); 5182fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris switch (code) { 5192fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_NONE: 5202fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_NONE; 5212fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris break; 5222fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 5232fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_MEMORY_INVALID: 5242fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_MEMORY_INVALID; 5252fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.address = section->LastErrorAddress(); 5262fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris break; 5272fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 5282fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_ILLEGAL_VALUE: 5292fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_ILLEGAL_STATE: 5302fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_STACK_INDEX_NOT_VALID: 5312fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_TOO_MANY_ITERATIONS: 5322fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_CFA_NOT_DEFINED: 5332fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_NO_FDES: 5342fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_UNWIND_INFO; 5352fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris break; 5362fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 5372fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_NOT_IMPLEMENTED: 5382fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris case DWARF_ERROR_UNSUPPORTED_VERSION: 5392fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris last_error_.code = ERROR_UNSUPPORTED; 5402fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris break; 5412fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } 5423958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 5433958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 5443958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 5453f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// This is an estimation of the size of the elf file using the location 5463f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// of the section headers and size. This assumes that the section headers 5473f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// are at the end of the elf file. If the elf has a load bias, the size 5483f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// will be too large, but this is acceptable. 5493f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferristemplate <typename EhdrType> 5503f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferrisvoid ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) { 5513f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris EhdrType ehdr; 552ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) { 5533f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris return; 5543f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } 5553f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris if (ehdr.e_shnum == 0) { 5563f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris return; 5573f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } 5583f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; 5593f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris} 5603f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris 5613958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris// Instantiate all of the needed template functions. 56261d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferristemplate void ElfInterface::InitHeadersWithTemplate<uint32_t>(); 56361d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferristemplate void ElfInterface::InitHeadersWithTemplate<uint64_t>(); 56461d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris 565e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*); 566e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*); 5673958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 568e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, uint64_t*); 569e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, uint64_t*); 5703958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 5713958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&); 5723958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&); 5733958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 5743958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*); 5753958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*); 5768098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 577e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, uint64_t, std::string*, 5788098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t*); 579e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, uint64_t, std::string*, 5808098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t*); 581d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 582150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferristemplate bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*); 583150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferristemplate bool ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(const std::string&, uint64_t*); 584150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 5853f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferristemplate void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*); 5863f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferristemplate void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*); 5873f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris 588b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferristemplate uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*); 589b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferristemplate uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*); 590b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 591d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} // namespace unwindstack 592