blob: e41308171d781028135d933ea1df48f164172b2e [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 Ferris2fcf4cf2018-01-23 17:52:23 -080027#include <unwindstack/DwarfError.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070028#include <unwindstack/DwarfSection.h>
29#include <unwindstack/ElfInterface.h>
30#include <unwindstack/Log.h>
31#include <unwindstack/Memory.h>
32#include <unwindstack/Regs.h>
33
Christopher Ferris61d40972017-06-12 19:14:20 -070034#include "DwarfDebugFrame.h"
35#include "DwarfEhFrame.h"
Christopher Ferrisc9dee842017-11-03 14:50:27 -070036#include "DwarfEhFrameWithHdr.h"
Christopher Ferris8098b1c2017-06-20 13:54:08 -070037#include "Symbols.h"
38
Christopher Ferrisd226a512017-07-14 10:37:19 -070039namespace unwindstack {
40
Christopher Ferris8098b1c2017-06-20 13:54:08 -070041ElfInterface::~ElfInterface() {
42 for (auto symbol : symbols_) {
43 delete symbol;
44 }
45}
Christopher Ferris3958f802017-02-01 15:44:40 -080046
Christopher Ferris150db122017-12-20 18:49:01 -080047bool ElfInterface::IsValidPc(uint64_t pc) {
48 if (!pt_loads_.empty()) {
49 for (auto& entry : pt_loads_) {
50 uint64_t start = entry.second.table_offset;
51 uint64_t end = start + entry.second.table_size;
52 if (pc >= start && pc < end) {
53 return true;
54 }
55 }
56 return false;
57 }
58
59 // No PT_LOAD data, look for a fde for this pc in the section data.
60 if (debug_frame_ != nullptr && debug_frame_->GetFdeFromPc(pc) != nullptr) {
61 return true;
62 }
63
64 if (eh_frame_ != nullptr && eh_frame_->GetFdeFromPc(pc) != nullptr) {
65 return true;
66 }
67
68 return false;
69}
70
Christopher Ferrisbae69f12017-06-28 14:51:54 -070071Memory* ElfInterface::CreateGnuDebugdataMemory() {
72 if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) {
73 return nullptr;
74 }
75
76 // TODO: Only call these initialization functions once.
77 CrcGenerateTable();
78 Crc64GenerateTable();
79
80 std::vector<uint8_t> src(gnu_debugdata_size_);
Josh Gaoef35aa52017-10-18 11:44:51 -070081 if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
Christopher Ferrisbae69f12017-06-28 14:51:54 -070082 gnu_debugdata_offset_ = 0;
83 gnu_debugdata_size_ = static_cast<uint64_t>(-1);
84 return nullptr;
85 }
86
87 ISzAlloc alloc;
88 CXzUnpacker state;
89 alloc.Alloc = [](void*, size_t size) { return malloc(size); };
90 alloc.Free = [](void*, void* ptr) { return free(ptr); };
91
92 XzUnpacker_Construct(&state, &alloc);
93
94 std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
95 int return_val;
96 size_t src_offset = 0;
97 size_t dst_offset = 0;
98 ECoderStatus status;
99 dst->Resize(5 * gnu_debugdata_size_);
100 do {
101 size_t src_remaining = src.size() - src_offset;
102 size_t dst_remaining = dst->Size() - dst_offset;
103 if (dst_remaining < 2 * gnu_debugdata_size_) {
104 dst->Resize(dst->Size() + 2 * gnu_debugdata_size_);
105 dst_remaining += 2 * gnu_debugdata_size_;
106 }
107 return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset],
108 &src_remaining, CODER_FINISH_ANY, &status);
109 src_offset += src_remaining;
110 dst_offset += dst_remaining;
111 } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED);
112 XzUnpacker_Free(&state);
113 if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) {
114 gnu_debugdata_offset_ = 0;
115 gnu_debugdata_size_ = static_cast<uint64_t>(-1);
116 return nullptr;
117 }
118
119 // Shrink back down to the exact size.
120 dst->Resize(dst_offset);
121
122 return dst.release();
123}
124
Christopher Ferris61d40972017-06-12 19:14:20 -0700125template <typename AddressType>
126void ElfInterface::InitHeadersWithTemplate() {
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700127 if (eh_frame_hdr_offset_ != 0) {
128 eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
129 if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) {
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700130 eh_frame_.reset(nullptr);
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700131 }
Christopher Ferris1a141a02018-01-24 08:52:47 -0800132 }
133
134 if (eh_frame_.get() == nullptr && eh_frame_offset_ != 0) {
135 // If there is an eh_frame section without an eh_frame_hdr section,
136 // or using the frame hdr object failed to init.
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);
Christopher Ferris61d40972017-06-12 19:14:20 -0700140 }
141 }
142
Christopher Ferris1a141a02018-01-24 08:52:47 -0800143 if (eh_frame_.get() == nullptr) {
144 eh_frame_hdr_offset_ = 0;
145 eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
146 eh_frame_offset_ = 0;
147 eh_frame_size_ = static_cast<uint64_t>(-1);
148 }
149
Christopher Ferris61d40972017-06-12 19:14:20 -0700150 if (debug_frame_offset_ != 0) {
151 debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
152 if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_)) {
153 debug_frame_.reset(nullptr);
154 debug_frame_offset_ = 0;
155 debug_frame_size_ = static_cast<uint64_t>(-1);
156 }
157 }
158}
159
Christopher Ferris3958f802017-02-01 15:44:40 -0800160template <typename EhdrType, typename PhdrType, typename ShdrType>
Christopher Ferrise69f4702017-10-19 16:08:58 -0700161bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800162 EhdrType ehdr;
Josh Gaoef35aa52017-10-18 11:44:51 -0700163 if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800164 last_error_.code = ERROR_MEMORY_INVALID;
165 last_error_.address = 0;
Christopher Ferris3958f802017-02-01 15:44:40 -0800166 return false;
167 }
168
Christopher Ferrise69f4702017-10-19 16:08:58 -0700169 if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias)) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800170 return false;
171 }
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700172
173 // We could still potentially unwind without the section header
174 // information, so ignore any errors.
175 if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) {
176 log(0, "Malformed section header found, ignoring...");
177 }
178 return true;
Christopher Ferris3958f802017-02-01 15:44:40 -0800179}
180
181template <typename EhdrType, typename PhdrType>
Christopher Ferrisb7de5f52017-12-01 21:37:37 -0800182uint64_t ElfInterface::GetLoadBias(Memory* memory) {
183 EhdrType ehdr;
184 if (!memory->Read(0, &ehdr, sizeof(ehdr))) {
185 return false;
186 }
187
188 uint64_t offset = ehdr.e_phoff;
189 for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
190 PhdrType phdr;
191 if (!memory->Read(offset, &phdr, sizeof(phdr))) {
192 return 0;
193 }
194 if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
195 return phdr.p_vaddr;
196 }
197 }
198 return 0;
199}
200
201template <typename EhdrType, typename PhdrType>
Christopher Ferrise69f4702017-10-19 16:08:58 -0700202bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800203 uint64_t offset = ehdr.e_phoff;
204 for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
205 PhdrType phdr;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700206 if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800207 last_error_.code = ERROR_MEMORY_INVALID;
208 last_error_.address =
209 offset + reinterpret_cast<uintptr_t>(&phdr.p_type) - reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800210 return false;
211 }
212
Christopher Ferrise69f4702017-10-19 16:08:58 -0700213 if (HandleType(offset, phdr.p_type, *load_bias)) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800214 continue;
215 }
216
217 switch (phdr.p_type) {
218 case PT_LOAD:
219 {
220 // Get the flags first, if this isn't an executable header, ignore it.
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700221 if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800222 last_error_.code = ERROR_MEMORY_INVALID;
223 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_flags) -
224 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800225 return false;
226 }
227 if ((phdr.p_flags & PF_X) == 0) {
228 continue;
229 }
230
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700231 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800232 last_error_.code = ERROR_MEMORY_INVALID;
233 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
234 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800235 return false;
236 }
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700237 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800238 last_error_.code = ERROR_MEMORY_INVALID;
239 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
240 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800241 return false;
242 }
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700243 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800244 last_error_.code = ERROR_MEMORY_INVALID;
245 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
246 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800247 return false;
248 }
249 pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
250 static_cast<size_t>(phdr.p_memsz)};
251 if (phdr.p_offset == 0) {
Christopher Ferrise69f4702017-10-19 16:08:58 -0700252 *load_bias = phdr.p_vaddr;
Christopher Ferris3958f802017-02-01 15:44:40 -0800253 }
254 break;
255 }
256
257 case PT_GNU_EH_FRAME:
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700258 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800259 last_error_.code = ERROR_MEMORY_INVALID;
260 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
261 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800262 return false;
263 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700264 // This is really the pointer to the .eh_frame_hdr section.
265 eh_frame_hdr_offset_ = phdr.p_offset;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700266 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800267 last_error_.code = ERROR_MEMORY_INVALID;
268 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
269 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800270 return false;
271 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700272 eh_frame_hdr_size_ = phdr.p_memsz;
Christopher Ferris3958f802017-02-01 15:44:40 -0800273 break;
274
275 case PT_DYNAMIC:
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700276 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800277 last_error_.code = ERROR_MEMORY_INVALID;
278 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
279 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800280 return false;
281 }
282 dynamic_offset_ = phdr.p_offset;
Christopher Ferris150db122017-12-20 18:49:01 -0800283 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800284 last_error_.code = ERROR_MEMORY_INVALID;
285 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
286 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris150db122017-12-20 18:49:01 -0800287 return false;
288 }
289 dynamic_vaddr_ = phdr.p_vaddr;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700290 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800291 last_error_.code = ERROR_MEMORY_INVALID;
292 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
293 reinterpret_cast<uintptr_t>(&phdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800294 return false;
295 }
296 dynamic_size_ = phdr.p_memsz;
297 break;
298 }
299 }
300 return true;
301}
302
303template <typename EhdrType, typename ShdrType>
304bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
305 uint64_t offset = ehdr.e_shoff;
306 uint64_t sec_offset = 0;
307 uint64_t sec_size = 0;
308
309 // Get the location of the section header names.
310 // If something is malformed in the header table data, we aren't going
311 // to terminate, we'll simply ignore this part.
312 ShdrType shdr;
313 if (ehdr.e_shstrndx < ehdr.e_shnum) {
314 uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700315 if (memory_->ReadField(sh_offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
316 memory_->ReadField(sh_offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800317 sec_offset = shdr.sh_offset;
318 sec_size = shdr.sh_size;
319 }
320 }
321
322 // Skip the first header, it's always going to be NULL.
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700323 offset += ehdr.e_shentsize;
Christopher Ferris3958f802017-02-01 15:44:40 -0800324 for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700325 if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800326 last_error_.code = ERROR_MEMORY_INVALID;
327 last_error_.address =
328 offset + reinterpret_cast<uintptr_t>(&shdr.sh_type) - reinterpret_cast<uintptr_t>(&shdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800329 return false;
330 }
331
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700332 if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
Josh Gaoef35aa52017-10-18 11:44:51 -0700333 if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800334 last_error_.code = ERROR_MEMORY_INVALID;
335 last_error_.address = offset;
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700336 return false;
337 }
338 // Need to go get the information about the section that contains
339 // the string terminated names.
340 ShdrType str_shdr;
341 if (shdr.sh_link >= ehdr.e_shnum) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800342 last_error_.code = ERROR_UNWIND_INFO;
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700343 return false;
344 }
345 uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
346 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800347 last_error_.code = ERROR_MEMORY_INVALID;
348 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_type) -
349 reinterpret_cast<uintptr_t>(&str_shdr);
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700350 return false;
351 }
352 if (str_shdr.sh_type != SHT_STRTAB) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800353 last_error_.code = ERROR_UNWIND_INFO;
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700354 return false;
355 }
356 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
357 sizeof(str_shdr.sh_offset))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800358 last_error_.code = ERROR_MEMORY_INVALID;
359 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_offset) -
360 reinterpret_cast<uintptr_t>(&str_shdr);
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700361 return false;
362 }
363 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800364 last_error_.code = ERROR_MEMORY_INVALID;
365 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_size) -
366 reinterpret_cast<uintptr_t>(&str_shdr);
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700367 return false;
368 }
369 symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
370 str_shdr.sh_offset, str_shdr.sh_size));
371 } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800372 // Look for the .debug_frame and .gnu_debugdata.
Christopher Ferrisf447c8e2017-04-03 12:39:47 -0700373 if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800374 last_error_.code = ERROR_MEMORY_INVALID;
375 last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_name) -
376 reinterpret_cast<uintptr_t>(&shdr);
Christopher Ferris3958f802017-02-01 15:44:40 -0800377 return false;
378 }
379 if (shdr.sh_name < sec_size) {
380 std::string name;
381 if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700382 uint64_t* offset_ptr = nullptr;
383 uint64_t* size_ptr = nullptr;
Christopher Ferris3958f802017-02-01 15:44:40 -0800384 if (name == ".debug_frame") {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700385 offset_ptr = &debug_frame_offset_;
386 size_ptr = &debug_frame_size_;
Christopher Ferris3958f802017-02-01 15:44:40 -0800387 } else if (name == ".gnu_debugdata") {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700388 offset_ptr = &gnu_debugdata_offset_;
389 size_ptr = &gnu_debugdata_size_;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700390 } else if (name == ".eh_frame") {
391 offset_ptr = &eh_frame_offset_;
392 size_ptr = &eh_frame_size_;
393 } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
394 offset_ptr = &eh_frame_hdr_offset_;
395 size_ptr = &eh_frame_hdr_size_;
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700396 }
397 if (offset_ptr != nullptr &&
398 memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
399 memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
400 *offset_ptr = shdr.sh_offset;
401 *size_ptr = shdr.sh_size;
Christopher Ferris3958f802017-02-01 15:44:40 -0800402 }
403 }
404 }
405 }
406 }
407 return true;
408}
409
410template <typename DynType>
411bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
412 if (soname_type_ == SONAME_INVALID) {
413 return false;
414 }
415 if (soname_type_ == SONAME_VALID) {
416 *soname = soname_;
417 return true;
418 }
419
420 soname_type_ = SONAME_INVALID;
421
422 uint64_t soname_offset = 0;
423 uint64_t strtab_offset = 0;
424 uint64_t strtab_size = 0;
425
426 // Find the soname location from the dynamic headers section.
427 DynType dyn;
428 uint64_t offset = dynamic_offset_;
429 uint64_t max_offset = offset + dynamic_size_;
430 for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
Josh Gaoef35aa52017-10-18 11:44:51 -0700431 if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800432 last_error_.code = ERROR_MEMORY_INVALID;
433 last_error_.address = offset;
Christopher Ferris3958f802017-02-01 15:44:40 -0800434 return false;
435 }
436
437 if (dyn.d_tag == DT_STRTAB) {
438 strtab_offset = dyn.d_un.d_ptr;
439 } else if (dyn.d_tag == DT_STRSZ) {
440 strtab_size = dyn.d_un.d_val;
441 } else if (dyn.d_tag == DT_SONAME) {
442 soname_offset = dyn.d_un.d_val;
443 } else if (dyn.d_tag == DT_NULL) {
444 break;
445 }
446 }
447
448 soname_offset += strtab_offset;
449 if (soname_offset >= strtab_offset + strtab_size) {
450 return false;
451 }
452 if (!memory_->ReadString(soname_offset, &soname_)) {
453 return false;
454 }
455 soname_type_ = SONAME_VALID;
456 *soname = soname_;
457 return true;
458}
459
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700460template <typename SymType>
Christopher Ferrise69f4702017-10-19 16:08:58 -0700461bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name,
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700462 uint64_t* func_offset) {
463 if (symbols_.empty()) {
464 return false;
465 }
466
467 for (const auto symbol : symbols_) {
Christopher Ferrise69f4702017-10-19 16:08:58 -0700468 if (symbol->GetName<SymType>(addr, load_bias, memory_, name, func_offset)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700469 return true;
470 }
471 }
472 return false;
473}
474
Christopher Ferris150db122017-12-20 18:49:01 -0800475template <typename SymType>
476bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address) {
477 if (symbols_.empty()) {
478 return false;
479 }
480
481 for (const auto symbol : symbols_) {
482 if (symbol->GetGlobal<SymType>(memory_, name, memory_address)) {
483 return true;
484 }
485 }
486 return false;
487}
488
Christopher Ferrise7b66242017-12-15 11:17:45 -0800489bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory,
490 bool* finished) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800491 last_error_.code = ERROR_NONE;
492 last_error_.address = 0;
493
Christopher Ferrise7b66242017-12-15 11:17:45 -0800494 // Adjust the load bias to get the real relative pc.
495 if (pc < load_bias) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800496 last_error_.code = ERROR_UNWIND_INFO;
Christopher Ferrise7b66242017-12-15 11:17:45 -0800497 return false;
498 }
499 uint64_t adjusted_pc = pc - load_bias;
500
Christopher Ferris1a141a02018-01-24 08:52:47 -0800501 // Try the debug_frame first since it contains the most specific unwind
502 // information.
503 DwarfSection* debug_frame = debug_frame_.get();
504 if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700505 return true;
506 }
507
Christopher Ferris1a141a02018-01-24 08:52:47 -0800508 // Try the eh_frame next.
509 DwarfSection* eh_frame = eh_frame_.get();
510 if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) {
Christopher Ferrise7b66242017-12-15 11:17:45 -0800511 return true;
512 }
513
514 // Finally try the gnu_debugdata interface, but always use a zero load bias.
515 if (gnu_debugdata_interface_ != nullptr &&
516 gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) {
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700517 return true;
518 }
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800519
520 // Set the error code based on the first error encountered.
521 DwarfSection* section = nullptr;
522 if (debug_frame_ != nullptr) {
523 section = debug_frame_.get();
524 } else if (eh_frame_ != nullptr) {
525 section = eh_frame_.get();
526 } else if (gnu_debugdata_interface_ != nullptr) {
527 last_error_ = gnu_debugdata_interface_->last_error();
528 return false;
529 } else {
530 return false;
531 }
532
533 // Convert the DWARF ERROR to an external error.
534 DwarfErrorCode code = section->LastErrorCode();
535 switch (code) {
536 case DWARF_ERROR_NONE:
537 last_error_.code = ERROR_NONE;
538 break;
539
540 case DWARF_ERROR_MEMORY_INVALID:
541 last_error_.code = ERROR_MEMORY_INVALID;
542 last_error_.address = section->LastErrorAddress();
543 break;
544
545 case DWARF_ERROR_ILLEGAL_VALUE:
546 case DWARF_ERROR_ILLEGAL_STATE:
547 case DWARF_ERROR_STACK_INDEX_NOT_VALID:
548 case DWARF_ERROR_TOO_MANY_ITERATIONS:
549 case DWARF_ERROR_CFA_NOT_DEFINED:
550 case DWARF_ERROR_NO_FDES:
551 last_error_.code = ERROR_UNWIND_INFO;
552 break;
553
554 case DWARF_ERROR_NOT_IMPLEMENTED:
555 case DWARF_ERROR_UNSUPPORTED_VERSION:
556 last_error_.code = ERROR_UNSUPPORTED;
557 break;
558 }
Christopher Ferris3958f802017-02-01 15:44:40 -0800559 return false;
560}
561
Christopher Ferris3f805ac2017-08-30 13:15:19 -0700562// This is an estimation of the size of the elf file using the location
563// of the section headers and size. This assumes that the section headers
564// are at the end of the elf file. If the elf has a load bias, the size
565// will be too large, but this is acceptable.
566template <typename EhdrType>
567void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
568 EhdrType ehdr;
Josh Gaoef35aa52017-10-18 11:44:51 -0700569 if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
Christopher Ferris3f805ac2017-08-30 13:15:19 -0700570 return;
571 }
572 if (ehdr.e_shnum == 0) {
573 return;
574 }
575 *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
576}
577
Christopher Ferris3958f802017-02-01 15:44:40 -0800578// Instantiate all of the needed template functions.
Christopher Ferris61d40972017-06-12 19:14:20 -0700579template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
580template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
581
Christopher Ferrise69f4702017-10-19 16:08:58 -0700582template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
583template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
Christopher Ferris3958f802017-02-01 15:44:40 -0800584
Christopher Ferrise69f4702017-10-19 16:08:58 -0700585template bool ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, uint64_t*);
586template bool ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, uint64_t*);
Christopher Ferris3958f802017-02-01 15:44:40 -0800587
588template bool ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
589template bool ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
590
591template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
592template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700593
Christopher Ferrise69f4702017-10-19 16:08:58 -0700594template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, uint64_t, std::string*,
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700595 uint64_t*);
Christopher Ferrise69f4702017-10-19 16:08:58 -0700596template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, uint64_t, std::string*,
Christopher Ferris8098b1c2017-06-20 13:54:08 -0700597 uint64_t*);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700598
Christopher Ferris150db122017-12-20 18:49:01 -0800599template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*);
600template bool ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(const std::string&, uint64_t*);
601
Christopher Ferris3f805ac2017-08-30 13:15:19 -0700602template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
603template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
604
Christopher Ferrisb7de5f52017-12-01 21:37:37 -0800605template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
606template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
607
Christopher Ferrisd226a512017-07-14 10:37:19 -0700608} // namespace unwindstack