summaryrefslogtreecommitdiff
path: root/simpleperf/dso.cpp
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2018-03-26 17:34:00 -0700
committerYabin Cui <yabinc@google.com>2018-03-28 17:16:27 -0700
commit516a87cd05e6f7dcf2c45fd8ba6d1d0e1e1e7bdd (patch)
tree642ab8433692d1862900ac93c7a24fc131ef4822 /simpleperf/dso.cpp
parent81ed0ea0e64d536287e823431f4999f183cc3cf1 (diff)
downloadextras-516a87cd05e6f7dcf2c45fd8ba6d1d0e1e1e7bdd.tar.gz
simpleperf: support showing symbols for interpreted java code.
To convert from a dex_pc (returned by libunwindstack) to a symbol name, we need below things: 1. The mapping info of the vdex file containing the dex_pc. 2. The offsets of dex files in the vdex file. So make below changes: 1. Record none executable maps when profiling java code. 2. Refactor dso code to add a new type for dex file, using DexFileDso to store dex file offsets in a vdex file, and load symbols from that vdex file. 3. Add read_dex_file.cpp to read java symbols using libdexfile. 4. Change the format of file section in record_file_format.h, to store dex file offsets in vdex files. Bug: http://b/73126888 Bug: http://b/77236599 Test: Run simpleperf to profile several apps manually, can see Test: callstacks of both java code and native code. Test: Run simpleperf_unit_test. Change-Id: I08005a03beb3df1a70db034bc463f555934856ba
Diffstat (limited to 'simpleperf/dso.cpp')
-rw-r--r--simpleperf/dso.cpp480
1 files changed, 222 insertions, 258 deletions
diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp
index 4825ac72..f3e9b2ce 100644
--- a/simpleperf/dso.cpp
+++ b/simpleperf/dso.cpp
@@ -28,6 +28,7 @@
#include "environment.h"
#include "read_apk.h"
+#include "read_dex_file.h"
#include "read_elf.h"
#include "utils.h"
@@ -38,7 +39,8 @@ Symbol::Symbol(const std::string& name, uint64_t addr, uint64_t len)
len(len),
name_(symbol_name_allocator.AllocateString(name)),
demangled_name_(nullptr),
- dump_id_(UINT_MAX) {}
+ dump_id_(UINT_MAX) {
+}
const char* Symbol::DemangledName() const {
if (demangled_name_ == nullptr) {
@@ -141,41 +143,14 @@ BuildId Dso::GetExpectedBuildId() {
return FindExpectedBuildIdForPath(path_);
}
-std::unique_ptr<Dso> Dso::CreateDso(DsoType dso_type, const std::string& dso_path,
- bool force_64bit) {
- return std::unique_ptr<Dso>(new Dso(dso_type, dso_path, force_64bit));
-}
-
-Dso::Dso(DsoType type, const std::string& path, bool force_64bit)
+Dso::Dso(DsoType type, const std::string& path, const std::string& debug_file_path)
: type_(type),
path_(path),
- debug_file_path_(path),
- min_vaddr_(std::numeric_limits<uint64_t>::max()),
+ debug_file_path_(debug_file_path),
is_loaded_(false),
dump_id_(UINT_MAX),
symbol_dump_id_(0),
symbol_warning_loglevel_(android::base::WARNING) {
- if (type_ == DSO_KERNEL) {
- min_vaddr_ = 0;
- }
- // Check if file matching path_ exists in symfs directory before using it as
- // debug_file_path_.
- if (!symfs_dir_.empty()) {
- std::string path_in_symfs = symfs_dir_ + path_;
- std::tuple<bool, std::string, std::string> tuple =
- SplitUrlInApk(path_in_symfs);
- std::string file_path =
- std::get<0>(tuple) ? std::get<1>(tuple) : path_in_symfs;
- if (IsRegularFile(file_path)) {
- debug_file_path_ = path_in_symfs;
- }
- } else if (path == "[vdso]") {
- if (force_64bit && !vdso_64bit_.empty()) {
- debug_file_path_ = vdso_64bit_;
- } else if (!force_64bit && !vdso_32bit_.empty()) {
- debug_file_path_ = vdso_32bit_;
- }
- }
size_t pos = path.find_last_of("/\\");
if (pos != std::string::npos) {
file_name_ = path.substr(pos + 1);
@@ -214,15 +189,13 @@ const Symbol* Dso::FindSymbol(uint64_t vaddr_in_dso) {
if (!is_loaded_) {
Load();
}
- if (!symbols_.empty()) {
- auto it = std::upper_bound(symbols_.begin(), symbols_.end(),
- Symbol("", vaddr_in_dso, 0),
- Symbol::CompareValueByAddr);
- if (it != symbols_.begin()) {
- --it;
- if (it->addr <= vaddr_in_dso && (it->addr + it->len > vaddr_in_dso)) {
- return &*it;
- }
+ auto it = std::upper_bound(symbols_.begin(), symbols_.end(),
+ Symbol("", vaddr_in_dso, 0),
+ Symbol::CompareValueByAddr);
+ if (it != symbols_.begin()) {
+ --it;
+ if (it->addr <= vaddr_in_dso && (it->addr + it->len > vaddr_in_dso)) {
+ return &*it;
}
}
if (!unknown_symbols_.empty()) {
@@ -234,13 +207,6 @@ const Symbol* Dso::FindSymbol(uint64_t vaddr_in_dso) {
return nullptr;
}
-const std::vector<Symbol>& Dso::GetSymbols() {
- if (!is_loaded_) {
- Load();
- }
- return symbols_;
-}
-
void Dso::SetSymbols(std::vector<Symbol>* symbols) {
symbols_ = std::move(*symbols);
symbols->clear();
@@ -250,252 +216,248 @@ void Dso::AddUnknownSymbol(uint64_t vaddr_in_dso, const std::string& name) {
unknown_symbols_.insert(std::make_pair(vaddr_in_dso, Symbol(name, vaddr_in_dso, 1)));
}
-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();
-
- uint64_t addr;
- ElfStatus result = ReadMinExecutableVirtualAddressFromElfFile(
- GetDebugFilePath(), build_id, &addr);
- if (result != ElfStatus::NO_ERROR) {
- LOG(WARNING) << "failed to read min virtual address of "
- << GetDebugFilePath() << ": " << result;
- } else {
- min_vaddr_ = addr;
- }
- }
- }
- return min_vaddr_;
-}
-
-static std::vector<Symbol> MergeSortedSymbols(const std::vector<Symbol>& s1,
- const std::vector<Symbol>& s2) {
- std::vector<Symbol> result;
- std::set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), std::back_inserter(result),
- Symbol::CompareValueByAddr);
- return result;
-}
-
void Dso::Load() {
is_loaded_ = true;
- std::vector<Symbol> dumped_symbols;
- if (!symbols_.empty()) {
- // If symbols has been read from file feature section of perf.data, move it to
- // dumped_symbols, so later we can merge them with symbols read from file system.
- dumped_symbols = std::move(symbols_);
- symbols_.clear();
- // Don't warn missing symbol table if we have dumped symbols in perf.data.
- symbol_warning_loglevel_ = android::base::DEBUG;
- }
- bool result = false;
- switch (type_) {
- case DSO_KERNEL:
- result = LoadKernel();
- break;
- case DSO_KERNEL_MODULE:
- result = LoadKernelModule();
- break;
- case DSO_ELF_FILE: {
- if (std::get<0>(SplitUrlInApk(path_))) {
- result = LoadEmbeddedElfFile();
- } else {
- result = LoadElfFile();
- }
- break;
- }
- }
- if (result) {
- std::sort(symbols_.begin(), symbols_.end(), Symbol::CompareValueByAddr);
- FixupSymbolLength();
- } else {
- symbols_.clear();
- }
-
- if (symbols_.empty()) {
- symbols_ = std::move(dumped_symbols);
- } else if (!dumped_symbols.empty()) {
- symbols_ = MergeSortedSymbols(symbols_, dumped_symbols);
- }
-
+ std::vector<Symbol> symbols = LoadSymbols();
if (symbols_.empty()) {
- LOG(DEBUG) << "failed to load dso: " << path_;
- }
-}
-
-static bool IsKernelFunctionSymbol(const KernelSymbol& symbol) {
- return (symbol.type == 'T' || symbol.type == 't' || symbol.type == 'W' ||
- symbol.type == 'w');
-}
-
-static bool KernelSymbolCallback(const KernelSymbol& kernel_symbol,
- std::vector<Symbol>* symbols) {
- if (IsKernelFunctionSymbol(kernel_symbol)) {
- symbols->emplace_back(Symbol(kernel_symbol.name, kernel_symbol.addr, 0));
- }
- return false;
-}
-
-static void VmlinuxSymbolCallback(const ElfFileSymbol& elf_symbol,
- std::vector<Symbol>* symbols) {
- if (elf_symbol.is_func) {
- symbols->emplace_back(
- Symbol(elf_symbol.name, elf_symbol.vaddr, elf_symbol.len));
+ symbols_ = std::move(symbols);
+ } else {
+ std::vector<Symbol> merged_symbols;
+ std::set_union(symbols_.begin(), symbols_.end(), symbols.begin(), symbols.end(),
+ std::back_inserter(merged_symbols), Symbol::CompareValueByAddr);
+ symbols_ = std::move(merged_symbols);
}
}
-bool Dso::CheckReadSymbolResult(ElfStatus result, const std::string& filename) {
+static void ReportReadElfSymbolResult(ElfStatus result, const std::string& path,
+ const std::string& debug_file_path,
+ android::base::LogSeverity warning_loglevel = android::base::WARNING) {
if (result == ElfStatus::NO_ERROR) {
- LOG(VERBOSE) << "Read symbols from " << filename << " successfully";
- return true;
+ LOG(VERBOSE) << "Read symbols from " << debug_file_path << " successfully";
} else if (result == ElfStatus::NO_SYMBOL_TABLE) {
- if (path_ == "[vdso]") {
+ if (path == "[vdso]") {
// Vdso only contains dynamic symbol table, and we can't change that.
- return true;
+ return;
}
// Lacking symbol table isn't considered as an error but worth reporting.
- LOG(symbol_warning_loglevel_) << filename << " doesn't contain symbol table";
- return true;
+ LOG(warning_loglevel) << debug_file_path << " doesn't contain symbol table";
} else {
- LOG(symbol_warning_loglevel_) << "failed to read symbols from " << filename << ": " << result;
- return false;
+ LOG(warning_loglevel) << "failed to read symbols from " << debug_file_path << ": " << result;
+ }
+}
+
+static void SortAndFixSymbols(std::vector<Symbol>& symbols) {
+ std::sort(symbols.begin(), symbols.end(), Symbol::CompareValueByAddr);
+ Symbol* prev_symbol = nullptr;
+ for (auto& symbol : symbols) {
+ if (prev_symbol != nullptr && prev_symbol->len == 0) {
+ prev_symbol->len = symbol.addr - prev_symbol->addr;
+ }
+ prev_symbol = &symbol;
}
}
-bool Dso::LoadKernel() {
- BuildId build_id = GetExpectedBuildId();
- if (!vmlinux_.empty()) {
- ElfStatus result = ParseSymbolsFromElfFile(vmlinux_, build_id,
- std::bind(VmlinuxSymbolCallback, std::placeholders::_1, &symbols_));
- return CheckReadSymbolResult(result, vmlinux_);
- } else if (!kallsyms_.empty()) {
- ProcessKernelSymbols(kallsyms_, std::bind(&KernelSymbolCallback,
- std::placeholders::_1, &symbols_));
- bool all_zero = true;
- for (const auto& symbol : symbols_) {
- if (symbol.addr != 0) {
- all_zero = false;
- break;
+class ElfDso : public Dso {
+ public:
+ ElfDso(const std::string& path, const std::string& debug_file_path)
+ : Dso(DSO_ELF_FILE, path, debug_file_path),
+ min_vaddr_(std::numeric_limits<uint64_t>::max()) {}
+
+ uint64_t MinVirtualAddress() override {
+ if (min_vaddr_ == std::numeric_limits<uint64_t>::max()) {
+ min_vaddr_ = 0;
+ if (type_ == DSO_ELF_FILE) {
+ BuildId build_id = GetExpectedBuildId();
+
+ uint64_t addr;
+ ElfStatus result = ReadMinExecutableVirtualAddressFromElfFile(
+ GetDebugFilePath(), build_id, &addr);
+ if (result != ElfStatus::NO_ERROR) {
+ LOG(WARNING) << "failed to read min virtual address of "
+ << GetDebugFilePath() << ": " << result;
+ } else {
+ min_vaddr_ = addr;
+ }
}
}
- if (all_zero) {
- LOG(symbol_warning_loglevel_)
- << "Symbol addresses in /proc/kallsyms on device are all zero. "
- "`echo 0 >/proc/sys/kernel/kptr_restrict` if possible.";
- symbols_.clear();
- return false;
+ return min_vaddr_;
+ }
+
+ void SetMinVirtualAddress(uint64_t min_vaddr) override {
+ min_vaddr_ = min_vaddr;
+ }
+
+ protected:
+ std::vector<Symbol> LoadSymbols() override {
+ std::vector<Symbol> symbols;
+ BuildId build_id = GetExpectedBuildId();
+ auto symbol_callback = [&](const ElfFileSymbol& symbol) {
+ if (symbol.is_func || (symbol.is_label && symbol.is_in_text_section)) {
+ symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
+ }
+ };
+ ElfStatus status;
+ std::tuple<bool, std::string, std::string> tuple = SplitUrlInApk(debug_file_path_);
+ if (std::get<0>(tuple)) {
+ status = ParseSymbolsFromApkFile(std::get<1>(tuple), std::get<2>(tuple), build_id,
+ symbol_callback);
+ } else {
+ status = ParseSymbolsFromElfFile(debug_file_path_, build_id, symbol_callback);
}
- } else if (read_kernel_symbols_from_proc_ || !build_id.IsEmpty()) {
- // Try /proc/kallsyms only when asked to do so, or when build id matches.
- // Otherwise, it is likely to use /proc/kallsyms on host for perf.data recorded on device.
- if (!build_id.IsEmpty()) {
- BuildId real_build_id;
- if (!GetKernelBuildId(&real_build_id)) {
- return false;
+ ReportReadElfSymbolResult(status, path_, debug_file_path_,
+ symbols_.empty() ? android::base::WARNING : android::base::DEBUG);
+ SortAndFixSymbols(symbols);
+ return symbols;
+ }
+
+ private:
+ uint64_t min_vaddr_;
+};
+
+class KernelDso : public Dso {
+ public:
+ KernelDso(const std::string& path, const std::string& debug_file_path)
+ : Dso(DSO_KERNEL, path, debug_file_path) {}
+
+ protected:
+ std::vector<Symbol> LoadSymbols() override {
+ std::vector<Symbol> symbols;
+ BuildId build_id = GetExpectedBuildId();
+ if (!vmlinux_.empty()) {
+ auto symbol_callback = [&](const ElfFileSymbol& symbol) {
+ if (symbol.is_func) {
+ symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
+ }
+ };
+ ElfStatus status = ParseSymbolsFromElfFile(vmlinux_, build_id, symbol_callback);
+ ReportReadElfSymbolResult(status, path_, vmlinux_);
+ } else if (!kallsyms_.empty()) {
+ symbols = ReadSymbolsFromKallsyms(kallsyms_);
+ } else if (read_kernel_symbols_from_proc_ || !build_id.IsEmpty()) {
+ // Try /proc/kallsyms only when asked to do so, or when build id matches.
+ // Otherwise, it is likely to use /proc/kallsyms on host for perf.data recorded on device.
+ bool can_read_kallsyms = true;
+ if (!build_id.IsEmpty()) {
+ BuildId real_build_id;
+ if (!GetKernelBuildId(&real_build_id) || build_id != real_build_id) {
+ LOG(DEBUG) << "failed to read symbols from /proc/kallsyms: Build id mismatch";
+ can_read_kallsyms = false;
+ }
}
- bool match = (build_id == real_build_id);
- if (!match) {
- LOG(symbol_warning_loglevel_) << "failed to read symbols from /proc/kallsyms: Build id "
- << "mismatch";
- return false;
+ if (can_read_kallsyms) {
+ std::string kallsyms;
+ if (!android::base::ReadFileToString("/proc/kallsyms", &kallsyms)) {
+ LOG(DEBUG) << "failed to read /proc/kallsyms";
+ } else {
+ symbols = ReadSymbolsFromKallsyms(kallsyms);
+ }
}
}
-
- std::string kallsyms;
- if (!android::base::ReadFileToString("/proc/kallsyms", &kallsyms)) {
- LOG(DEBUG) << "failed to read /proc/kallsyms";
- return false;
+ SortAndFixSymbols(symbols);
+ if (!symbols.empty()) {
+ symbols.back().len = std::numeric_limits<uint64_t>::max() - symbols.back().addr;
}
- ProcessKernelSymbols(kallsyms, std::bind(&KernelSymbolCallback,
- std::placeholders::_1, &symbols_));
- bool all_zero = true;
- for (const auto& symbol : symbols_) {
- if (symbol.addr != 0) {
- all_zero = false;
- break;
+ return symbols;
+ }
+
+ private:
+ std::vector<Symbol> ReadSymbolsFromKallsyms(std::string& kallsyms) {
+ std::vector<Symbol> symbols;
+ auto symbol_callback = [&](const KernelSymbol& symbol) {
+ if (strchr("TtWw", symbol.type) && symbol.addr != 0u) {
+ symbols.emplace_back(symbol.name, symbol.addr, 0);
}
- }
- if (all_zero) {
- LOG(symbol_warning_loglevel_) << "Symbol addresses in /proc/kallsyms are all zero. "
- "`echo 0 >/proc/sys/kernel/kptr_restrict` if possible.";
- symbols_.clear();
return false;
+ };
+ ProcessKernelSymbols(kallsyms, symbol_callback);
+ if (symbols.empty()) {
+ LOG(WARNING) << "Symbol addresses in /proc/kallsyms on device are all zero. "
+ "`echo 0 >/proc/sys/kernel/kptr_restrict` if possible.";
}
+ return symbols;
}
- return true;
-}
-
-static void ElfFileSymbolCallback(const ElfFileSymbol& elf_symbol,
- bool (*filter)(const ElfFileSymbol&),
- std::vector<Symbol>* symbols) {
- if (filter(elf_symbol)) {
- symbols->emplace_back(elf_symbol.name, elf_symbol.vaddr, elf_symbol.len);
+};
+
+class KernelModuleDso : public Dso {
+ public:
+ KernelModuleDso(const std::string& path, const std::string& debug_file_path)
+ : Dso(DSO_KERNEL_MODULE, path, debug_file_path) {}
+
+ protected:
+ std::vector<Symbol> LoadSymbols() override {
+ std::vector<Symbol> symbols;
+ BuildId build_id = GetExpectedBuildId();
+ auto symbol_callback = [&](const ElfFileSymbol& symbol) {
+ if (symbol.is_func || symbol.is_in_text_section) {
+ symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
+ }
+ };
+ ElfStatus status = ParseSymbolsFromElfFile(debug_file_path_, build_id, symbol_callback);
+ ReportReadElfSymbolResult(status, path_, debug_file_path_,
+ symbols_.empty() ? android::base::WARNING : android::base::DEBUG);
+ SortAndFixSymbols(symbols);
+ return symbols;
}
-}
-
-static bool SymbolFilterForKernelModule(const ElfFileSymbol& elf_symbol) {
- // TODO: Parse symbol outside of .text section.
- return (elf_symbol.is_func && elf_symbol.is_in_text_section);
-}
-
-bool Dso::LoadKernelModule() {
- BuildId build_id = GetExpectedBuildId();
- ElfStatus result = ParseSymbolsFromElfFile(GetDebugFilePath(), build_id,
- std::bind(ElfFileSymbolCallback, std::placeholders::_1,
- SymbolFilterForKernelModule, &symbols_));
- return CheckReadSymbolResult(result, GetDebugFilePath());
-}
+};
-static bool SymbolFilterForDso(const ElfFileSymbol& elf_symbol) {
- return elf_symbol.is_func ||
- (elf_symbol.is_label && elf_symbol.is_in_text_section);
-}
-
-bool Dso::LoadElfFile() {
- BuildId build_id = GetExpectedBuildId();
-
- if (symfs_dir_.empty()) {
- // Linux host can store debug shared libraries in /usr/lib/debug.
- ElfStatus result = ParseSymbolsFromElfFile(
- "/usr/lib/debug" + path_, build_id,
- std::bind(ElfFileSymbolCallback, std::placeholders::_1,
- SymbolFilterForDso, &symbols_));
- if (result == ElfStatus::NO_ERROR) {
- return CheckReadSymbolResult(result, "/usr/lib/debug" + path_);
+std::unique_ptr<Dso> Dso::CreateDso(DsoType dso_type, const std::string& dso_path,
+ bool force_64bit) {
+ auto find_debug_file = [&]() {
+ // Check if file matching path_ exists in symfs directory before using it as
+ // debug_file_path_.
+ if (!symfs_dir_.empty()) {
+ std::string path_in_symfs = symfs_dir_ + dso_path;
+ std::tuple<bool, std::string, std::string> tuple = SplitUrlInApk(path_in_symfs);
+ std::string file_path = std::get<0>(tuple) ? std::get<1>(tuple) : path_in_symfs;
+ if (IsRegularFile(file_path)) {
+ return path_in_symfs;
+ }
+ } else if (dso_path == "[vdso]") {
+ if (force_64bit && !vdso_64bit_.empty()) {
+ return vdso_64bit_;
+ } else if (!force_64bit && !vdso_32bit_.empty()) {
+ return vdso_32bit_;
+ }
+ } else if (dso_type == DSO_ELF_FILE) {
+ // Linux host can store debug shared libraries in /usr/lib/debug.
+ std::string path = "/usr/lib/debug" + dso_path;
+ if (IsRegularFile(path)) {
+ return path;
+ }
}
- }
- // TODO: load std::vector<Symbol> directly from ParseSymbolsFromElfFile
- // instead of needing to call a callback function for each symbol.
- ElfStatus result = ParseSymbolsFromElfFile(
- GetDebugFilePath(), build_id,
- std::bind(ElfFileSymbolCallback, std::placeholders::_1,
- SymbolFilterForDso, &symbols_));
- return CheckReadSymbolResult(result, GetDebugFilePath());
-}
+ return dso_path;
+ };
-bool Dso::LoadEmbeddedElfFile() {
- BuildId build_id = GetExpectedBuildId();
- auto tuple = SplitUrlInApk(GetDebugFilePath());
- CHECK(std::get<0>(tuple));
- ElfStatus result = ParseSymbolsFromApkFile(
- std::get<1>(tuple), std::get<2>(tuple), build_id,
- std::bind(ElfFileSymbolCallback, std::placeholders::_1,
- SymbolFilterForDso, &symbols_));
- return CheckReadSymbolResult(result, GetDebugFilePath());
+ switch (dso_type) {
+ case DSO_ELF_FILE:
+ return std::unique_ptr<Dso>(new ElfDso(dso_path, find_debug_file()));
+ case DSO_KERNEL:
+ return std::unique_ptr<Dso>(new KernelDso(dso_path, dso_path));
+ case DSO_KERNEL_MODULE:
+ return std::unique_ptr<Dso>(new KernelModuleDso(dso_path, find_debug_file()));
+ case DSO_DEX_FILE:
+ return std::unique_ptr<Dso>(new DexFileDso(dso_path, find_debug_file()));
+ default:
+ LOG(FATAL) << "Unexpected dso_type " << static_cast<int>(dso_type);
+ }
+ return nullptr;
}
-void Dso::FixupSymbolLength() {
- Symbol* prev_symbol = nullptr;
- for (auto& symbol : symbols_) {
- if (prev_symbol != nullptr && prev_symbol->len == 0) {
- prev_symbol->len = symbol.addr - prev_symbol->addr;
- }
- prev_symbol = &symbol;
+std::vector<Symbol> DexFileDso::LoadSymbols() {
+ std::vector<Symbol> symbols;
+ std::vector<DexFileSymbol> dex_file_symbols;
+ if (!ReadSymbolsFromDexFile(debug_file_path_, dex_file_offsets_, &dex_file_symbols)) {
+ android::base::LogSeverity level = symbols_.empty() ? android::base::WARNING
+ : android::base::DEBUG;
+ LOG(level) << "Failed to read symbols from " << debug_file_path_;
+ return symbols;
}
- if (prev_symbol != nullptr && prev_symbol->len == 0) {
- prev_symbol->len = std::numeric_limits<uint64_t>::max() - prev_symbol->addr;
+ LOG(VERBOSE) << "Read symbols from " << debug_file_path_ << " successfully";
+ for (auto& symbol : dex_file_symbols) {
+ symbols.emplace_back(symbol.name, symbol.offset, symbol.len);
}
+ SortAndFixSymbols(symbols);
+ return symbols;
}
const char* DsoTypeToString(DsoType dso_type) {
@@ -506,6 +468,8 @@ const char* DsoTypeToString(DsoType dso_type) {
return "dso_kernel_module";
case DSO_ELF_FILE:
return "dso_elf_file";
+ case DSO_DEX_FILE:
+ return "dso_dex_file";
default:
return "unknown";
}