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