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_.reset(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,const MapInfo * map_info)104 uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) {
105 return pc - map_info->start + load_bias_ + map_info->elf_offset;
106 }
107
GetFunctionName(uint64_t addr,std::string * name,uint64_t * func_offset)108 bool Elf::GetFunctionName(uint64_t addr, std::string* 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 }
161 }
162
GetLastErrorCode()163 ErrorCode Elf::GetLastErrorCode() {
164 if (valid_) {
165 return interface_->LastErrorCode();
166 }
167 return ERROR_INVALID_ELF;
168 }
169
GetLastErrorAddress()170 uint64_t Elf::GetLastErrorAddress() {
171 if (valid_) {
172 return interface_->LastErrorAddress();
173 }
174 return 0;
175 }
176
177 // 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)178 bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
179 if (!valid_) {
180 return false;
181 }
182
183 // Convert the rel_pc to an elf_offset.
184 if (rel_pc < static_cast<uint64_t>(load_bias_)) {
185 return false;
186 }
187 return regs->StepIfSignalHandler(rel_pc - load_bias_, this, process_memory);
188 }
189
190 // 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)191 bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) {
192 if (!valid_) {
193 return false;
194 }
195
196 // Lock during the step which can update information in the object.
197 std::lock_guard<std::mutex> guard(lock_);
198 return interface_->Step(rel_pc, regs, process_memory, finished);
199 }
200
IsValidElf(Memory * memory)201 bool Elf::IsValidElf(Memory* memory) {
202 if (memory == nullptr) {
203 return false;
204 }
205
206 // Verify that this is a valid elf file.
207 uint8_t e_ident[SELFMAG + 1];
208 if (!memory->ReadFully(0, e_ident, SELFMAG)) {
209 return false;
210 }
211
212 if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
213 return false;
214 }
215 return true;
216 }
217
GetInfo(Memory * memory,uint64_t * size)218 bool Elf::GetInfo(Memory* memory, uint64_t* size) {
219 if (!IsValidElf(memory)) {
220 return false;
221 }
222 *size = 0;
223
224 uint8_t class_type;
225 if (!memory->ReadFully(EI_CLASS, &class_type, 1)) {
226 return false;
227 }
228
229 // Get the maximum size of the elf data from the header.
230 if (class_type == ELFCLASS32) {
231 ElfInterface32::GetMaxSize(memory, size);
232 } else if (class_type == ELFCLASS64) {
233 ElfInterface64::GetMaxSize(memory, size);
234 } else {
235 return false;
236 }
237 return true;
238 }
239
IsValidPc(uint64_t pc)240 bool Elf::IsValidPc(uint64_t pc) {
241 if (!valid_ || (load_bias_ > 0 && pc < static_cast<uint64_t>(load_bias_))) {
242 return false;
243 }
244
245 if (interface_->IsValidPc(pc)) {
246 return true;
247 }
248
249 if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->IsValidPc(pc)) {
250 return true;
251 }
252
253 return false;
254 }
255
CreateInterfaceFromMemory(Memory * memory)256 ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
257 if (!IsValidElf(memory)) {
258 return nullptr;
259 }
260
261 std::unique_ptr<ElfInterface> interface;
262 if (!memory->ReadFully(EI_CLASS, &class_type_, 1)) {
263 return nullptr;
264 }
265 if (class_type_ == ELFCLASS32) {
266 Elf32_Half e_machine;
267 if (!memory->ReadFully(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) {
268 return nullptr;
269 }
270
271 machine_type_ = e_machine;
272 if (e_machine == EM_ARM) {
273 arch_ = ARCH_ARM;
274 interface.reset(new ElfInterfaceArm(memory));
275 } else if (e_machine == EM_386) {
276 arch_ = ARCH_X86;
277 interface.reset(new ElfInterface32(memory));
278 } else if (e_machine == EM_MIPS) {
279 arch_ = ARCH_MIPS;
280 interface.reset(new ElfInterface32(memory));
281 } else {
282 // Unsupported.
283 ALOGI("32 bit elf that is neither arm nor x86 nor mips: e_machine = %d\n", e_machine);
284 return nullptr;
285 }
286 } else if (class_type_ == ELFCLASS64) {
287 Elf64_Half e_machine;
288 if (!memory->ReadFully(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
289 return nullptr;
290 }
291
292 machine_type_ = e_machine;
293 if (e_machine == EM_AARCH64) {
294 arch_ = ARCH_ARM64;
295 } else if (e_machine == EM_X86_64) {
296 arch_ = ARCH_X86_64;
297 } else if (e_machine == EM_MIPS) {
298 arch_ = ARCH_MIPS64;
299 } else {
300 // Unsupported.
301 ALOGI("64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = %d\n",
302 e_machine);
303 return nullptr;
304 }
305 interface.reset(new ElfInterface64(memory));
306 }
307
308 return interface.release();
309 }
310
GetLoadBias(Memory * memory)311 int64_t Elf::GetLoadBias(Memory* memory) {
312 if (!IsValidElf(memory)) {
313 return 0;
314 }
315
316 uint8_t class_type;
317 if (!memory->Read(EI_CLASS, &class_type, 1)) {
318 return 0;
319 }
320
321 if (class_type == ELFCLASS32) {
322 return ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(memory);
323 } else if (class_type == ELFCLASS64) {
324 return ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(memory);
325 }
326 return 0;
327 }
328
SetCachingEnabled(bool enable)329 void Elf::SetCachingEnabled(bool enable) {
330 if (!cache_enabled_ && enable) {
331 cache_enabled_ = true;
332 cache_ = new std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>;
333 cache_lock_ = new std::mutex;
334 } else if (cache_enabled_ && !enable) {
335 cache_enabled_ = false;
336 delete cache_;
337 delete cache_lock_;
338 }
339 }
340
CacheLock()341 void Elf::CacheLock() {
342 cache_lock_->lock();
343 }
344
CacheUnlock()345 void Elf::CacheUnlock() {
346 cache_lock_->unlock();
347 }
348
CacheAdd(MapInfo * info)349 void Elf::CacheAdd(MapInfo* info) {
350 // If elf_offset != 0, then cache both name:offset and name.
351 // The cached name is used to do lookups if multiple maps for the same
352 // named elf file exist.
353 // For example, if there are two maps boot.odex:1000 and boot.odex:2000
354 // where each reference the entire boot.odex, the cache will properly
355 // use the same cached elf object.
356
357 if (info->offset == 0 || info->elf_offset != 0) {
358 (*cache_)[info->name] = std::make_pair(info->elf, true);
359 }
360
361 if (info->offset != 0) {
362 // The second element in the pair indicates whether elf_offset should
363 // be set to offset when getting out of the cache.
364 (*cache_)[info->name + ':' + std::to_string(info->offset)] =
365 std::make_pair(info->elf, info->elf_offset != 0);
366 }
367 }
368
CacheAfterCreateMemory(MapInfo * info)369 bool Elf::CacheAfterCreateMemory(MapInfo* info) {
370 if (info->name.empty() || info->offset == 0 || info->elf_offset == 0) {
371 return false;
372 }
373
374 auto entry = cache_->find(info->name);
375 if (entry == cache_->end()) {
376 return false;
377 }
378
379 // In this case, the whole file is the elf, and the name has already
380 // been cached. Add an entry at name:offset to get this directly out
381 // of the cache next time.
382 info->elf = entry->second.first;
383 (*cache_)[info->name + ':' + std::to_string(info->offset)] = std::make_pair(info->elf, true);
384 return true;
385 }
386
CacheGet(MapInfo * info)387 bool Elf::CacheGet(MapInfo* info) {
388 std::string name(info->name);
389 if (info->offset != 0) {
390 name += ':' + std::to_string(info->offset);
391 }
392 auto entry = cache_->find(name);
393 if (entry != cache_->end()) {
394 info->elf = entry->second.first;
395 if (entry->second.second) {
396 info->elf_offset = info->offset;
397 }
398 return true;
399 }
400 return false;
401 }
402
GetBuildID(Memory * memory)403 std::string Elf::GetBuildID(Memory* memory) {
404 if (!IsValidElf(memory)) {
405 return "";
406 }
407
408 uint8_t class_type;
409 if (!memory->Read(EI_CLASS, &class_type, 1)) {
410 return "";
411 }
412
413 if (class_type == ELFCLASS32) {
414 return ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(memory);
415 } else if (class_type == ELFCLASS64) {
416 return ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(memory);
417 }
418 return "";
419 }
420
421 } // namespace unwindstack
422