• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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