ElfInterface.cpp revision e7b6624c3fd6bb780f6330448fad175e80469384
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> 223958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 23bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris#include <7zCrc.h> 24bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris#include <Xz.h> 25bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris#include <XzCrc64.h> 26bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 27d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/DwarfSection.h> 28d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/ElfInterface.h> 29d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Log.h> 30d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h> 31d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Regs.h> 32d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 3361d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris#include "DwarfDebugFrame.h" 3461d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris#include "DwarfEhFrame.h" 35c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris#include "DwarfEhFrameWithHdr.h" 368098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris#include "Symbols.h" 378098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 38d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisnamespace unwindstack { 39d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 408098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher FerrisElfInterface::~ElfInterface() { 418098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris for (auto symbol : symbols_) { 428098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris delete symbol; 438098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 448098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris} 453958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 46bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher FerrisMemory* ElfInterface::CreateGnuDebugdataMemory() { 47bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) { 48bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return nullptr; 49bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 50bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 51bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris // TODO: Only call these initialization functions once. 52bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris CrcGenerateTable(); 53bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris Crc64GenerateTable(); 54bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 55bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris std::vector<uint8_t> src(gnu_debugdata_size_); 56ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) { 57bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_offset_ = 0; 58bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_size_ = static_cast<uint64_t>(-1); 59bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return nullptr; 60bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 61bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 62bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris ISzAlloc alloc; 63bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris CXzUnpacker state; 64bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris alloc.Alloc = [](void*, size_t size) { return malloc(size); }; 65bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris alloc.Free = [](void*, void* ptr) { return free(ptr); }; 66bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 67bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris XzUnpacker_Construct(&state, &alloc); 68bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 69bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer); 70bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris int return_val; 71bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t src_offset = 0; 72bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t dst_offset = 0; 73bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris ECoderStatus status; 74bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst->Resize(5 * gnu_debugdata_size_); 75bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris do { 76bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t src_remaining = src.size() - src_offset; 77bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris size_t dst_remaining = dst->Size() - dst_offset; 78bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (dst_remaining < 2 * gnu_debugdata_size_) { 79bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst->Resize(dst->Size() + 2 * gnu_debugdata_size_); 80bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst_remaining += 2 * gnu_debugdata_size_; 81bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 82bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset], 83bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris &src_remaining, CODER_FINISH_ANY, &status); 84bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris src_offset += src_remaining; 85bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst_offset += dst_remaining; 86bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED); 87bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris XzUnpacker_Free(&state); 88bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) { 89bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_offset_ = 0; 90bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_size_ = static_cast<uint64_t>(-1); 91bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return nullptr; 92bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 93bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 94bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris // Shrink back down to the exact size. 95bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris dst->Resize(dst_offset); 96bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 97bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return dst.release(); 98bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris} 99bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 10061d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferristemplate <typename AddressType> 10161d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferrisvoid ElfInterface::InitHeadersWithTemplate() { 102c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris if (eh_frame_hdr_offset_ != 0) { 103c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_)); 104c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) { 105c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris // Even if the eh_frame_offset_ is non-zero, do not bother 106c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris // trying to read that since something has gone wrong. 107c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_.reset(nullptr); 108c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_hdr_offset_ = 0; 109c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_hdr_size_ = static_cast<uint64_t>(-1); 110c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris } 111c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris } else if (eh_frame_offset_ != 0) { 112c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris // If there is a eh_frame section without a eh_frame_hdr section. 11361d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_)); 11461d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) { 11561d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris eh_frame_.reset(nullptr); 11661d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris eh_frame_offset_ = 0; 11761d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris eh_frame_size_ = static_cast<uint64_t>(-1); 11861d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 11961d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 12061d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris 12161d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris if (debug_frame_offset_ != 0) { 12261d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_)); 12361d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_)) { 12461d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_.reset(nullptr); 12561d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_offset_ = 0; 12661d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris debug_frame_size_ = static_cast<uint64_t>(-1); 12761d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 12861d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris } 12961d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris} 13061d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris 1313958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename EhdrType, typename PhdrType, typename ShdrType> 132e69f470933f24977825bb34ee39d32650b75107fChristopher Ferrisbool ElfInterface::ReadAllHeaders(uint64_t* load_bias) { 1333958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris EhdrType ehdr; 134ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) { 1353958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 138e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias)) { 1393958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1403958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1418098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 1428098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // We could still potentially unwind without the section header 1438098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // information, so ignore any errors. 1448098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) { 1458098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris log(0, "Malformed section header found, ignoring..."); 1468098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 1478098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 1483958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 1493958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 1503958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename EhdrType, typename PhdrType> 151b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferrisuint64_t ElfInterface::GetLoadBias(Memory* memory) { 152b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris EhdrType ehdr; 153b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (!memory->Read(0, &ehdr, sizeof(ehdr))) { 154b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return false; 155b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 156b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 157b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris uint64_t offset = ehdr.e_phoff; 158b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { 159b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris PhdrType phdr; 160b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (!memory->Read(offset, &phdr, sizeof(phdr))) { 161b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return 0; 162b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 163b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) { 164b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return phdr.p_vaddr; 165b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 166b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 167b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return 0; 168b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris} 169b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 170b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferristemplate <typename EhdrType, typename PhdrType> 171e69f470933f24977825bb34ee39d32650b75107fChristopher Ferrisbool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) { 1723958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t offset = ehdr.e_phoff; 1733958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { 1743958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris PhdrType phdr; 175f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) { 1763958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1773958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1783958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 179e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (HandleType(offset, phdr.p_type, *load_bias)) { 1803958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris continue; 1813958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1823958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 1833958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris switch (phdr.p_type) { 1843958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris case PT_LOAD: 1853958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris { 1863958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Get the flags first, if this isn't an executable header, ignore it. 187f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) { 1883958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1893958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1903958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if ((phdr.p_flags & PF_X) == 0) { 1913958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris continue; 1923958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1933958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 194f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) { 1953958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1963958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 197f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 1983958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1993958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 200f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 2013958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2023958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2033958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr, 2043958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris static_cast<size_t>(phdr.p_memsz)}; 2053958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (phdr.p_offset == 0) { 206e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris *load_bias = phdr.p_vaddr; 2073958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2083958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 2093958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2103958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2113958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris case PT_GNU_EH_FRAME: 212f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 2133958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2143958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 215c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris // This is really the pointer to the .eh_frame_hdr section. 216c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_hdr_offset_ = phdr.p_offset; 217f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 2183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 220c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris eh_frame_hdr_size_ = phdr.p_memsz; 2213958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 2223958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2233958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris case PT_DYNAMIC: 224f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 2253958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2263958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2273958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris dynamic_offset_ = phdr.p_offset; 228f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 2293958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2303958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2313958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris dynamic_size_ = phdr.p_memsz; 2323958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 2333958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2343958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2353958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 2363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 2373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2383958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename EhdrType, typename ShdrType> 2393958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferrisbool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { 2403958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t offset = ehdr.e_shoff; 2413958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t sec_offset = 0; 2423958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t sec_size = 0; 2433958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2443958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Get the location of the section header names. 2453958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // If something is malformed in the header table data, we aren't going 2463958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // to terminate, we'll simply ignore this part. 2473958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris ShdrType shdr; 2483958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (ehdr.e_shstrndx < ehdr.e_shnum) { 2493958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize; 250f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (memory_->ReadField(sh_offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && 251f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris memory_->ReadField(sh_offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) { 2523958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris sec_offset = shdr.sh_offset; 2533958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris sec_size = shdr.sh_size; 2543958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2553958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2563958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2573958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Skip the first header, it's always going to be NULL. 2588098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris offset += ehdr.e_shentsize; 2593958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { 260f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) { 2613958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2623958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2633958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2648098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { 265ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) { 2668098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 2678098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 2688098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // Need to go get the information about the section that contains 2698098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // the string terminated names. 2708098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris ShdrType str_shdr; 2718098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (shdr.sh_link >= ehdr.e_shnum) { 2728098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 2738098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 2748098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize; 2758098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) { 2768098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 2778098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 2788098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (str_shdr.sh_type != SHT_STRTAB) { 2798098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 2808098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 2818098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset, 2828098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris sizeof(str_shdr.sh_offset))) { 2838098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 2848098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 2858098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) { 2868098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 2878098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 2888098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize, 2898098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris str_shdr.sh_offset, str_shdr.sh_size)); 2908098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) { 2913958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Look for the .debug_frame and .gnu_debugdata. 292f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) { 2933958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 2943958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2953958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (shdr.sh_name < sec_size) { 2963958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris std::string name; 2973958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) { 2988098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t* offset_ptr = nullptr; 2998098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t* size_ptr = nullptr; 3003958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (name == ".debug_frame") { 3018098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris offset_ptr = &debug_frame_offset_; 3028098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris size_ptr = &debug_frame_size_; 3033958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (name == ".gnu_debugdata") { 3048098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris offset_ptr = &gnu_debugdata_offset_; 3058098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris size_ptr = &gnu_debugdata_size_; 306c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris } else if (name == ".eh_frame") { 307c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris offset_ptr = &eh_frame_offset_; 308c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris size_ptr = &eh_frame_size_; 309c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") { 310c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris offset_ptr = &eh_frame_hdr_offset_; 311c9dee84d81e4672dee5dd08890c904d1ab841e56Christopher Ferris size_ptr = &eh_frame_hdr_size_; 3128098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 3138098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (offset_ptr != nullptr && 3148098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && 3158098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) { 3168098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris *offset_ptr = shdr.sh_offset; 3178098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris *size_ptr = shdr.sh_size; 3183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3203958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3213958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3223958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3233958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 3243958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 3253958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3263958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate <typename DynType> 3273958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferrisbool ElfInterface::GetSonameWithTemplate(std::string* soname) { 3283958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (soname_type_ == SONAME_INVALID) { 3293958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 3303958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3313958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (soname_type_ == SONAME_VALID) { 3323958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris *soname = soname_; 3333958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 3343958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3353958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris soname_type_ = SONAME_INVALID; 3373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3383958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t soname_offset = 0; 3393958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t strtab_offset = 0; 3403958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t strtab_size = 0; 3413958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3423958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Find the soname location from the dynamic headers section. 3433958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris DynType dyn; 3443958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t offset = dynamic_offset_; 3453958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint64_t max_offset = offset + dynamic_size_; 3463958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) { 347ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) { 3483958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 3493958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3503958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3513958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (dyn.d_tag == DT_STRTAB) { 3523958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris strtab_offset = dyn.d_un.d_ptr; 3533958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (dyn.d_tag == DT_STRSZ) { 3543958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris strtab_size = dyn.d_un.d_val; 3553958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (dyn.d_tag == DT_SONAME) { 3563958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris soname_offset = dyn.d_un.d_val; 3573958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (dyn.d_tag == DT_NULL) { 3583958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris break; 3593958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3603958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3613958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3623958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris soname_offset += strtab_offset; 3633958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (soname_offset >= strtab_offset + strtab_size) { 3643958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 3653958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3663958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (!memory_->ReadString(soname_offset, &soname_)) { 3673958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 3683958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 3693958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris soname_type_ = SONAME_VALID; 3703958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris *soname = soname_; 3713958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 3723958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 3733958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 3748098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferristemplate <typename SymType> 375e69f470933f24977825bb34ee39d32650b75107fChristopher Ferrisbool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name, 3768098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t* func_offset) { 3778098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris if (symbols_.empty()) { 3788098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 3798098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 3808098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 3818098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris for (const auto symbol : symbols_) { 382e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (symbol->GetName<SymType>(addr, load_bias, memory_, name, func_offset)) { 3838098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 3848098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 3858098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 3868098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return false; 3878098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris} 3888098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 389e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferrisbool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 390e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris bool* finished) { 391e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris // Adjust the load bias to get the real relative pc. 392e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris if (pc < load_bias) { 393e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris return false; 394e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris } 395e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris uint64_t adjusted_pc = pc - load_bias; 396e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris 3978098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // Try the eh_frame first. 3988098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris DwarfSection* eh_frame = eh_frame_.get(); 399e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) { 4008098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 4018098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 4028098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 4038098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris // Try the debug_frame next. 4048098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris DwarfSection* debug_frame = debug_frame_.get(); 405e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) { 406e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris return true; 407e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris } 408e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris 409e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris // Finally try the gnu_debugdata interface, but always use a zero load bias. 410e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris if (gnu_debugdata_interface_ != nullptr && 411e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) { 4128098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris return true; 4138098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris } 4143958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 4153958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 4163958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 4173f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// This is an estimation of the size of the elf file using the location 4183f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// of the section headers and size. This assumes that the section headers 4193f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// are at the end of the elf file. If the elf has a load bias, the size 4203f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris// will be too large, but this is acceptable. 4213f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferristemplate <typename EhdrType> 4223f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferrisvoid ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) { 4233f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris EhdrType ehdr; 424ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) { 4253f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris return; 4263f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } 4273f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris if (ehdr.e_shnum == 0) { 4283f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris return; 4293f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } 4303f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; 4313f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris} 4323f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris 4333958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris// Instantiate all of the needed template functions. 43461d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferristemplate void ElfInterface::InitHeadersWithTemplate<uint32_t>(); 43561d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferristemplate void ElfInterface::InitHeadersWithTemplate<uint64_t>(); 43661d4097737c897847b7600d7d5ddbd384efb8540Christopher Ferris 437e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*); 438e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*); 4393958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 440e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, uint64_t*); 441e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, uint64_t*); 4423958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 4433958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&); 4443958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&); 4453958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 4463958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*); 4473958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferristemplate bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*); 4488098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris 449e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, uint64_t, std::string*, 4508098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t*); 451e69f470933f24977825bb34ee39d32650b75107fChristopher Ferristemplate bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, uint64_t, std::string*, 4528098b1c378cf999fda76c2dc0dfbdfaafc25adb9Christopher Ferris uint64_t*); 453d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 4543f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferristemplate void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*); 4553f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferristemplate void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*); 4563f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris 457b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferristemplate uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*); 458b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferristemplate uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*); 459b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 460d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} // namespace unwindstack 461