summaryrefslogtreecommitdiff
path: root/perfprofd/symbolizer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'perfprofd/symbolizer.cc')
-rw-r--r--perfprofd/symbolizer.cc111
1 files changed, 93 insertions, 18 deletions
diff --git a/perfprofd/symbolizer.cc b/perfprofd/symbolizer.cc
index bde680f5..58ff280b 100644
--- a/perfprofd/symbolizer.cc
+++ b/perfprofd/symbolizer.cc
@@ -22,9 +22,11 @@
#include <unordered_map>
#include <android-base/logging.h>
-
-#include "build_id.h"
-#include "read_elf.h"
+#include <base/mem_map.h>
+#include <build_id.h>
+#include <read_dex_file.h>
+#include <read_elf.h>
+#include <vdex_file.h>
namespace perfprofd {
@@ -33,6 +35,8 @@ namespace {
struct SimpleperfSymbolizer : public Symbolizer {
// For simplicity, we assume non-overlapping symbols.
struct Symbol {
+ Symbol(const std::string& n, uint64_t l) : name(n), length(l) {}
+
std::string name;
uint64_t length;
};
@@ -66,28 +70,99 @@ struct SimpleperfSymbolizer : public Symbolizer {
}
void LoadDso(const std::string& dso) {
- SymbolMap data;
- auto callback = [&data](const ElfFileSymbol& sym) {
- if (sym.is_func) {
- Symbol symbol;
- symbol.name = sym.name;
- symbol.length = sym.len;
- if (sym.len == 0) {
- LOG(ERROR) << "Symbol size is zero for " << sym.name;
+ // See whether it's an ELF file.
+ {
+ SymbolMap elf_data;
+ auto callback = [&elf_data](const ElfFileSymbol& sym) {
+ if (sym.is_func) {
+ if (sym.len == 0) {
+ LOG(ERROR) << "Symbol size is zero for " << sym.name;
+ }
+ elf_data.emplace(sym.vaddr, Symbol(sym.name, sym.len));
}
- data.emplace(sym.vaddr, std::move(symbol));
+ };
+ ElfStatus status = ParseSymbolsFromElfFile(dso, BuildId(), callback);
+ if (status == ElfStatus::NO_ERROR) {
+ dsos.emplace(dso, std::move(elf_data));
+ return;
+ }
+ }
+
+ // See whether it's a vdex file.
+ {
+ ::art::MemMap::Init();
+
+ using VdexFile = ::art::VdexFile;
+ std::string error_msg;
+ std::unique_ptr<VdexFile> vdex = VdexFile::Open(dso,
+ /* writable= */ false,
+ /* low_4gb= */ false,
+ /* unquicken= */ false,
+ &error_msg);
+ if (vdex != nullptr) {
+ const uint8_t* cur = nullptr;
+ std::vector<uint64_t> dex_file_offsets;
+ const uint8_t* base = vdex->Begin();
+ for (;;) {
+ cur = vdex->GetNextDexFileData(cur);
+ if (cur == nullptr) {
+ break;
+ }
+ dex_file_offsets.push_back(cur - base);
+ }
+
+ if (!dex_file_offsets.empty()) {
+ std::vector<DexFileSymbol> symbols;
+ if (ReadSymbolsFromDexFile(dso, dex_file_offsets, &symbols)) {
+ SymbolMap vdex_data;
+ for (const DexFileSymbol& symbol : symbols) {
+ vdex_data.emplace(symbol.offset, Symbol(symbol.name, symbol.len));
+ }
+ dsos.emplace(dso, std::move(vdex_data));
+ LOG(INFO) << "Found " << symbols.size() << " dex symbols in " << dso;
+ return;
+ } else {
+ LOG(WARNING) << "Could not read symbols from dex files in " << dso;
+ }
+ } else {
+ LOG(WARNING) << "Could not find dex files for vdex " << dso;
+ dsos.emplace(dso, SymbolMap());
+ }
+ } else {
+ LOG(WARNING) << dso << " is not a vdex: " << error_msg;
}
- };
- ElfStatus status = ParseSymbolsFromElfFile(dso, BuildId(), callback);
- if (status != ElfStatus::NO_ERROR) {
- LOG(WARNING) << "Could not parse dso " << dso << ": " << status;
}
- dsos.emplace(dso, std::move(data));
+
+ // TODO: See whether it's a dex file.
+
+ // OK, give up.
+ LOG(WARNING) << "Could not symbolize " << dso;
+ dsos.emplace(dso, SymbolMap());
}
bool GetMinExecutableVAddr(const std::string& dso, uint64_t* addr) override {
ElfStatus status = ReadMinExecutableVirtualAddressFromElfFile(dso, BuildId(), addr);
- return status == ElfStatus::NO_ERROR;
+ if (status != ElfStatus::NO_ERROR) {
+ return true;
+ }
+
+ {
+ ::art::MemMap::Init();
+
+ using VdexFile = ::art::VdexFile;
+ std::string error_msg;
+ std::unique_ptr<VdexFile> vdex = VdexFile::Open(dso,
+ /* writable= */ false,
+ /* low_4gb= */ false,
+ /* unquicken= */ false,
+ &error_msg);
+ if (vdex != nullptr) {
+ *addr = 0u;
+ return true;
+ }
+ }
+
+ return false;
}
std::unordered_map<std::string, SymbolMap> dsos;