}
int Compare(const SampleEntry& sample1, const SampleEntry& sample2) const override {
- return strcmp(sample1.symbol->name.c_str(), sample2.symbol->name.c_str());
+ return strcmp(sample1.symbol->GetDemangledName().c_str(),
+ sample2.symbol->GetDemangledName().c_str());
}
std::string Show(const SampleEntry& sample) const override {
- return sample.symbol->name;
+ return sample.symbol->GetDemangledName();
}
};
}
int Compare(const SampleEntry& sample1, const SampleEntry& sample2) const override {
- return strcmp(sample1.branch_from.symbol->name.c_str(),
- sample2.branch_from.symbol->name.c_str());
+ return strcmp(sample1.branch_from.symbol->GetDemangledName().c_str(),
+ sample2.branch_from.symbol->GetDemangledName().c_str());
}
std::string Show(const SampleEntry& sample) const override {
- return sample.branch_from.symbol->name;
+ return sample.branch_from.symbol->GetDemangledName();
}
};
#include "read_elf.h"
#include "utils.h"
+const std::string& SymbolEntry::GetDemangledName() const {
+ if (demangled_name_.empty()) {
+ demangled_name_ = DsoFactory::GetInstance()->Demangle(name);
+ }
+ return demangled_name_;
+}
+
bool SymbolComparator::operator()(const std::unique_ptr<SymbolEntry>& symbol1,
const std::unique_ptr<SymbolEntry>& symbol2) {
return symbol1->addr < symbol2->addr;
return std::unique_ptr<DsoEntry>(new DsoEntry(dso_type, path));
}
+extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status);
+
+std::string DsoFactory::Demangle(const std::string& name) {
+ if (!demangle_) {
+ return name;
+ }
+ int status;
+ bool is_linker_symbol = (name.find(linker_prefix) == 0);
+ const char* mangled_str = name.c_str();
+ if (is_linker_symbol) {
+ mangled_str += linker_prefix.size();
+ }
+ std::string result = name;
+ char* demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status);
+ if (status == 0) {
+ if (is_linker_symbol) {
+ result = std::string("[linker]") + demangled_name;
+ } else {
+ result = demangled_name;
+ }
+ free(demangled_name);
+ } else if (is_linker_symbol) {
+ result = std::string("[linker]") + mangled_str;
+ }
+ return result;
+}
+
bool DsoFactory::LoadDso(DsoEntry* dso) {
switch (dso->type) {
case DSO_KERNEL:
static bool KernelSymbolCallback(const KernelSymbol& kernel_symbol, DsoEntry* dso) {
if (IsKernelFunctionSymbol(kernel_symbol)) {
- SymbolEntry* symbol = new SymbolEntry{
- kernel_symbol.name, // name
- kernel_symbol.addr, // addr
- 0, // len
- };
- dso->symbols.insert(std::unique_ptr<SymbolEntry>(symbol));
+ dso->symbols.insert(
+ std::unique_ptr<SymbolEntry>(new SymbolEntry(kernel_symbol.name, kernel_symbol.addr, 0)));
}
return false;
}
static void VmlinuxSymbolCallback(const ElfFileSymbol& elf_symbol, DsoEntry* dso) {
if (elf_symbol.is_func) {
- SymbolEntry* symbol = new SymbolEntry{
- elf_symbol.name, // name
- elf_symbol.vaddr, // addr
- elf_symbol.len, // len
- };
- dso->symbols.insert(std::unique_ptr<SymbolEntry>(symbol));
+ dso->symbols.insert(std::unique_ptr<SymbolEntry>(
+ new SymbolEntry(elf_symbol.name, elf_symbol.vaddr, elf_symbol.len)));
}
}
static void ParseSymbolCallback(const ElfFileSymbol& elf_symbol, DsoEntry* dso,
bool (*filter)(const ElfFileSymbol&)) {
if (filter(elf_symbol)) {
- SymbolEntry* symbol = new SymbolEntry{
- elf_symbol.name, // name
- elf_symbol.start_in_file, // addr
- elf_symbol.len, // len
- };
- dso->symbols.insert(std::unique_ptr<SymbolEntry>(symbol));
+ dso->symbols.insert(std::unique_ptr<SymbolEntry>(
+ new SymbolEntry(elf_symbol.name, elf_symbol.start_in_file, elf_symbol.len)));
}
}
return elf_symbol.is_func || (elf_symbol.is_label && elf_symbol.is_in_text_section);
}
-extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status);
-
-static void DemangleInPlace(std::string* name) {
- int status;
- bool is_linker_symbol = (name->find(linker_prefix) == 0);
- const char* mangled_str = name->c_str();
- if (is_linker_symbol) {
- mangled_str += linker_prefix.size();
- }
- char* demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status);
- if (status == 0) {
- if (is_linker_symbol) {
- *name = std::string("[linker]") + demangled_name;
- } else {
- *name = demangled_name;
- }
- free(demangled_name);
- } else if (is_linker_symbol) {
- std::string temp = std::string("[linker]") + mangled_str;
- *name = std::move(temp);
- }
-}
-
bool DsoFactory::LoadElfFile(DsoEntry* dso) {
BuildId build_id = GetExpectedBuildId(dso->path);
ParseSymbolsFromElfFile(
symfs_dir_ + dso->path, build_id,
std::bind(ParseSymbolCallback, std::placeholders::_1, dso, SymbolFilterForDso));
- if (demangle_) {
- for (auto& symbol : dso->symbols) {
- DemangleInPlace(&symbol->name);
- }
- }
FixupSymbolLength(dso);
return true;
}
std::string name;
uint64_t addr;
uint64_t len;
+
+ SymbolEntry(const std::string& name, uint64_t addr, uint64_t len)
+ : name(name), addr(addr), len(len) {
+ }
+
+ const std::string& GetDemangledName() const;
+
+ private:
+ mutable std::string demangled_name_;
};
struct SymbolComparator {
class DsoFactory {
public:
static DsoFactory* GetInstance();
+
void SetDemangle(bool demangle);
bool SetSymFsDir(const std::string& symfs_dir);
void SetVmlinux(const std::string& vmlinux);
void SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_ids);
+
std::unique_ptr<DsoEntry> CreateDso(DsoType dso_type, const std::string& dso_path = "");
+ std::string Demangle(const std::string& name);
bool LoadDso(DsoEntry* dso);
private: