#include <limits>
#include <vector>
-#include <base/logging.h>
+#include <android-base/logging.h>
#include "environment.h"
#include "read_elf.h"
return std::unique_ptr<Dso>(new Dso(dso_type, path));
}
-Dso::Dso(DsoType type, const std::string& path) : type_(type), path_(path), is_loaded_(false) {
+Dso::Dso(DsoType type, const std::string& path)
+ : type_(type), path_(path), min_vaddr_(std::numeric_limits<uint64_t>::max()), is_loaded_(false) {
dso_count_++;
}
}
};
-const Symbol* Dso::FindSymbol(uint64_t offset_in_dso) {
+std::string Dso::GetAccessiblePath() const {
+ return symfs_dir_ + path_;
+}
+
+const Symbol* Dso::FindSymbol(uint64_t vaddr_in_dso) {
if (!is_loaded_) {
is_loaded_ = true;
if (!Load()) {
}
}
- auto it = std::upper_bound(symbols_.begin(), symbols_.end(), Symbol("", offset_in_dso, 0),
+ auto it = std::upper_bound(symbols_.begin(), symbols_.end(), Symbol("", vaddr_in_dso, 0),
SymbolComparator());
if (it != symbols_.begin()) {
--it;
- if (it->addr <= offset_in_dso && it->addr + it->len > offset_in_dso) {
+ if (it->addr <= vaddr_in_dso && it->addr + it->len > vaddr_in_dso) {
return &*it;
}
}
return nullptr;
}
+uint64_t Dso::MinVirtualAddress() {
+ if (min_vaddr_ == std::numeric_limits<uint64_t>::max()) {
+ min_vaddr_ = 0;
+ if (type_ == DSO_ELF_FILE) {
+ BuildId build_id = GetExpectedBuildId(GetAccessiblePath());
+
+ uint64_t addr;
+ if (ReadMinExecutableVirtualAddressFromElfFile(GetAccessiblePath(), build_id, &addr)) {
+ min_vaddr_ = addr;
+ }
+ }
+ }
+ return min_vaddr_;
+}
+
bool Dso::Load() {
bool result = false;
switch (type_) {
return false;
}
}
+
ProcessKernelSymbols("/proc/kallsyms",
std::bind(&KernelSymbolCallback, std::placeholders::_1, this));
+ bool allZero = true;
+ for (auto& symbol : symbols_) {
+ if (symbol.addr != 0) {
+ allZero = false;
+ break;
+ }
+ }
+ if (allZero) {
+ LOG(WARNING) << "Symbol addresses in /proc/kallsyms are all zero. Check "
+ "/proc/sys/kernel/kptr_restrict if possible.";
+ symbols_.clear();
+ return false;
+ }
}
return true;
}
void Dso::ElfFileSymbolCallback(const ElfFileSymbol& elf_symbol, Dso* dso,
bool (*filter)(const ElfFileSymbol&)) {
if (filter(elf_symbol)) {
- dso->InsertSymbol(Symbol(elf_symbol.name, elf_symbol.start_in_file, elf_symbol.len));
+ dso->InsertSymbol(Symbol(elf_symbol.name, elf_symbol.vaddr, elf_symbol.len));
}
}
}
bool Dso::LoadElfFile() {
- BuildId build_id = GetExpectedBuildId(path_);
- ParseSymbolsFromElfFile(
- symfs_dir_ + path_, build_id,
- std::bind(ElfFileSymbolCallback, std::placeholders::_1, this, SymbolFilterForDso));
- return true;
+ bool loaded = false;
+ BuildId build_id = GetExpectedBuildId(GetAccessiblePath());
+
+ if (symfs_dir_.empty()) {
+ // Linux host can store debug shared libraries in /usr/lib/debug.
+ loaded = ParseSymbolsFromElfFile(
+ "/usr/lib/debug" + path_, build_id,
+ std::bind(ElfFileSymbolCallback, std::placeholders::_1, this, SymbolFilterForDso));
+ }
+ if (!loaded) {
+ loaded = ParseSymbolsFromElfFile(
+ GetAccessiblePath(), build_id,
+ std::bind(ElfFileSymbolCallback, std::placeholders::_1, this, SymbolFilterForDso));
+ }
+ return loaded;
}
void Dso::InsertSymbol(const Symbol& symbol) {