Home | History | Annotate | Download | only in libunwindstack
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <elf.h>
     18 #include <stdint.h>
     19 
     20 #include <memory>
     21 #include <string>
     22 #include <utility>
     23 
     24 #include <7zCrc.h>
     25 #include <Xz.h>
     26 #include <XzCrc64.h>
     27 
     28 #include <unwindstack/DwarfError.h>
     29 #include <unwindstack/DwarfSection.h>
     30 #include <unwindstack/ElfInterface.h>
     31 #include <unwindstack/Log.h>
     32 #include <unwindstack/Memory.h>
     33 #include <unwindstack/Regs.h>
     34 
     35 #include "DwarfDebugFrame.h"
     36 #include "DwarfEhFrame.h"
     37 #include "DwarfEhFrameWithHdr.h"
     38 #include "Symbols.h"
     39 
     40 namespace unwindstack {
     41 
     42 ElfInterface::~ElfInterface() {
     43   for (auto symbol : symbols_) {
     44     delete symbol;
     45   }
     46 }
     47 
     48 bool ElfInterface::IsValidPc(uint64_t pc) {
     49   if (!pt_loads_.empty()) {
     50     for (auto& entry : pt_loads_) {
     51       uint64_t start = entry.second.table_offset;
     52       uint64_t end = start + entry.second.table_size;
     53       if (pc >= start && pc < end) {
     54         return true;
     55       }
     56     }
     57     return false;
     58   }
     59 
     60   // No PT_LOAD data, look for a fde for this pc in the section data.
     61   if (debug_frame_ != nullptr && debug_frame_->GetFdeFromPc(pc) != nullptr) {
     62     return true;
     63   }
     64 
     65   if (eh_frame_ != nullptr && eh_frame_->GetFdeFromPc(pc) != nullptr) {
     66     return true;
     67   }
     68 
     69   return false;
     70 }
     71 
     72 Memory* ElfInterface::CreateGnuDebugdataMemory() {
     73   if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) {
     74     return nullptr;
     75   }
     76 
     77   // TODO: Only call these initialization functions once.
     78   CrcGenerateTable();
     79   Crc64GenerateTable();
     80 
     81   std::vector<uint8_t> src(gnu_debugdata_size_);
     82   if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
     83     gnu_debugdata_offset_ = 0;
     84     gnu_debugdata_size_ = static_cast<uint64_t>(-1);
     85     return nullptr;
     86   }
     87 
     88   ISzAlloc alloc;
     89   CXzUnpacker state;
     90   alloc.Alloc = [](void*, size_t size) { return malloc(size); };
     91   alloc.Free = [](void*, void* ptr) { return free(ptr); };
     92 
     93   XzUnpacker_Construct(&state, &alloc);
     94 
     95   std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
     96   int return_val;
     97   size_t src_offset = 0;
     98   size_t dst_offset = 0;
     99   ECoderStatus status;
    100   dst->Resize(5 * gnu_debugdata_size_);
    101   do {
    102     size_t src_remaining = src.size() - src_offset;
    103     size_t dst_remaining = dst->Size() - dst_offset;
    104     if (dst_remaining < 2 * gnu_debugdata_size_) {
    105       dst->Resize(dst->Size() + 2 * gnu_debugdata_size_);
    106       dst_remaining += 2 * gnu_debugdata_size_;
    107     }
    108     return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset],
    109                                  &src_remaining, CODER_FINISH_ANY, &status);
    110     src_offset += src_remaining;
    111     dst_offset += dst_remaining;
    112   } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED);
    113   XzUnpacker_Free(&state);
    114   if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) {
    115     gnu_debugdata_offset_ = 0;
    116     gnu_debugdata_size_ = static_cast<uint64_t>(-1);
    117     return nullptr;
    118   }
    119 
    120   // Shrink back down to the exact size.
    121   dst->Resize(dst_offset);
    122 
    123   return dst.release();
    124 }
    125 
    126 template <typename AddressType>
    127 void ElfInterface::InitHeadersWithTemplate() {
    128   if (eh_frame_hdr_offset_ != 0) {
    129     eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
    130     if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) {
    131       eh_frame_.reset(nullptr);
    132     }
    133   }
    134 
    135   if (eh_frame_.get() == nullptr && eh_frame_offset_ != 0) {
    136     // If there is an eh_frame section without an eh_frame_hdr section,
    137     // or using the frame hdr object failed to init.
    138     eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
    139     if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) {
    140       eh_frame_.reset(nullptr);
    141     }
    142   }
    143 
    144   if (eh_frame_.get() == nullptr) {
    145     eh_frame_hdr_offset_ = 0;
    146     eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
    147     eh_frame_offset_ = 0;
    148     eh_frame_size_ = static_cast<uint64_t>(-1);
    149   }
    150 
    151   if (debug_frame_offset_ != 0) {
    152     debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
    153     if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_)) {
    154       debug_frame_.reset(nullptr);
    155       debug_frame_offset_ = 0;
    156       debug_frame_size_ = static_cast<uint64_t>(-1);
    157     }
    158   }
    159 }
    160 
    161 template <typename EhdrType, typename PhdrType, typename ShdrType>
    162 bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
    163   EhdrType ehdr;
    164   if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
    165     last_error_.code = ERROR_MEMORY_INVALID;
    166     last_error_.address = 0;
    167     return false;
    168   }
    169 
    170   if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias)) {
    171     return false;
    172   }
    173 
    174   // We could still potentially unwind without the section header
    175   // information, so ignore any errors.
    176   if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) {
    177     log(0, "Malformed section header found, ignoring...");
    178   }
    179   return true;
    180 }
    181 
    182 template <typename EhdrType, typename PhdrType>
    183 uint64_t ElfInterface::GetLoadBias(Memory* memory) {
    184   EhdrType ehdr;
    185   if (!memory->Read(0, &ehdr, sizeof(ehdr))) {
    186     return false;
    187   }
    188 
    189   uint64_t offset = ehdr.e_phoff;
    190   for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
    191     PhdrType phdr;
    192     if (!memory->Read(offset, &phdr, sizeof(phdr))) {
    193       return 0;
    194     }
    195     if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
    196       return phdr.p_vaddr;
    197     }
    198   }
    199   return 0;
    200 }
    201 
    202 template <typename EhdrType, typename PhdrType>
    203 bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
    204   uint64_t offset = ehdr.e_phoff;
    205   for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
    206     PhdrType phdr;
    207     if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) {
    208       last_error_.code = ERROR_MEMORY_INVALID;
    209       last_error_.address =
    210           offset + reinterpret_cast<uintptr_t>(&phdr.p_type) - reinterpret_cast<uintptr_t>(&phdr);
    211       return false;
    212     }
    213 
    214     if (HandleType(offset, phdr.p_type, *load_bias)) {
    215       continue;
    216     }
    217 
    218     switch (phdr.p_type) {
    219     case PT_LOAD:
    220     {
    221       // Get the flags first, if this isn't an executable header, ignore it.
    222       if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) {
    223         last_error_.code = ERROR_MEMORY_INVALID;
    224         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_flags) -
    225                               reinterpret_cast<uintptr_t>(&phdr);
    226         return false;
    227       }
    228       if ((phdr.p_flags & PF_X) == 0) {
    229         continue;
    230       }
    231 
    232       if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
    233         last_error_.code = ERROR_MEMORY_INVALID;
    234         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
    235                               reinterpret_cast<uintptr_t>(&phdr);
    236         return false;
    237       }
    238       if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
    239         last_error_.code = ERROR_MEMORY_INVALID;
    240         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
    241                               reinterpret_cast<uintptr_t>(&phdr);
    242         return false;
    243       }
    244       if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
    245         last_error_.code = ERROR_MEMORY_INVALID;
    246         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
    247                               reinterpret_cast<uintptr_t>(&phdr);
    248         return false;
    249       }
    250       pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
    251                                           static_cast<size_t>(phdr.p_memsz)};
    252       if (phdr.p_offset == 0) {
    253         *load_bias = phdr.p_vaddr;
    254       }
    255       break;
    256     }
    257 
    258     case PT_GNU_EH_FRAME:
    259       if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
    260         last_error_.code = ERROR_MEMORY_INVALID;
    261         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
    262                               reinterpret_cast<uintptr_t>(&phdr);
    263         return false;
    264       }
    265       // This is really the pointer to the .eh_frame_hdr section.
    266       eh_frame_hdr_offset_ = phdr.p_offset;
    267       if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
    268         last_error_.code = ERROR_MEMORY_INVALID;
    269         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
    270                               reinterpret_cast<uintptr_t>(&phdr);
    271         return false;
    272       }
    273       eh_frame_hdr_size_ = phdr.p_memsz;
    274       break;
    275 
    276     case PT_DYNAMIC:
    277       if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
    278         last_error_.code = ERROR_MEMORY_INVALID;
    279         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
    280                               reinterpret_cast<uintptr_t>(&phdr);
    281         return false;
    282       }
    283       dynamic_offset_ = phdr.p_offset;
    284       if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
    285         last_error_.code = ERROR_MEMORY_INVALID;
    286         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
    287                               reinterpret_cast<uintptr_t>(&phdr);
    288         return false;
    289       }
    290       dynamic_vaddr_ = phdr.p_vaddr;
    291       if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
    292         last_error_.code = ERROR_MEMORY_INVALID;
    293         last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
    294                               reinterpret_cast<uintptr_t>(&phdr);
    295         return false;
    296       }
    297       dynamic_size_ = phdr.p_memsz;
    298       break;
    299     }
    300   }
    301   return true;
    302 }
    303 
    304 template <typename EhdrType, typename ShdrType>
    305 bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
    306   uint64_t offset = ehdr.e_shoff;
    307   uint64_t sec_offset = 0;
    308   uint64_t sec_size = 0;
    309 
    310   // Get the location of the section header names.
    311   // If something is malformed in the header table data, we aren't going
    312   // to terminate, we'll simply ignore this part.
    313   ShdrType shdr;
    314   if (ehdr.e_shstrndx < ehdr.e_shnum) {
    315     uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
    316     if (memory_->ReadField(sh_offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
    317         memory_->ReadField(sh_offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
    318       sec_offset = shdr.sh_offset;
    319       sec_size = shdr.sh_size;
    320     }
    321   }
    322 
    323   // Skip the first header, it's always going to be NULL.
    324   offset += ehdr.e_shentsize;
    325   for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
    326     if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
    327       last_error_.code = ERROR_MEMORY_INVALID;
    328       last_error_.address = offset;
    329       return false;
    330     }
    331 
    332     if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
    333       // Need to go get the information about the section that contains
    334       // the string terminated names.
    335       ShdrType str_shdr;
    336       if (shdr.sh_link >= ehdr.e_shnum) {
    337         last_error_.code = ERROR_UNWIND_INFO;
    338         return false;
    339       }
    340       uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
    341       if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) {
    342         last_error_.code = ERROR_MEMORY_INVALID;
    343         last_error_.address = str_offset;
    344         return false;
    345       }
    346       if (str_shdr.sh_type != SHT_STRTAB) {
    347         last_error_.code = ERROR_UNWIND_INFO;
    348         return false;
    349       }
    350       symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
    351                                      str_shdr.sh_offset, str_shdr.sh_size));
    352     } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
    353       // Look for the .debug_frame and .gnu_debugdata.
    354       if (shdr.sh_name < sec_size) {
    355         std::string name;
    356         if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
    357           uint64_t* offset_ptr = nullptr;
    358           uint64_t* size_ptr = nullptr;
    359           if (name == ".debug_frame") {
    360             offset_ptr = &debug_frame_offset_;
    361             size_ptr = &debug_frame_size_;
    362           } else if (name == ".gnu_debugdata") {
    363             offset_ptr = &gnu_debugdata_offset_;
    364             size_ptr = &gnu_debugdata_size_;
    365           } else if (name == ".eh_frame") {
    366             offset_ptr = &eh_frame_offset_;
    367             size_ptr = &eh_frame_size_;
    368           } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
    369             offset_ptr = &eh_frame_hdr_offset_;
    370             size_ptr = &eh_frame_hdr_size_;
    371           }
    372           if (offset_ptr != nullptr) {
    373             *offset_ptr = shdr.sh_offset;
    374             *size_ptr = shdr.sh_size;
    375           }
    376         }
    377       }
    378     } else if (shdr.sh_type == SHT_STRTAB) {
    379       // In order to read soname, keep track of address to offset mapping.
    380       strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr),
    381                                                             static_cast<uint64_t>(shdr.sh_offset)));
    382     }
    383   }
    384   return true;
    385 }
    386 
    387 template <typename DynType>
    388 bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
    389   if (soname_type_ == SONAME_INVALID) {
    390     return false;
    391   }
    392   if (soname_type_ == SONAME_VALID) {
    393     *soname = soname_;
    394     return true;
    395   }
    396 
    397   soname_type_ = SONAME_INVALID;
    398 
    399   uint64_t soname_offset = 0;
    400   uint64_t strtab_addr = 0;
    401   uint64_t strtab_size = 0;
    402 
    403   // Find the soname location from the dynamic headers section.
    404   DynType dyn;
    405   uint64_t offset = dynamic_offset_;
    406   uint64_t max_offset = offset + dynamic_size_;
    407   for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
    408     if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
    409       last_error_.code = ERROR_MEMORY_INVALID;
    410       last_error_.address = offset;
    411       return false;
    412     }
    413 
    414     if (dyn.d_tag == DT_STRTAB) {
    415       strtab_addr = dyn.d_un.d_ptr;
    416     } else if (dyn.d_tag == DT_STRSZ) {
    417       strtab_size = dyn.d_un.d_val;
    418     } else if (dyn.d_tag == DT_SONAME) {
    419       soname_offset = dyn.d_un.d_val;
    420     } else if (dyn.d_tag == DT_NULL) {
    421       break;
    422     }
    423   }
    424 
    425   // Need to map the strtab address to the real offset.
    426   for (const auto& entry : strtabs_) {
    427     if (entry.first == strtab_addr) {
    428       soname_offset = entry.second + soname_offset;
    429       if (soname_offset >= entry.second + strtab_size) {
    430         return false;
    431       }
    432       if (!memory_->ReadString(soname_offset, &soname_)) {
    433         return false;
    434       }
    435       soname_type_ = SONAME_VALID;
    436       *soname = soname_;
    437       return true;
    438     }
    439   }
    440   return false;
    441 }
    442 
    443 template <typename SymType>
    444 bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name,
    445                                                uint64_t* func_offset) {
    446   if (symbols_.empty()) {
    447     return false;
    448   }
    449 
    450   for (const auto symbol : symbols_) {
    451     if (symbol->GetName<SymType>(addr, load_bias, memory_, name, func_offset)) {
    452       return true;
    453     }
    454   }
    455   return false;
    456 }
    457 
    458 template <typename SymType>
    459 bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address) {
    460   if (symbols_.empty()) {
    461     return false;
    462   }
    463 
    464   for (const auto symbol : symbols_) {
    465     if (symbol->GetGlobal<SymType>(memory_, name, memory_address)) {
    466       return true;
    467     }
    468   }
    469   return false;
    470 }
    471 
    472 bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory,
    473                         bool* finished) {
    474   last_error_.code = ERROR_NONE;
    475   last_error_.address = 0;
    476 
    477   // Adjust the load bias to get the real relative pc.
    478   if (pc < load_bias) {
    479     last_error_.code = ERROR_UNWIND_INFO;
    480     return false;
    481   }
    482   uint64_t adjusted_pc = pc - load_bias;
    483 
    484   // Try the debug_frame first since it contains the most specific unwind
    485   // information.
    486   DwarfSection* debug_frame = debug_frame_.get();
    487   if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) {
    488     return true;
    489   }
    490 
    491   // Try the eh_frame next.
    492   DwarfSection* eh_frame = eh_frame_.get();
    493   if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) {
    494     return true;
    495   }
    496 
    497   // Finally try the gnu_debugdata interface, but always use a zero load bias.
    498   if (gnu_debugdata_interface_ != nullptr &&
    499       gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) {
    500     return true;
    501   }
    502 
    503   // Set the error code based on the first error encountered.
    504   DwarfSection* section = nullptr;
    505   if (debug_frame_ != nullptr) {
    506     section = debug_frame_.get();
    507   } else if (eh_frame_ != nullptr) {
    508     section = eh_frame_.get();
    509   } else if (gnu_debugdata_interface_ != nullptr) {
    510     last_error_ = gnu_debugdata_interface_->last_error();
    511     return false;
    512   } else {
    513     return false;
    514   }
    515 
    516   // Convert the DWARF ERROR to an external error.
    517   DwarfErrorCode code = section->LastErrorCode();
    518   switch (code) {
    519     case DWARF_ERROR_NONE:
    520       last_error_.code = ERROR_NONE;
    521       break;
    522 
    523     case DWARF_ERROR_MEMORY_INVALID:
    524       last_error_.code = ERROR_MEMORY_INVALID;
    525       last_error_.address = section->LastErrorAddress();
    526       break;
    527 
    528     case DWARF_ERROR_ILLEGAL_VALUE:
    529     case DWARF_ERROR_ILLEGAL_STATE:
    530     case DWARF_ERROR_STACK_INDEX_NOT_VALID:
    531     case DWARF_ERROR_TOO_MANY_ITERATIONS:
    532     case DWARF_ERROR_CFA_NOT_DEFINED:
    533     case DWARF_ERROR_NO_FDES:
    534       last_error_.code = ERROR_UNWIND_INFO;
    535       break;
    536 
    537     case DWARF_ERROR_NOT_IMPLEMENTED:
    538     case DWARF_ERROR_UNSUPPORTED_VERSION:
    539       last_error_.code = ERROR_UNSUPPORTED;
    540       break;
    541   }
    542   return false;
    543 }
    544 
    545 // This is an estimation of the size of the elf file using the location
    546 // of the section headers and size. This assumes that the section headers
    547 // are at the end of the elf file. If the elf has a load bias, the size
    548 // will be too large, but this is acceptable.
    549 template <typename EhdrType>
    550 void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
    551   EhdrType ehdr;
    552   if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
    553     return;
    554   }
    555   if (ehdr.e_shnum == 0) {
    556     return;
    557   }
    558   *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
    559 }
    560 
    561 // Instantiate all of the needed template functions.
    562 template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
    563 template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
    564 
    565 template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
    566 template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
    567 
    568 template bool ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, uint64_t*);
    569 template bool ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, uint64_t*);
    570 
    571 template bool ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
    572 template bool ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
    573 
    574 template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
    575 template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
    576 
    577 template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, uint64_t, std::string*,
    578                                                                    uint64_t*);
    579 template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, uint64_t, std::string*,
    580                                                                    uint64_t*);
    581 
    582 template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*);
    583 template bool ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(const std::string&, uint64_t*);
    584 
    585 template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
    586 template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
    587 
    588 template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
    589 template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
    590 
    591 }  // namespace unwindstack
    592