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