13958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris/* 23958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * Copyright (C) 2016 The Android Open Source Project 33958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * 43958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 53958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * you may not use this file except in compliance with the License. 63958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * You may obtain a copy of the License at 73958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * 83958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 93958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * 103958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * Unless required by applicable law or agreed to in writing, software 113958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 123958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * See the License for the specific language governing permissions and 143958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris * limitations under the License. 153958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris */ 163958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 173958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <elf.h> 183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <string.h> 193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 203958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <memory> 21be788d891da26943b1ad6abe0f07a8745fa676d5Christopher Ferris#include <mutex> 223958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <string> 23d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris#include <utility> 243958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 253958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#define LOG_TAG "unwind" 263958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include <log/log.h> 273958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 28d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Elf.h> 29d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/ElfInterface.h> 30d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/MapInfo.h> 31d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h> 32d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Regs.h> 33d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 343958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris#include "ElfInterfaceArm.h" 35d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include "Symbols.h" 36d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 37d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisnamespace unwindstack { 383958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 390b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferrisbool Elf::cache_enabled_; 40d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferrisstd::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* Elf::cache_; 410b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferrisstd::mutex* Elf::cache_lock_; 420b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris 43e69f470933f24977825bb34ee39d32650b75107fChristopher Ferrisbool Elf::Init(bool init_gnu_debugdata) { 44e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris load_bias_ = 0; 453958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (!memory_) { 463958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 473958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 483958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 493958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris interface_.reset(CreateInterfaceFromMemory(memory_.get())); 503958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (!interface_) { 513958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 523958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 533958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 54e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris valid_ = interface_->Init(&load_bias_); 553958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (valid_) { 563958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris interface_->InitHeaders(); 57e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (init_gnu_debugdata) { 58e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris InitGnuDebugdata(); 59e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris } else { 60e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris gnu_debugdata_interface_.reset(nullptr); 61e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris } 623958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else { 633958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris interface_.reset(nullptr); 643958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 653958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return valid_; 663958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 673958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 68bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris// It is expensive to initialize the .gnu_debugdata section. Provide a method 69bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris// to initialize this data separately. 70bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferrisvoid Elf::InitGnuDebugdata() { 71bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (!valid_ || interface_->gnu_debugdata_offset() == 0) { 72bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return; 73bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 74bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 75bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_memory_.reset(interface_->CreateGnuDebugdataMemory()); 76bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_interface_.reset(CreateInterfaceFromMemory(gnu_debugdata_memory_.get())); 77bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris ElfInterface* gnu = gnu_debugdata_interface_.get(); 78bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris if (gnu == nullptr) { 79bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris return; 80bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 81e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris 82e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris // Ignore the load_bias from the compressed section, the correct load bias 83e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris // is in the uncompressed data. 84e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris uint64_t load_bias; 85e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris if (gnu->Init(&load_bias)) { 86bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu->InitHeaders(); 87e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris interface_->SetGnuDebugdataInterface(gnu); 88bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } else { 89bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris // Free all of the memory associated with the gnu_debugdata section. 90bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_memory_.reset(nullptr); 91bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris gnu_debugdata_interface_.reset(nullptr); 92bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris } 93bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris} 94bae69f1892b5eee6e2a5af374d524ce3212f0abbChristopher Ferris 95d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisbool Elf::GetSoname(std::string* name) { 96be788d891da26943b1ad6abe0f07a8745fa676d5Christopher Ferris std::lock_guard<std::mutex> guard(lock_); 97d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris return valid_ && interface_->GetSoname(name); 98d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} 99d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 100d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisuint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) { 101e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris return pc - map_info->start + load_bias_ + map_info->elf_offset; 102d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} 103d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 104d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisbool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) { 105be788d891da26943b1ad6abe0f07a8745fa676d5Christopher Ferris std::lock_guard<std::mutex> guard(lock_); 106e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris return valid_ && (interface_->GetFunctionName(addr, load_bias_, name, func_offset) || 107e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris (gnu_debugdata_interface_ && gnu_debugdata_interface_->GetFunctionName( 108e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris addr, load_bias_, name, func_offset))); 109d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} 110d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 111150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferrisbool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { 112150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (!valid_) { 113150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 114150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 115150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 116150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (!interface_->GetGlobalVariable(name, memory_address) && 117150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris (gnu_debugdata_interface_ == nullptr || 118150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris !gnu_debugdata_interface_->GetGlobalVariable(name, memory_address))) { 119150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 120150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 121150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 122150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris // Adjust by the load bias. 123150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (*memory_address < load_bias_) { 124150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 125150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 126150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 127150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris *memory_address -= load_bias_; 128150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 129150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris // If this winds up in the dynamic section, then we might need to adjust 130150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris // the address. 131150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris uint64_t dynamic_end = interface_->dynamic_vaddr() + interface_->dynamic_size(); 132150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (*memory_address >= interface_->dynamic_vaddr() && *memory_address < dynamic_end) { 133150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (interface_->dynamic_vaddr() > interface_->dynamic_offset()) { 134150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris *memory_address -= interface_->dynamic_vaddr() - interface_->dynamic_offset(); 135150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } else { 136150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris *memory_address += interface_->dynamic_offset() - interface_->dynamic_vaddr(); 137150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 138150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 139150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return true; 140150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris} 141150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 1422fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferrisvoid Elf::GetLastError(ErrorData* data) { 1432fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris if (valid_) { 1442fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris *data = interface_->last_error(); 1452fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } 1462fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris} 1472fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 1482fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher FerrisErrorCode Elf::GetLastErrorCode() { 1492fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris if (valid_) { 1502fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris return interface_->LastErrorCode(); 1512fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } 1522fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris return ERROR_NONE; 1532fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris} 1542fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 1552fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferrisuint64_t Elf::GetLastErrorAddress() { 1562fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris if (valid_) { 1572fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris return interface_->LastErrorAddress(); 1582fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris } 1592fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris return 0; 1602fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris} 1612fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris 162e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris// The relative pc is always relative to the start of the map from which it comes. 163d299a7ab588cba9038124613ac086635f96a47d4Christopher Ferrisbool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory, 164d299a7ab588cba9038124613ac086635f96a47d4Christopher Ferris bool* finished) { 165b9de87f7edefd7a2473134b267716c5fd750e89fChristopher Ferris if (!valid_) { 166b9de87f7edefd7a2473134b267716c5fd750e89fChristopher Ferris return false; 167b9de87f7edefd7a2473134b267716c5fd750e89fChristopher Ferris } 168e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris 169e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris // The relative pc expectd by StepIfSignalHandler is relative to the start of the elf. 170d299a7ab588cba9038124613ac086635f96a47d4Christopher Ferris if (regs->StepIfSignalHandler(rel_pc, this, process_memory)) { 171b9de87f7edefd7a2473134b267716c5fd750e89fChristopher Ferris *finished = false; 172b9de87f7edefd7a2473134b267716c5fd750e89fChristopher Ferris return true; 173b9de87f7edefd7a2473134b267716c5fd750e89fChristopher Ferris } 174e69f470933f24977825bb34ee39d32650b75107fChristopher Ferris 175be788d891da26943b1ad6abe0f07a8745fa676d5Christopher Ferris // Lock during the step which can update information in the object. 176be788d891da26943b1ad6abe0f07a8745fa676d5Christopher Ferris std::lock_guard<std::mutex> guard(lock_); 177e7b6624c3fd6bb780f6330448fad175e80469384Christopher Ferris return interface_->Step(adjusted_rel_pc, load_bias_, regs, process_memory, finished); 178d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} 179d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 1803958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferrisbool Elf::IsValidElf(Memory* memory) { 1813958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (memory == nullptr) { 1823958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1833958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1843958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 1853958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Verify that this is a valid elf file. 1863958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris uint8_t e_ident[SELFMAG + 1]; 187ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory->ReadFully(0, e_ident, SELFMAG)) { 1883958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1893958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1903958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 1913958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { 1923958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return false; 1933958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 1943958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return true; 1953958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 1963958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 1973f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferrisvoid Elf::GetInfo(Memory* memory, bool* valid, uint64_t* size) { 1983f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris if (!IsValidElf(memory)) { 1993f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris *valid = false; 2003f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris return; 2013f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } 2023f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris *size = 0; 2033f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris *valid = true; 2043f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris 2053f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris // Now read the section header information. 2063f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris uint8_t class_type; 207ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory->ReadFully(EI_CLASS, &class_type, 1)) { 2083f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris return; 2093f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } 2103f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris if (class_type == ELFCLASS32) { 2113f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris ElfInterface32::GetMaxSize(memory, size); 2123f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } else if (class_type == ELFCLASS64) { 2133f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris ElfInterface64::GetMaxSize(memory, size); 2143f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } else { 2153f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris *valid = false; 2163f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris } 2173f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris} 2183f805ac3f8e61489f66a54bbdb1a8dd541c043d1Christopher Ferris 219150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferrisbool Elf::IsValidPc(uint64_t pc) { 220150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (!valid_ || pc < load_bias_) { 221150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 222150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 223150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris pc -= load_bias_; 224150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 225150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (interface_->IsValidPc(pc)) { 226150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return true; 227150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 228150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 229150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->IsValidPc(pc)) { 230150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return true; 231150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris } 232150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 233150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris return false; 234150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris} 235150db124f3f3c0f8e1c341fd33c6c64310e0ac39Christopher Ferris 2363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher FerrisElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { 2373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (!IsValidElf(memory)) { 2383958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return nullptr; 2393958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2403958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2413958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris std::unique_ptr<ElfInterface> interface; 242ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory->ReadFully(EI_CLASS, &class_type_, 1)) { 2433958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return nullptr; 2443958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2453958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (class_type_ == ELFCLASS32) { 2463958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris Elf32_Half e_machine; 247ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory->ReadFully(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) { 2483958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return nullptr; 2493958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2503958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2513958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris machine_type_ = e_machine; 2523958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (e_machine == EM_ARM) { 253d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris arch_ = ARCH_ARM; 2543958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris interface.reset(new ElfInterfaceArm(memory)); 255a019665b3cb73609c888af7f17c64bf80ec40283Christopher Ferris } else if (e_machine == EM_386) { 256d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris arch_ = ARCH_X86; 2573958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris interface.reset(new ElfInterface32(memory)); 25861b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung } else if (e_machine == EM_MIPS) { 25961b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung arch_ = ARCH_MIPS; 26061b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung interface.reset(new ElfInterface32(memory)); 261a019665b3cb73609c888af7f17c64bf80ec40283Christopher Ferris } else { 262d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris // Unsupported. 26361b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung ALOGI("32 bit elf that is neither arm nor x86 nor mips: e_machine = %d\n", e_machine); 264a019665b3cb73609c888af7f17c64bf80ec40283Christopher Ferris return nullptr; 2653958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2663958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } else if (class_type_ == ELFCLASS64) { 2673958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris Elf64_Half e_machine; 268ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao if (!memory->ReadFully(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) { 2693958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return nullptr; 2703958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 271d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris 272d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris machine_type_ = e_machine; 273d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris if (e_machine == EM_AARCH64) { 274d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris arch_ = ARCH_ARM64; 275d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris } else if (e_machine == EM_X86_64) { 276d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris arch_ = ARCH_X86_64; 27761b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung } else if (e_machine == EM_MIPS) { 27861b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung arch_ = ARCH_MIPS64; 279d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris } else { 2803958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Unsupported. 28161b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung ALOGI("64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = %d\n", 28261b1a1ae7797e0d3177400cdb3cda028ea14669dDouglas Leung e_machine); 2833958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return nullptr; 2843958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2853958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris interface.reset(new ElfInterface64(memory)); 2863958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 2873958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2883958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris return interface.release(); 2893958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris} 290d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 291b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferrisuint64_t Elf::GetLoadBias(Memory* memory) { 292b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (!IsValidElf(memory)) { 293b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return 0; 294b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 295b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 296b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris uint8_t class_type; 297b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (!memory->Read(EI_CLASS, &class_type, 1)) { 298b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return 0; 299b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 300b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 301b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (class_type == ELFCLASS32) { 302b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(memory); 303b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } else if (class_type == ELFCLASS64) { 304b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(memory); 305b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris } 306b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris return 0; 307b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris} 308b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris 3090b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferrisvoid Elf::SetCachingEnabled(bool enable) { 3100b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris if (!cache_enabled_ && enable) { 3110b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris cache_enabled_ = true; 312d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris cache_ = new std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>; 3130b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris cache_lock_ = new std::mutex; 3140b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris } else if (cache_enabled_ && !enable) { 3150b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris cache_enabled_ = false; 3160b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris delete cache_; 3170b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris delete cache_lock_; 3180b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris } 3190b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris} 3200b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris 3210b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferrisvoid Elf::CacheLock() { 3220b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris cache_lock_->lock(); 3230b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris} 3240b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris 3250b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferrisvoid Elf::CacheUnlock() { 3260b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris cache_lock_->unlock(); 3270b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris} 3280b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris 3290b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferrisvoid Elf::CacheAdd(MapInfo* info) { 330d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // If elf_offset != 0, then cache both name:offset and name. 331d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // The cached name is used to do lookups if multiple maps for the same 332d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // named elf file exist. 333d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // For example, if there are two maps boot.odex:1000 and boot.odex:2000 334d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // where each reference the entire boot.odex, the cache will properly 335d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // use the same cached elf object. 336d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris 337d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris if (info->offset == 0 || info->elf_offset != 0) { 338d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris (*cache_)[info->name] = std::make_pair(info->elf, true); 339d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris } 340d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris 341d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris if (info->offset != 0) { 342d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // The second element in the pair indicates whether elf_offset should 343d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // be set to offset when getting out of the cache. 344d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris (*cache_)[info->name + ':' + std::to_string(info->offset)] = 345d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris std::make_pair(info->elf, info->elf_offset != 0); 3460b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris } 3470b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris} 3480b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris 349d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferrisbool Elf::CacheAfterCreateMemory(MapInfo* info) { 350d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris if (info->name.empty() || info->offset == 0 || info->elf_offset == 0) { 351d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris return false; 352d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris } 353d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris 354d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris auto entry = cache_->find(info->name); 355d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris if (entry == cache_->end()) { 356d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris return false; 357d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris } 358d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris 359d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // In this case, the whole file is the elf, and the name has already 360d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // been cached. Add an entry at name:offset to get this directly out 361d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris // of the cache next time. 362d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris info->elf = entry->second.first; 363d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris (*cache_)[info->name + ':' + std::to_string(info->offset)] = std::make_pair(info->elf, true); 364d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris return true; 365d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris} 366d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris 367d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferrisbool Elf::CacheGet(MapInfo* info) { 368d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris std::string name(info->name); 369d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris if (info->offset != 0) { 370d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris name += ':' + std::to_string(info->offset); 371d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris } 3720b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris auto entry = cache_->find(name); 3730b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris if (entry != cache_->end()) { 374d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris info->elf = entry->second.first; 375d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris if (entry->second.second) { 376d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris info->elf_offset = info->offset; 377d9575b668bd122f1ad80767bc36024e4571ffeb0Christopher Ferris } 3780b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris return true; 3790b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris } 3800b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris return false; 3810b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris} 3820b79ae155f0a5740a04723071e9f05f2527cbb86Christopher Ferris 383d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} // namespace unwindstack 384