1 /*
2 * Copyright (C) 2016 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 <inttypes.h>
19 #include <string.h>
20 #include <sys/mman.h>
21
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <utility>
26
27 #include <android-base/stringprintf.h>
28
29 #include <unwindstack/Elf.h>
30 #include <unwindstack/ElfInterface.h>
31 #include <unwindstack/Log.h>
32 #include <unwindstack/MapInfo.h>
33 #include <unwindstack/Memory.h>
34 #include <unwindstack/Regs.h>
35 #include <unwindstack/SharedString.h>
36
37 #include <android-base/stringprintf.h>
38
39 #include "ElfInterfaceArm.h"
40 #include "Symbols.h"
41
42 namespace unwindstack {
43
44 bool Elf::cache_enabled_;
45 std::unordered_map<std::string, std::unordered_map<uint64_t, std::shared_ptr<Elf>>>* Elf::cache_;
46 std::mutex* Elf::cache_lock_;
47
Init()48 bool Elf::Init() {
49 load_bias_ = 0;
50 if (!memory_) {
51 return false;
52 }
53
54 interface_.reset(CreateInterfaceFromMemory(memory_));
55 if (!interface_) {
56 return false;
57 }
58
59 valid_ = interface_->Init(&load_bias_);
60 if (valid_) {
61 interface_->InitHeaders();
62 InitGnuDebugdata();
63 } else {
64 interface_.reset(nullptr);
65 }
66 return valid_;
67 }
68
69 // It is expensive to initialize the .gnu_debugdata section. Provide a method
70 // to initialize this data separately.
InitGnuDebugdata()71 void Elf::InitGnuDebugdata() {
72 if (!valid_ || interface_->gnu_debugdata_offset() == 0) {
73 return;
74 }
75
76 auto memory = interface_->CreateGnuDebugdataMemory();
77 gnu_debugdata_interface_.reset(CreateInterfaceFromMemory(memory));
78 ElfInterface* gnu = gnu_debugdata_interface_.get();
79 if (gnu == nullptr) {
80 return;
81 }
82
83 // Ignore the load_bias from the compressed section, the correct load bias
84 // is in the uncompressed data.
85 int64_t load_bias;
86 if (gnu->Init(&load_bias)) {
87 gnu->InitHeaders();
88 interface_->SetGnuDebugdataInterface(gnu);
89 } else {
90 gnu_debugdata_interface_.reset(nullptr);
91 }
92 }
93
Invalidate()94 void Elf::Invalidate() {
95 interface_.reset(nullptr);
96 valid_ = false;
97 }
98
GetSoname()99 std::string Elf::GetSoname() {
100 std::lock_guard<std::mutex> guard(lock_);
101 if (!valid_) {
102 return "";
103 }
104 return interface_->GetSoname();
105 }
106
GetRelPc(uint64_t pc,MapInfo * map_info)107 uint64_t Elf::GetRelPc(uint64_t pc, MapInfo* map_info) {
108 return pc - map_info->start() + load_bias_ + map_info->elf_offset();
109 }
110
GetFunctionName(uint64_t addr,SharedString * name,uint64_t * func_offset)111 bool Elf::GetFunctionName(uint64_t addr, SharedString* name, uint64_t* func_offset) {
112 std::lock_guard<std::mutex> guard(lock_);
113 return valid_ && (interface_->GetFunctionName(addr, name, func_offset) ||
114 (gnu_debugdata_interface_ &&
115 gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
116 }
117
GetGlobalVariableOffset(const std::string & name,uint64_t * memory_offset)118 bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) {
119 if (!valid_) {
120 return false;
121 }
122
123 uint64_t vaddr;
124 if (!interface_->GetGlobalVariable(name, &vaddr) &&
125 (gnu_debugdata_interface_ == nullptr ||
126 !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) {
127 return false;
128 }
129
130 if (arch() == ARCH_ARM64) {
131 // Tagged pointer after Android R would lead top byte to have random values
132 // https://source.android.com/devices/tech/debug/tagged-pointers
133 vaddr &= (1ULL << 56) - 1;
134 }
135
136 // Check the .data section.
137 uint64_t vaddr_start = interface_->data_vaddr_start();
138 if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) {
139 *memory_offset = vaddr - vaddr_start + interface_->data_offset();
140 return true;
141 }
142
143 // Check the .dynamic section.
144 vaddr_start = interface_->dynamic_vaddr_start();
145 if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) {
146 *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset();
147 return true;
148 }
149
150 return false;
151 }
152
GetBuildID()153 std::string Elf::GetBuildID() {
154 if (!valid_) {
155 return "";
156 }
157 return interface_->GetBuildID();
158 }
159
GetLastError(ErrorData * data)160 void Elf::GetLastError(ErrorData* data) {
161 if (valid_) {
162 *data = interface_->last_error();
163 } else {
164 data->code = ERROR_INVALID_ELF;
165 data->address = 0;
166 }
167 }
168
GetLastErrorCode()169 ErrorCode Elf::GetLastErrorCode() {
170 if (valid_) {
171 return interface_->LastErrorCode();
172 }
173 return ERROR_INVALID_ELF;
174 }
175
GetLastErrorAddress()176 uint64_t Elf::GetLastErrorAddress() {
177 if (valid_) {
178 return interface_->LastErrorAddress();
179 }
180 return 0;
181 }
182
183 // The relative pc expectd by this function is relative to the start of the elf.
StepIfSignalHandler(uint64_t rel_pc,Regs * regs,Memory * process_memory)184 bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
185 if (!valid_) {
186 return false;
187 }
188
189 // Convert the rel_pc to an elf_offset.
190 if (rel_pc < static_cast<uint64_t>(load_bias_)) {
191 return false;
192 }
193 return regs->StepIfSignalHandler(rel_pc - load_bias_, this, process_memory);
194 }
195
196 // The relative pc is always relative to the start of the map from which it comes.
Step(uint64_t rel_pc,Regs * regs,Memory * process_memory,bool * finished,bool * is_signal_frame)197 bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
198 bool* is_signal_frame) {
199 if (!valid_) {
200 return false;
201 }
202
203 // Lock during the step which can update information in the object.
204 std::lock_guard<std::mutex> guard(lock_);
205 return interface_->Step(rel_pc, regs, process_memory, finished, is_signal_frame);
206 }
207
IsValidElf(Memory * memory)208 bool Elf::IsValidElf(Memory* memory) {
209 if (memory == nullptr) {
210 return false;
211 }
212
213 // Verify that this is a valid elf file.
214 uint8_t e_ident[SELFMAG + 1];
215 if (!memory->ReadFully(0, e_ident, SELFMAG)) {
216 return false;
217 }
218
219 if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
220 return false;
221 }
222 return true;
223 }
224
GetInfo(Memory * memory,uint64_t * size)225 bool Elf::GetInfo(Memory* memory, uint64_t* size) {
226 if (!IsValidElf(memory)) {
227 return false;
228 }
229 *size = 0;
230
231 uint8_t class_type;
232 if (!memory->ReadFully(EI_CLASS, &class_type, 1)) {
233 return false;
234 }
235
236 // Get the maximum size of the elf data from the header.
237 if (class_type == ELFCLASS32) {
238 ElfInterface32::GetMaxSize(memory, size);
239 } else if (class_type == ELFCLASS64) {
240 ElfInterface64::GetMaxSize(memory, size);
241 } else {
242 return false;
243 }
244 return true;
245 }
246
IsValidPc(uint64_t pc)247 bool Elf::IsValidPc(uint64_t pc) {
248 if (!valid_ || (load_bias_ > 0 && pc < static_cast<uint64_t>(load_bias_))) {
249 return false;
250 }
251
252 if (interface_->IsValidPc(pc)) {
253 return true;
254 }
255
256 if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->IsValidPc(pc)) {
257 return true;
258 }
259
260 return false;
261 }
262
GetTextRange(uint64_t * addr,uint64_t * size)263 bool Elf::GetTextRange(uint64_t* addr, uint64_t* size) {
264 if (!valid_) {
265 return false;
266 }
267
268 if (interface_->GetTextRange(addr, size)) {
269 *addr += load_bias_;
270 return true;
271 }
272
273 if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->GetTextRange(addr, size)) {
274 *addr += load_bias_;
275 return true;
276 }
277
278 return false;
279 }
280
CreateInterfaceFromMemory(std::shared_ptr<Memory> & memory)281 ElfInterface* Elf::CreateInterfaceFromMemory(std::shared_ptr<Memory>& memory) {
282 if (!IsValidElf(memory.get())) {
283 return nullptr;
284 }
285
286 std::unique_ptr<ElfInterface> interface;
287 if (!memory->ReadFully(EI_CLASS, &class_type_, 1)) {
288 return nullptr;
289 }
290 if (class_type_ == ELFCLASS32) {
291 Elf32_Half e_machine;
292 if (!memory->ReadFully(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) {
293 return nullptr;
294 }
295
296 machine_type_ = e_machine;
297 if (e_machine == EM_ARM) {
298 arch_ = ARCH_ARM;
299 interface.reset(new ElfInterfaceArm(memory));
300 } else if (e_machine == EM_386) {
301 arch_ = ARCH_X86;
302 interface.reset(new ElfInterface32(memory));
303 } else {
304 // Unsupported.
305 return nullptr;
306 }
307 } else if (class_type_ == ELFCLASS64) {
308 Elf64_Half e_machine;
309 if (!memory->ReadFully(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
310 return nullptr;
311 }
312
313 machine_type_ = e_machine;
314 if (e_machine == EM_AARCH64) {
315 arch_ = ARCH_ARM64;
316 } else if (e_machine == EM_X86_64) {
317 arch_ = ARCH_X86_64;
318 } else if (e_machine == EM_RISCV) {
319 arch_ = ARCH_RISCV64;
320 } else {
321 // Unsupported.
322 return nullptr;
323 }
324 interface.reset(new ElfInterface64(memory));
325 }
326
327 return interface.release();
328 }
329
GetLoadBias(Memory * memory)330 int64_t Elf::GetLoadBias(Memory* memory) {
331 if (!IsValidElf(memory)) {
332 return 0;
333 }
334
335 uint8_t class_type;
336 if (!memory->Read(EI_CLASS, &class_type, 1)) {
337 return 0;
338 }
339
340 if (class_type == ELFCLASS32) {
341 return ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(memory);
342 } else if (class_type == ELFCLASS64) {
343 return ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(memory);
344 }
345 return 0;
346 }
347
SetCachingEnabled(bool enable)348 void Elf::SetCachingEnabled(bool enable) {
349 if (!cache_enabled_ && enable) {
350 cache_enabled_ = true;
351 cache_ =
352 new std::unordered_map<std::string, std::unordered_map<uint64_t, std::shared_ptr<Elf>>>;
353 cache_lock_ = new std::mutex;
354 } else if (cache_enabled_ && !enable) {
355 cache_enabled_ = false;
356 delete cache_;
357 delete cache_lock_;
358 }
359 }
360
CacheLock()361 void Elf::CacheLock() {
362 cache_lock_->lock();
363 }
364
CacheUnlock()365 void Elf::CacheUnlock() {
366 cache_lock_->unlock();
367 }
368
CacheAdd(MapInfo * info)369 void Elf::CacheAdd(MapInfo* info) {
370 if (!info->elf()->valid()) {
371 return;
372 }
373 (*cache_)[std::string(info->name())].emplace(info->elf_start_offset(), info->elf());
374 }
375
CacheGet(MapInfo * info)376 bool Elf::CacheGet(MapInfo* info) {
377 auto name_entry = cache_->find(std::string(info->name()));
378 if (name_entry == cache_->end()) {
379 return false;
380 }
381 // First look to see if there is a zero offset entry, this indicates
382 // the whole elf is the file.
383 auto& offset_cache = name_entry->second;
384 uint64_t elf_start_offset = 0;
385 auto entry = offset_cache.find(elf_start_offset);
386 if (entry == offset_cache.end()) {
387 // Try and find using the current offset.
388 elf_start_offset = info->offset();
389 entry = offset_cache.find(elf_start_offset);
390 if (entry == offset_cache.end()) {
391 // If this is an execute map, then see if the previous read-only
392 // map is the start of the elf.
393 if (!(info->flags() & PROT_EXEC)) {
394 return false;
395 }
396 auto prev_map = info->GetPrevRealMap();
397 if (prev_map == nullptr || info->offset() <= prev_map->offset() ||
398 (prev_map->flags() != PROT_READ)) {
399 return false;
400 }
401 elf_start_offset = prev_map->offset();
402 entry = offset_cache.find(elf_start_offset);
403 if (entry == offset_cache.end()) {
404 return false;
405 }
406 }
407 }
408
409 info->set_elf(entry->second);
410 info->set_elf_start_offset(elf_start_offset);
411 info->set_elf_offset(info->offset() - elf_start_offset);
412 return true;
413 }
414
GetBuildID(Memory * memory)415 std::string Elf::GetBuildID(Memory* memory) {
416 if (!IsValidElf(memory)) {
417 return "";
418 }
419
420 uint8_t class_type;
421 if (!memory->Read(EI_CLASS, &class_type, 1)) {
422 return "";
423 }
424
425 if (class_type == ELFCLASS32) {
426 return ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(memory);
427 } else if (class_type == ELFCLASS64) {
428 return ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(memory);
429 }
430 return "";
431 }
432
GetPrintableBuildID(std::string & build_id)433 std::string Elf::GetPrintableBuildID(std::string& build_id) {
434 if (build_id.empty()) {
435 return "";
436 }
437 std::string printable_build_id;
438 for (const char& c : build_id) {
439 // Use %hhx to avoid sign extension on abis that have signed chars.
440 printable_build_id += android::base::StringPrintf("%02hhx", c);
441 }
442 return printable_build_id;
443 }
444
GetPrintableBuildID()445 std::string Elf::GetPrintableBuildID() {
446 std::string build_id = GetBuildID();
447 return Elf::GetPrintableBuildID(build_id);
448 }
449
450 } // namespace unwindstack
451