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