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