blob: 0e3ab2c8846e8ef831ed5b4935f898c190bf2e0a [file] [log] [blame]
Christopher Ferris3958f802017-02-01 15:44:40 -08001/*
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
Christopher Ferrisbae69f12017-06-28 14:51:54 -070023#include <7zCrc.h>
24#include <Xz.h>
25#include <XzCrc64.h>
26
Christopher Ferrisd226a512017-07-14 10:37:19 -070027#include <unwindstack/DwarfSection.h>
28#include <unwindstack/ElfInterface.h>
29#include <unwindstack/Log.h>
30#include <unwindstack/Memory.h>
31#include <unwindstack/Regs.h>
32
Christopher Ferris61d40972017-06-12 19:14:20 -070033#include "DwarfDebugFrame.h"
34#include "DwarfEhFrame.h"
Christopher Ferrisc9dee842017-11-03 14:50:27 -070035#include "DwarfEhFrameWithHdr.h"
Christopher Ferris8098b1c2017-06-20 13:54:08 -070036#include "Symbols.h"
37
Christopher Ferrisd226a512017-07-14 10:37:19 -070038namespace unwindstack {
39
Christopher Ferris8098b1c2017-06-20 13:54:08 -070040ElfInterface::~ElfInterface() {
41 for (auto symbol : symbols_) {
42 delete symbol;
43 }
44}
Christopher Ferris3958f802017-02-01 15:44:40 -080045
Christopher Ferris150db122017-12-20 18:49:01 -080046bool ElfInterface::IsValidPc(uint64_t pc) {
47 if (!pt_loads_.empty()) {
48 for (auto& entry : pt_loads_) {
49 uint64_t start = entry.second.table_offset;
50 uint64_t end = start + entry.second.table_size;
51 if (pc >= start && pc < end) {
52 return true;
53 }
54 }
55 return false;
56 }
57
58 // No PT_LOAD data, look for a fde for this pc in the section data.
59 if (debug_frame_ != nullptr && debug_frame_->GetFdeFromPc(pc) != nullptr) {
60 return true;
61 }
62
63 if (eh_frame_ != nullptr && eh_frame_->GetFdeFromPc(pc) != nullptr) {
64 return true;
65 }
66
67 return false;
68}
69
Christopher Ferrisbae69f12017-06-28 14:51:54 -070070Memory* ElfInterface::CreateGnuDebugdataMemory() {
71 if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) {
72 return nullptr;
73 }
74
75 // TODO: Only call these initialization functions once.
76 CrcGenerateTable();
77 Crc64GenerateTable();
78
79 std::vector<uint8_t> src(gnu_debugdata_size_);
Josh Gaoef35aa52017-10-18 11:44:51 -070080 if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
Christopher Ferrisbae69f12017-06-28 14:51:54 -070081 gnu_debugdata_offset_ = 0;
82 gnu_debugdata_size_ = static_cast<uint64_t>(-1);
83 return nullptr;
84 }
85
86 ISzAlloc alloc;
87 CXzUnpacker state;
88 alloc.Alloc = [](void*, size_t size) { return malloc(size); };
89 alloc.Free = [](void*, void* ptr) { return free(ptr); };
90
91 XzUnpacker_Construct(&state, &alloc);
92
93 std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
94 int return_val;
95 size_t src_offset = 0;
96 size_t dst_offset = 0;
97 ECoderStatus status;
98 dst->Resize(5 * gnu_debugdata_size_);
99 do {
100 size_t src_remaining = src.size() - src_offset;
101 size_t dst_remaining = dst->Size() - dst_offset;
102 if (dst_remaining < 2 * gnu_debugdata_size_) {
103 dst->Resize(dst->Size() + 2 * gnu_debugdata_size_);
104 dst_remaining += 2 * gnu_debugdata_size_;
105 }
106 return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset],
107 &src_remaining, CODER_FINISH_ANY, &status);
108 src_offset += src_remaining;
109 dst_offset += dst_remaining;
110 } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED);
111 XzUnpacker_Free(&state);
112 if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) {
113 gnu_debugdata_offset_ = 0;
114 gnu_debugdata_size_ = static_cast<uint64_t>(-1);
115 return nullptr;
116 }
117
118 // Shrink back down to the exact size.
119 dst->Resize(dst_offset);
120
121 return dst.release();
122}
123
Christopher Ferris61d40972017-06-12 19:14:20 -0700124template <typename AddressType>
125void ElfInterface::InitHeadersWithTemplate() {
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700126 if (eh_frame_hdr_offset_ != 0) {
127 eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
128 if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) {
129 // Even if the eh_frame_offset_ is non-zero, do not bother
130 // trying to read that since something has gone wrong.
131 eh_frame_.reset(nullptr);
132 eh_frame_hdr_offset_ = 0;
133 eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
134 }
135 } else if (eh_frame_offset_ != 0) {
136 // If there is a eh_frame section without a eh_frame_hdr section.
Christopher Ferris61d40972017-06-12 19:14:20 -0700137 eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
138 if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) {
139 eh_frame_.reset(nullptr);
140 eh_frame_offset_ = 0;
141 eh_frame_size_ = static_cast<uint64_t>(-1);
142 }
143 }
144
145 if (debug_frame_offset_ != 0) {
146 debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
147 if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_)) {
148 debug_frame_.reset(nullptr);
149 debug_frame_offset_ = 0;
150 debug_frame_size_ = static_cast<uint64_t>(-1);
151 }
152 }
153}
154
Christopher Ferris3958f802017-02-01 15:44:40 -0800155template <typename EhdrType, typename PhdrType, typename ShdrType>
Christopher Ferrise69f4702017-10-19 16:08:58 -0700156bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800157 EhdrType ehdr;
Josh Gaoef35aa52017-10-18 11:44:51 -0700158 if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800159 return false;
160 }
161
Christopher Ferrise69f4702017-10-19 16:08:58 -0700162 if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias)) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800163 return false;
164 }
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700165
166 // We could still potentially unwind without the section header
167 // information, so ignore any errors.
168 if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) {
169 log(0, "Malformed section header found, ignoring...");
170 }
171 return true;
Christopher Ferris3958f802017-02-01 15:44:40 -0800172}
173
174template <typename EhdrType, typename PhdrType>
Christopher Ferrisb7de5f52017-12-01 21:37:37 -0800175uint64_t ElfInterface::GetLoadBias(Memory* memory) {
176 EhdrType ehdr;
177 if (!memory->Read(0, &ehdr, sizeof(ehdr))) {
178 return false;
179 }
180
181 uint64_t offset = ehdr.e_phoff;
182 for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
183 PhdrType phdr;
184 if (!memory->Read(offset, &phdr, sizeof(phdr))) {
185 return 0;
186 }
187 if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
188 return phdr.p_vaddr;
189 }
190 }
191 return 0;
192}
193
194template <typename EhdrType, typename PhdrType>
Christopher Ferrise69f4702017-10-19 16:08:58 -0700195bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800196 uint64_t offset = ehdr.e_phoff;
197 for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
198 PhdrType phdr;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700199 if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800200 return false;
201 }
202
Christopher Ferrise69f4702017-10-19 16:08:58 -0700203 if (HandleType(offset, phdr.p_type, *load_bias)) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800204 continue;
205 }
206
207 switch (phdr.p_type) {
208 case PT_LOAD:
209 {
210 // Get the flags first, if this isn't an executable header, ignore it.
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700211 if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800212 return false;
213 }
214 if ((phdr.p_flags & PF_X) == 0) {
215 continue;
216 }
217
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700218 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800219 return false;
220 }
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700221 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800222 return false;
223 }
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700224 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800225 return false;
226 }
227 pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
228 static_cast<size_t>(phdr.p_memsz)};
229 if (phdr.p_offset == 0) {
Christopher Ferrise69f4702017-10-19 16:08:58 -0700230 *load_bias = phdr.p_vaddr;
Christopher Ferris3958f802017-02-01 15:44:40 -0800231 }
232 break;
233 }
234
235 case PT_GNU_EH_FRAME:
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700236 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800237 return false;
238 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700239 // This is really the pointer to the .eh_frame_hdr section.
240 eh_frame_hdr_offset_ = phdr.p_offset;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700241 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800242 return false;
243 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700244 eh_frame_hdr_size_ = phdr.p_memsz;
Christopher Ferris3958f802017-02-01 15:44:40 -0800245 break;
246
247 case PT_DYNAMIC:
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700248 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800249 return false;
250 }
251 dynamic_offset_ = phdr.p_offset;
Christopher Ferris150db122017-12-20 18:49:01 -0800252 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
253 return false;
254 }
255 dynamic_vaddr_ = phdr.p_vaddr;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700256 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800257 return false;
258 }
259 dynamic_size_ = phdr.p_memsz;
260 break;
261 }
262 }
263 return true;
264}
265
266template <typename EhdrType, typename ShdrType>
267bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
268 uint64_t offset = ehdr.e_shoff;
269 uint64_t sec_offset = 0;
270 uint64_t sec_size = 0;
271
272 // Get the location of the section header names.
273 // If something is malformed in the header table data, we aren't going
274 // to terminate, we'll simply ignore this part.
275 ShdrType shdr;
276 if (ehdr.e_shstrndx < ehdr.e_shnum) {
277 uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700278 if (memory_->ReadField(sh_offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
279 memory_->ReadField(sh_offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800280 sec_offset = shdr.sh_offset;
281 sec_size = shdr.sh_size;
282 }
283 }
284
285 // Skip the first header, it's always going to be NULL.
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700286 offset += ehdr.e_shentsize;
Christopher Ferris3958f802017-02-01 15:44:40 -0800287 for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700288 if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800289 return false;
290 }
291
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700292 if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
Josh Gaoef35aa52017-10-18 11:44:51 -0700293 if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700294 return false;
295 }
296 // Need to go get the information about the section that contains
297 // the string terminated names.
298 ShdrType str_shdr;
299 if (shdr.sh_link >= ehdr.e_shnum) {
300 return false;
301 }
302 uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
303 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) {
304 return false;
305 }
306 if (str_shdr.sh_type != SHT_STRTAB) {
307 return false;
308 }
309 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
310 sizeof(str_shdr.sh_offset))) {
311 return false;
312 }
313 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
314 return false;
315 }
316 symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
317 str_shdr.sh_offset, str_shdr.sh_size));
318 } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800319 // Look for the .debug_frame and .gnu_debugdata.
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700320 if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800321 return false;
322 }
323 if (shdr.sh_name < sec_size) {
324 std::string name;
325 if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700326 uint64_t* offset_ptr = nullptr;
327 uint64_t* size_ptr = nullptr;
Christopher Ferris3958f802017-02-01 15:44:40 -0800328 if (name == ".debug_frame") {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700329 offset_ptr = &debug_frame_offset_;
330 size_ptr = &debug_frame_size_;
Christopher Ferris3958f802017-02-01 15:44:40 -0800331 } else if (name == ".gnu_debugdata") {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700332 offset_ptr = &gnu_debugdata_offset_;
333 size_ptr = &gnu_debugdata_size_;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700334 } else if (name == ".eh_frame") {
335 offset_ptr = &eh_frame_offset_;
336 size_ptr = &eh_frame_size_;
337 } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
338 offset_ptr = &eh_frame_hdr_offset_;
339 size_ptr = &eh_frame_hdr_size_;
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700340 }
341 if (offset_ptr != nullptr &&
342 memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
343 memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
344 *offset_ptr = shdr.sh_offset;
345 *size_ptr = shdr.sh_size;
Christopher Ferris3958f802017-02-01 15:44:40 -0800346 }
347 }
348 }
349 }
350 }
351 return true;
352}
353
354template <typename DynType>
355bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
356 if (soname_type_ == SONAME_INVALID) {
357 return false;
358 }
359 if (soname_type_ == SONAME_VALID) {
360 *soname = soname_;
361 return true;
362 }
363
364 soname_type_ = SONAME_INVALID;
365
366 uint64_t soname_offset = 0;
367 uint64_t strtab_offset = 0;
368 uint64_t strtab_size = 0;
369
370 // Find the soname location from the dynamic headers section.
371 DynType dyn;
372 uint64_t offset = dynamic_offset_;
373 uint64_t max_offset = offset + dynamic_size_;
374 for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
Josh Gaoef35aa52017-10-18 11:44:51 -0700375 if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800376 return false;
377 }
378
379 if (dyn.d_tag == DT_STRTAB) {
380 strtab_offset = dyn.d_un.d_ptr;
381 } else if (dyn.d_tag == DT_STRSZ) {
382 strtab_size = dyn.d_un.d_val;
383 } else if (dyn.d_tag == DT_SONAME) {
384 soname_offset = dyn.d_un.d_val;
385 } else if (dyn.d_tag == DT_NULL) {
386 break;
387 }
388 }
389
390 soname_offset += strtab_offset;
391 if (soname_offset >= strtab_offset + strtab_size) {
392 return false;
393 }
394 if (!memory_->ReadString(soname_offset, &soname_)) {
395 return false;
396 }
397 soname_type_ = SONAME_VALID;
398 *soname = soname_;
399 return true;
400}
401
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700402template <typename SymType>
Christopher Ferrise69f4702017-10-19 16:08:58 -0700403bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name,
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700404 uint64_t* func_offset) {
405 if (symbols_.empty()) {
406 return false;
407 }
408
409 for (const auto symbol : symbols_) {
Christopher Ferrise69f4702017-10-19 16:08:58 -0700410 if (symbol->GetName<SymType>(addr, load_bias, memory_, name, func_offset)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700411 return true;
412 }
413 }
414 return false;
415}
416
Christopher Ferris150db122017-12-20 18:49:01 -0800417template <typename SymType>
418bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address) {
419 if (symbols_.empty()) {
420 return false;
421 }
422
423 for (const auto symbol : symbols_) {
424 if (symbol->GetGlobal<SymType>(memory_, name, memory_address)) {
425 return true;
426 }
427 }
428 return false;
429}
430
Christopher Ferrise7b66242017-12-15 11:17:45 -0800431bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory,
432 bool* finished) {
433 // Adjust the load bias to get the real relative pc.
434 if (pc < load_bias) {
435 return false;
436 }
437 uint64_t adjusted_pc = pc - load_bias;
438
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700439 // Try the eh_frame first.
440 DwarfSection* eh_frame = eh_frame_.get();
Christopher Ferrise7b66242017-12-15 11:17:45 -0800441 if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700442 return true;
443 }
444
445 // Try the debug_frame next.
446 DwarfSection* debug_frame = debug_frame_.get();
Christopher Ferrise7b66242017-12-15 11:17:45 -0800447 if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) {
448 return true;
449 }
450
451 // Finally try the gnu_debugdata interface, but always use a zero load bias.
452 if (gnu_debugdata_interface_ != nullptr &&
453 gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700454 return true;
455 }
Christopher Ferris3958f802017-02-01 15:44:40 -0800456 return false;
457}
458
Christopher Ferris3f805ac2017-08-30 13:15:19 -0700459// This is an estimation of the size of the elf file using the location
460// of the section headers and size. This assumes that the section headers
461// are at the end of the elf file. If the elf has a load bias, the size
462// will be too large, but this is acceptable.
463template <typename EhdrType>
464void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
465 EhdrType ehdr;
Josh Gaoef35aa52017-10-18 11:44:51 -0700466 if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
Christopher Ferris3f805ac2017-08-30 13:15:19 -0700467 return;
468 }
469 if (ehdr.e_shnum == 0) {
470 return;
471 }
472 *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
473}
474
Christopher Ferris3958f802017-02-01 15:44:40 -0800475// Instantiate all of the needed template functions.
Christopher Ferris61d40972017-06-12 19:14:20 -0700476template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
477template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
478
Christopher Ferrise69f4702017-10-19 16:08:58 -0700479template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
480template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
Christopher Ferris3958f802017-02-01 15:44:40 -0800481
Christopher Ferrise69f4702017-10-19 16:08:58 -0700482template bool ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, uint64_t*);
483template bool ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, uint64_t*);
Christopher Ferris3958f802017-02-01 15:44:40 -0800484
485template bool ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
486template bool ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
487
488template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
489template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700490
Christopher Ferrise69f4702017-10-19 16:08:58 -0700491template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, uint64_t, std::string*,
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700492 uint64_t*);
Christopher Ferrise69f4702017-10-19 16:08:58 -0700493template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, uint64_t, std::string*,
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700494 uint64_t*);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700495
Christopher Ferris150db122017-12-20 18:49:01 -0800496template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*);
497template bool ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(const std::string&, uint64_t*);
498
Christopher Ferris3f805ac2017-08-30 13:15:19 -0700499template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
500template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
501
Christopher Ferrisb7de5f52017-12-01 21:37:37 -0800502template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
503template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
504
Christopher Ferrisd226a512017-07-14 10:37:19 -0700505} // namespace unwindstack