Skip to content

Commit

Permalink
Added Disassembler functionality.
Browse files Browse the repository at this point in the history
Added mangled symbol name, start address and size into Symbol and their stream output.
  • Loading branch information
dknysh committed Sep 21, 2020
1 parent 6f5d22f commit 61be877
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 20 deletions.
5 changes: 4 additions & 1 deletion app/perfaddresscache.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,18 @@ class PerfAddressCache

struct SymbolCacheEntry
{
SymbolCacheEntry(quint64 offset = 0, quint64 size = 0, const QByteArray &symname = {})
SymbolCacheEntry(quint64 offset = 0, quint64 value = 0, quint64 size = 0, const QByteArray &symname = {})
: offset(offset)
, value(value)
, size(size)
, symname(symname)
{}

bool isValid() const { return !symname.isEmpty(); }

quint64 offset;
// st_value in elf symbol table entry
quint64 value;
quint64 size;
QByteArray symname;
bool demangled = false;
Expand Down
32 changes: 20 additions & 12 deletions app/perfsymboltable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QByteArray &
}

int PerfSymbolTable::insertSubprogram(CuDieRangeMapping *cudie, Dwarf_Die *top, Dwarf_Addr entry,
quint64 offset, quint64 size,
qint32 binaryId, qint32 binaryPathId,
qint32 inlineCallLocationId, bool isKernel)
{
Expand All @@ -329,13 +330,15 @@ int PerfSymbolTable::insertSubprogram(CuDieRangeMapping *cudie, Dwarf_Die *top,
qint32 fileId = m_unwind->resolveString(file);
int locationId = m_unwind->resolveLocation(PerfUnwind::Location(entry, fileId, m_pid, line,
column, inlineCallLocationId));
qint32 symId = m_unwind->resolveString(cudie->dieName(top));
m_unwind->resolveSymbol(locationId, PerfUnwind::Symbol(symId, binaryId, binaryPathId, isKernel));
const auto mangled = cudie->dieName(top);
const auto mangledSymId = m_unwind->resolveString(mangled);
const auto symId = m_unwind->resolveString(demangle(mangled));
m_unwind->resolveSymbol(locationId, PerfUnwind::Symbol(symId, mangledSymId, offset, size, binaryId, binaryPathId, isKernel));

return locationId;
}

int PerfSymbolTable::parseDie(CuDieRangeMapping *cudie, Dwarf_Die *top, qint32 binaryId, qint32 binaryPathId,
int PerfSymbolTable::parseDie(CuDieRangeMapping *cudie, Dwarf_Die *top, quint64 offset, quint64 size, qint32 binaryId, qint32 binaryPathId,
bool isKernel, Dwarf_Files *files, Dwarf_Addr entry, qint32 parentLocationId)
{
int tag = dwarf_tag(top);
Expand All @@ -359,17 +362,17 @@ int PerfSymbolTable::parseDie(CuDieRangeMapping *cudie, Dwarf_Die *top, qint32 b
location.parentLocationId = parentLocationId;

int callLocationId = m_unwind->resolveLocation(location);
return insertSubprogram(cudie, top, entry, binaryId, binaryPathId, callLocationId, isKernel);
return insertSubprogram(cudie, top, entry, offset, size, binaryId, binaryPathId, callLocationId, isKernel);
}
case DW_TAG_subprogram:
return insertSubprogram(cudie, top, entry, binaryId, binaryPathId, -1, isKernel);
return insertSubprogram(cudie, top, entry, offset, size, binaryId, binaryPathId, -1, isKernel);
default:
return -1;
}
}

qint32 PerfSymbolTable::parseDwarf(CuDieRangeMapping *cudie, SubProgramDie *subprogram, const QVector<Dwarf_Die> &inlined,
Dwarf_Addr bias, qint32 binaryId, qint32 binaryPathId, bool isKernel)
Dwarf_Addr bias, quint64 offset, quint64 size, qint32 binaryId, qint32 binaryPathId, bool isKernel)
{
Dwarf_Files *files = nullptr;
dwarf_getsrcfiles(cudie->cudie(), &files, nullptr);
Expand All @@ -381,7 +384,7 @@ qint32 PerfSymbolTable::parseDwarf(CuDieRangeMapping *cudie, SubProgramDie *subp
if (dwarf_entrypc(&scope, &entry) == 0 && entry != 0)
scopeAddr += entry;

auto locationId = parseDie(cudie, &scope, binaryId, binaryPathId, isKernel, files, scopeAddr, parentLocationId);
auto locationId = parseDie(cudie, &scope, offset, size, binaryId, binaryPathId, isKernel, files, scopeAddr, parentLocationId);
if (locationId != -1)
parentLocationId = locationId;
};
Expand Down Expand Up @@ -732,7 +735,7 @@ static PerfAddressCache::SymbolCache cacheSymbols(Dwfl_Module *module, quint64 e
GElf_Addr symAddr;
const auto symbol = dwfl_module_getsym_info(module, i, &sym, &symAddr, nullptr, nullptr, nullptr);
if (symbol)
cache.append({symAddr - elfStart, sym.st_size, symbol});
cache.append({symAddr - elfStart, sym.st_value, sym.st_size, symbol});
}
return cache;
}
Expand Down Expand Up @@ -768,6 +771,8 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
QByteArray symname;
GElf_Off off = 0;

quint64 start = 0;
quint64 size = 0;
if (mod) {
if (!addressCache->hasSymbolCache(elf.originalPath)) {
// cache all symbols in a sorted lookup table and demangle them on-demand
Expand All @@ -780,6 +785,8 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
if (cachedAddrInfo.isValid()) {
off = addressLocation.address - elfStart - cachedAddrInfo.offset;
symname = cachedAddrInfo.symname;
start = cachedAddrInfo.value;
size = cachedAddrInfo.size;

Dwarf_Addr bias = 0;
functionLocation.address -= off; // in case we don't find anything better
Expand Down Expand Up @@ -821,7 +828,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
addressLocation.parentLocationId = m_unwind->lookupLocation(functionLocation);
// otherwise resolve the inline chain if possible
if (!scopes.isEmpty() && !m_unwind->hasSymbol(addressLocation.parentLocationId)) {
functionLocation.parentLocationId = parseDwarf(cudie, subprogram, scopes, bias,
functionLocation.parentLocationId = parseDwarf(cudie, subprogram, scopes, bias, start, size,
binaryId, binaryPathId, isKernel);
}
}
Expand All @@ -838,9 +845,10 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,

if (!m_unwind->hasSymbol(addressLocation.parentLocationId)) {
// no sufficient debug information. Use what we already know
qint32 symId = m_unwind->resolveString(symname);
qint32 symId = m_unwind->resolveString(demangle(symname));
qint32 mangledSymId = m_unwind->resolveString(symname);
m_unwind->resolveSymbol(addressLocation.parentLocationId,
PerfUnwind::Symbol(symId, binaryId, binaryPathId, isKernel));
PerfUnwind::Symbol(symId, mangledSymId, start, size, binaryId, binaryPathId, isKernel));
}
} else {
if (isKernel) {
Expand All @@ -861,7 +869,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
if (!m_unwind->hasSymbol(addressLocation.parentLocationId)) {
qint32 symId = m_unwind->resolveString(symname);
m_unwind->resolveSymbol(addressLocation.parentLocationId,
PerfUnwind::Symbol(symId, binaryId, binaryPathId, isKernel));
PerfUnwind::Symbol(symId, symId, start, size, binaryId, binaryPathId, isKernel));
}
}

Expand Down
6 changes: 3 additions & 3 deletions app/perfsymboltable.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ class PerfSymbolTable
qint32 m_pid;

QByteArray symbolFromPerfMap(quint64 ip, GElf_Off *offset) const;
int parseDie(CuDieRangeMapping *cudie, Dwarf_Die *top, qint32 binaryId, qint32 binaryPathId, bool isKernel,
int parseDie(CuDieRangeMapping *cudie, Dwarf_Die *top, quint64 offset, quint64 size, qint32 binaryId, qint32 binaryPathId, bool isKernel,
Dwarf_Files *files, Dwarf_Addr entry, qint32 parentLocationId);
int insertSubprogram(CuDieRangeMapping *cudie, Dwarf_Die *top, Dwarf_Addr entry, qint32 binaryId, qint32 binaryPathId,
int insertSubprogram(CuDieRangeMapping *cudie, Dwarf_Die *top, Dwarf_Addr entry, quint64 offset, quint64 size, qint32 binaryId, qint32 binaryPathId,
qint32 inlineParent, bool isKernel);
qint32 parseDwarf(CuDieRangeMapping *cudie, SubProgramDie *subprogram, const QVector<Dwarf_Die> &inlined,
Dwarf_Addr bias, qint32 binaryId, qint32 binaryPathId, bool isKernel);
Dwarf_Addr bias, quint64 offset, quint64 size, qint32 binaryId, qint32 binaryPathId, bool isKernel);
};

QT_BEGIN_NAMESPACE
Expand Down
2 changes: 1 addition & 1 deletion app/perfunwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ QDataStream &operator<<(QDataStream &stream, const PerfUnwind::Location &locatio

QDataStream &operator<<(QDataStream &stream, const PerfUnwind::Symbol &symbol)
{
return stream << symbol.name << symbol.binary << symbol.path << symbol.isKernel;
return stream << symbol.name << symbol.mangled << symbol.relAddr << symbol.size << symbol.binary << symbol.path << symbol.isKernel;
}

static int frameCallback(Dwfl_Frame *state, void *arg)
Expand Down
7 changes: 5 additions & 2 deletions app/perfunwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,15 @@ class PerfUnwind : public QObject
};

struct Symbol {
explicit Symbol(qint32 name = -1, qint32 binary = -1, qint32 path = -1,
explicit Symbol(qint32 name = -1, qint32 mangled = -1, quint64 relAddr = 0, quint64 size = 0, qint32 binary = -1, qint32 path = -1,
bool isKernel = false) :
name(name), binary(binary), path(path), isKernel(isKernel)
name(name), mangled(mangled), relAddr(relAddr), size(size), binary(binary), path(path), isKernel(isKernel)
{}

qint32 name;
qint32 mangled;
quint64 relAddr;
quint64 size;
qint32 binary;
qint32 path;
bool isKernel;
Expand Down
2 changes: 1 addition & 1 deletion tests/auto/addresscache/tst_addresscache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private slots:
QVERIFY(!cache.findSymbol(libfoo_a, 0).isValid());
QVERIFY(!cache.findSymbol(libfoo_b, 0).isValid());

cache.setSymbolCache(libfoo_a, {{0x100, 10, "Foo"}, {0x11a, 0, "FooZ"}, {0x12a, 10, "FooN"}});
cache.setSymbolCache(libfoo_a, {{0x100, 0x100, 10, "Foo"}, {0x11a, 0x11a, 0, "FooZ"}, {0x12a, 0x12a, 10, "FooN"}});
for (auto addr : {0x100, 0x100 + 9}) {
const auto cached = cache.findSymbol(libfoo_a, addr);
QVERIFY(cached.isValid());
Expand Down

0 comments on commit 61be877

Please sign in to comment.