gctf2023/pwn/flipper/dist/common/source/util/SWEBDebugInfo.cpp
2023-11-24 13:11:34 -05:00

113 lines
2.8 KiB
C++

#include <ustl/ustring.h>
#include "kprintf.h"
#include "SWEBDebugInfo.h"
#include "Stabs2DebugInfo.h"
#include "ArchCommon.h"
#include "ArchMemory.h"
struct FileHeader {
uint16_t functions;
uint8_t filename_len;
} __attribute__((packed));
struct FunctionHeader {
uint64_t offset;
uint16_t line_entries;
uint8_t name_len;
} __attribute__((packed));
struct LineHeader {
uint16_t offset;
uint16_t number;
} __attribute__((packed));
SWEBDebugInfo::SWEBDebugInfo(char const *sweb_start, char const *sweb_end) : Stabs2DebugInfo(sweb_start, sweb_end, 0) {
if (sweb_start != 0 && sweb_end != 0)
initialiseSymbolTable();
}
SWEBDebugInfo::~SWEBDebugInfo() {
}
void SWEBDebugInfo::initialiseSymbolTable() {
function_defs_.reserve(256);
file_addrs_.reserve(256);
char *data = (char *) stab_start_ + 8;
char buffer[256];
do {
FileHeader *fh = (FileHeader *) data;
data += sizeof(FileHeader);
strncpy(buffer, data, fh->filename_len);
buffer[fh->filename_len] = 0;
data += fh->filename_len;
ustl::string filename(buffer);
for(int fn = 0; fn < fh->functions; fn++) {
FunctionHeader* fnh = (FunctionHeader*)data;
if(fn == 0) {
file_addrs_[fnh->offset] = filename;
}
function_defs_[fnh->offset] = data;
data += sizeof(FunctionHeader);
data += fnh->name_len;
data += fnh->line_entries * sizeof(LineHeader);
}
} while(data != (char*)stab_end_);
debug(USERTRACE, "found %zd sweb debug functions\n", function_defs_.size());
}
void SWEBDebugInfo::getCallNameAndLine(pointer address, const char *&name, ssize_t &line) const {
name = "UNKNOWN FUNCTION";
line = 0;
if (!this || function_defs_.size() == 0)
return;
FunctionHeader* fh = 0;
for(auto f : function_defs_) {
if (address >= f.first)
fh = (FunctionHeader*)f.second;
}
if (fh == 0)
return;
name = ((char*)fh) + sizeof(FunctionHeader);
LineHeader* lh = (LineHeader*)((char*)(fh + 1) + fh->name_len);
bool found = false;
for(int e = 0; e < fh->line_entries; e++) {
if(address < fh->offset + lh->offset) {
lh--;
found = true;
break;
} else if(address == fh->offset + lh->offset) {
found = true;
break;
}
lh++;
}
line = found ? lh->number : -(int)(address - fh->offset);
}
void SWEBDebugInfo::printCallInformation(pointer address) const {
const char *name;
ssize_t line;
getCallNameAndLine(address, name, line);
if (line >= 0) {
kprintfd("%10zx: %." CALL_FUNC_NAME_LIMIT_STR "s:%zu \n", address, name, line );
}
else {
kprintfd("%10zx: %." CALL_FUNC_NAME_LIMIT_STR "s+%zx\n", address, name, -line);
}
}