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