Skip to content

Commit

Permalink
Start to construct inlining call chains using Nvidia's extended line map
Browse files Browse the repository at this point in the history
  • Loading branch information
mxz297 authored and hainest committed Nov 11, 2021
1 parent dc45b75 commit 0f9750a
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 82 deletions.
1 change: 1 addition & 0 deletions symtabAPI/h/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ class SYMTAB_EXPORT InlinedFunction : public FunctionBase
{
friend class Symtab;
friend class DwarfWalker;
friend class Object;
protected:
InlinedFunction(FunctionBase *parent);
~InlinedFunction();
Expand Down
1 change: 1 addition & 0 deletions symtabAPI/h/Symtab.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class SYMTAB_EXPORT Symtab : public LookupInterface,
friend class emitWin;
friend class Aggregate;
friend class relocationEntry;
friend class Object;

public:

Expand Down
153 changes: 76 additions & 77 deletions symtabAPI/src/Object-elf.C
Original file line number Diff line number Diff line change
Expand Up @@ -2484,7 +2484,8 @@ Object::Object(MappedFile *mf_, bool, void (*err_func)(const char *),
EEL(false), did_open(false),
obj_type_(obj_Unknown),
DbgSectionMapSorted(false),
soname_(NULL)
soname_(NULL),
containingFunc(nullptr)
{
li_for_object = NULL;

Expand Down Expand Up @@ -3346,71 +3347,6 @@ const char *Object::interpreter_name() const {
return interpreter_name_;
}

class open_statement {
public:
open_statement() { reset(); }
Dwarf_Addr noAddress() { return (Dwarf_Addr) ~0; }
bool uninitialized() {
return start_addr == noAddress();
}
void reset() {
string_table_index = -1;
start_addr = noAddress();
end_addr = noAddress();
line_number = 0;
column_number = 0;
context = 0;
funcname_offset = 0;
};
bool sameFileLineColumn(const open_statement &rhs) {
return ((string_table_index == rhs.string_table_index) &&
(line_number == rhs.line_number) &&
(column_number == rhs.column_number));
}
void operator=(const open_statement &rhs) {
string_table_index = rhs.string_table_index;
start_addr = rhs.start_addr;
end_addr = rhs.end_addr;
line_number = rhs.line_number;
column_number = rhs.column_number;
context = rhs.context;
funcname_offset = rhs.funcname_offset;
};
friend std::ostream& operator<<(std::ostream& os, const open_statement& st)
{
st.dump(os, 0, true);
return os;
};
const char * str(Region *r, unsigned int offset) const {
return ((char *) r->getPtrToRawData()) + offset;
};
void dump(std::ostream& os, Region *debug_str, bool addrRange) const {
// to facilitate comparison with nvdisasm output, where each function starts at 0,
// set o to an offset that makes a function of interest report addresses that
// match its unrelocated offsets reported by nvdisasm
unsigned int o = 0;
if (addrRange) os << "[" << hex << start_addr - o << ", " << end_addr - o << "]";
else os << " inlined at";
os << " file:" << string_table_index;
os << " line:" << dec << line_number;
os << " col:" << column_number;
if (context) {
os << " context " << context;
os << " function name " << str(debug_str, funcname_offset);
}
os << std::endl;
}
public:
Dwarf_Word string_table_index;
Dwarf_Addr start_addr;
Dwarf_Addr end_addr;
int line_number;
int column_number;
unsigned int context;
unsigned int funcname_offset;
};


void Object::parseLineInfoForCU(Dwarf_Die cuDIE, LineInformation* li_for_module)
{
/* Acquire this CU's source lines. */
Expand Down Expand Up @@ -3608,28 +3544,91 @@ dumpLineWithInlineContext


void
recordLine
Object::recordLine
(
LineInformation *li_for_object,
Region *debug_str,
open_statement &saved_statement,
vector<open_statement> &inline_context
vector<open_statement> &inline_context,
Symtab* associated_symtab
)
{
{
// record line map entry
li_for_object->addLine((unsigned int)(saved_statement.string_table_index),
(unsigned int)(saved_statement.line_number),
(unsigned int)(saved_statement.column_number),
saved_statement.start_addr, saved_statement.end_addr);

saved_statement.start_addr, saved_statement.end_addr);
// record inline context, if any
if (inline_context.size()) {
for (unsigned int i = inline_context.size(); i > 0; i--) {
// record inline context for inline_context[i -1]

// We only do a lookup when the current function does not contain the current range
if (containingFunc == nullptr ||
containingFunc->getOffset() >= saved_statement.start_addr ||
containingFunc->getOffset() + containingFunc->getSize() < saved_statement.start_addr) {

associated_symtab->getContainingFunction(saved_statement.start_addr, containingFunc);
if (containingFunc == nullptr) {
fprintf(stderr, "Cannot find function contains range [%lx, %lx)\n", saved_statement.start_addr, saved_statement.end_addr);
assert(0);
}
}

FunctionBase* cur = static_cast<FunctionBase*>(containingFunc);
FunctionBase* outer_most = cur;
StringTablePtr strings(li_for_object->getStrings());
const char* func_name_table = static_cast<const char*>(debug_str->getPtrToRawData());

// Record all inline call sites
for (unsigned int i = 0; i < inline_context.size() - 1; ++i) {
cur = recordAnInlinedFunction(
inline_context[i],
inline_context[i + 1],
strings,
cur,
func_name_table,
saved_statement.start_addr,
saved_statement.end_addr);
}
recordAnInlinedFunction(
*(inline_context.rbegin()),
saved_statement,
strings,
cur,
func_name_table,
saved_statement.start_addr,
saved_statement.end_addr);

associated_symtab->addFunctionRange(outer_most, 0);
}

dumpLineWithInlineContext(debug_str, saved_statement, inline_context);
//dumpLineWithInlineContext(debug_str, saved_statement, inline_context);
}

InlinedFunction* Object::recordAnInlinedFunction(
open_statement& caller,
open_statement& callee,
StringTablePtr strings,
FunctionBase *parent,
const char* func_name_table,
Dwarf_Addr start,
Dwarf_Addr end
) {
InlinedFunction *ifunc = new InlinedFunction(parent);

// Use the filename and line number from the caller
const string& src_file = (*strings)[caller.string_table_index].str;
ifunc->callsite_file_number = strings->project<0>(strings->get<1>().insert(StringTableEntry(src_file,"")).first) - strings->begin();
ifunc->callsite_line = caller.line_number;

// Use the function name from the callee
const char* func_name_ptr = func_name_table + callee.funcname_offset;
ifunc->addMangledName(func_name_ptr, true, true);

ifunc->ranges.emplace_back(FuncRange(start, end - start, ifunc));

fprintf(stderr, "%p %p [%lx, %lx)", ifunc, parent, start, end);
fprintf(stderr, " func name %s, line number %d, file name %s, func name index %lx\n", func_name_ptr, ifunc->callsite_line, src_file.c_str(), caller.string_table_index);
return ifunc;
}


Expand Down Expand Up @@ -3803,7 +3802,7 @@ LineInformation* Object::parseLineInfoForObject(StringTablePtr strings)
status = dwarf_linefunctionname(line, &current_statement.funcname_offset);
if(status != 0) {
cout << "dwarf_linefunctionname failed" << endl;
continue;
continue;
}

if (saved_statement.uninitialized()) {
Expand All @@ -3820,7 +3819,7 @@ LineInformation* Object::parseLineInfoForObject(StringTablePtr strings)
// record saved_statement and its inlining context if any addresses fall
// between saved_statement and current_statement.
if (current_statement.start_addr != saved_statement.start_addr)
recordLine (li_for_object, debug_str, saved_statement, inline_context);
recordLine (li_for_object, debug_str, saved_statement, inline_context, associated_symtab);

// record saved_statement as inlined context for current_statement`
inline_context.push_back(saved_statement);
Expand All @@ -3833,7 +3832,7 @@ LineInformation* Object::parseLineInfoForObject(StringTablePtr strings)
if (!pushed) {
// we didn't add saved_statement to the inlined context of current_statement,
// so a line map entry for saved_statement needs to be recorded
recordLine (li_for_object, debug_str, saved_statement, inline_context);
recordLine (li_for_object, debug_str, saved_statement, inline_context, associated_symtab);
}

if (current_statement.context == 0) {
Expand Down
84 changes: 84 additions & 0 deletions symtabAPI/src/Object-elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,73 @@ class pdElfShdr;
class Symtab;
class Region;
class Object;
class InlinedFunction;

class open_statement {
public:
open_statement() { reset(); };
Dwarf_Addr noAddress() { return (Dwarf_Addr) ~0; }
bool uninitialized() {
return start_addr == noAddress();
};
void reset() {
string_table_index = -1;
start_addr = noAddress();
end_addr = noAddress();
line_number = 0;
column_number = 0;
context = 0;
funcname_offset = 0;
};
bool sameFileLineColumn(const open_statement &rhs) {
return ((string_table_index == rhs.string_table_index) &&
(line_number == rhs.line_number) &&
(column_number == rhs.column_number));
};
void operator=(const open_statement &rhs) {
string_table_index = rhs.string_table_index;
start_addr = rhs.start_addr;
end_addr = rhs.end_addr;
line_number = rhs.line_number;
column_number = rhs.column_number;
context = rhs.context;
funcname_offset = rhs.funcname_offset;
};
friend std::ostream& operator<<(std::ostream& os, const open_statement& st)
{
st.dump(os, 0, true);
return os;
};
const char * str(Region *r, unsigned int offset) const {
return ((char *) r->getPtrToRawData()) + offset;
};
void dump(std::ostream& os, Region *debug_str, bool addrRange) const {
// to facilitate comparison with nvdisasm output, where each function starts at 0,
// set o to an offset that makes a function of interest report addresses that
// match its unrelocated offsets reported by nvdisasm
unsigned int o = 0;
if (addrRange) os << "[" << std::hex << start_addr - o << ", " << end_addr - o << "]";
else os << " inlined at";
os << " file:" << string_table_index;
os << " line:" << std::dec << line_number;
os << " col:" << column_number;
if (context) {
os << " context " << context;
os << " function name " << str(debug_str, funcname_offset);
os << " function name offset " << std::hex << funcname_offset << std::dec;
}
os << std::endl;
}
public:
Dwarf_Word string_table_index;
Dwarf_Addr start_addr;
Dwarf_Addr end_addr;
int line_number;
int column_number;
unsigned int context;
unsigned int funcname_offset;
};


class Object : public AObject
{
Expand Down Expand Up @@ -349,6 +416,22 @@ class Object : public AObject

private:
void parseLineInfoForCU(Module::DebugInfoT cuDIE, LineInformation* li);
void recordLine(
LineInformation *li_for_object,
Region *debug_str,
open_statement &saved_statement,
std::vector<open_statement> &inline_context,
Symtab* associated_symtab
);
InlinedFunction* recordAnInlinedFunction(
open_statement&,
open_statement&,
StringTablePtr,
FunctionBase*,
const char*,
Dwarf_Addr,
Dwarf_Addr
);

LineInformation* li_for_object;
LineInformation* parseLineInfoForObject(StringTablePtr strings);
Expand Down Expand Up @@ -422,6 +505,7 @@ class Object : public AObject
std::vector<std::pair<long, long> > new_dynamic_entries;
private:
const char* soname_;
Function* containingFunc;

};

Expand Down
10 changes: 5 additions & 5 deletions symtabAPI/src/Symtab-lookup.C
Original file line number Diff line number Diff line change
Expand Up @@ -722,13 +722,13 @@ bool Symtab::addFunctionRange(FunctionBase *func, Dyninst::Offset next_start)
for (FuncRangeCollection::iterator i = ranges.begin(); i != ranges.end(); i++) {
FuncRange &range = *i;
if (range.low() == sym_low && range.high() == sym_high)
found_sym_range = true;
found_sym_range = true;
func_lookup->insert(&range);
}

//Add symbol range to func_lookup, if present and not already added
if (!found_sym_range && sym_low && sym_high) {
FuncRange *frange = new FuncRange(sym_low, sym_high - sym_low, func);
FuncRange *frange = new FuncRange(sym_low, sym_high - sym_low, func);
func_lookup->insert(frange);
}

Expand Down Expand Up @@ -825,7 +825,7 @@ bool Symtab::getContainingFunction(Offset offset, Function* &func)
}

bool Symtab::getContainingInlinedFunction(Offset offset, FunctionBase* &func)
{
{
if (!func_lookup)
parseFunctionRanges();
assert(func_lookup);
Expand All @@ -851,7 +851,7 @@ bool Symtab::getContainingInlinedFunction(Offset offset, FunctionBase* &func)
// Therefore, here we heuristicaly prefer the deeper call chain
// to reflect inlining information.
int maxDepth = 0;
for (auto range : ranges) {
for (auto range : ranges) {
FunctionBase *cur_func = range->container;
int depth = 0;
while (cur_func) {
Expand All @@ -862,7 +862,7 @@ bool Symtab::getContainingInlinedFunction(Offset offset, FunctionBase* &func)
maxDepth = depth;
func = range->container;
}
}
}
return true;
}

Expand Down

0 comments on commit 0f9750a

Please sign in to comment.