Skip to content

Commit

Permalink
Cache module DIEs and build ranges as interval trees.
Browse files Browse the repository at this point in the history
  • Loading branch information
wrwilliams committed Oct 19, 2016
1 parent 85bd675 commit 8580fba
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 121 deletions.
5 changes: 3 additions & 2 deletions symtabAPI/h/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,9 @@ class SYMTAB_EXPORT FunctionBase
{return Aggregate::addMangledName(name, isPrimary, isDebug);}
virtual bool addPrettyName(std::string name, bool isPrimary, bool isDebug=false)
{return Aggregate::addPrettyName(name, isPrimary, isDebug);}
virtual Module* getModule() const { return module_; }
};

virtual Module * getModule() const;
};

class SYMTAB_EXPORT InlinedFunction : public FunctionBase
{
Expand Down
16 changes: 16 additions & 0 deletions symtabAPI/h/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@

#include "Annotatable.h"
#include "Serialization.h"
#include "IBSTree.h"
#if defined(cap_dwarf)
#include "libdwarf.h"
#endif

namespace Dyninst{
namespace SymtabAPI{
Expand Down Expand Up @@ -106,6 +110,11 @@ typedef Statement LineNoTuple;

class SYMTAB_EXPORT Module : public LookupInterface
{
#if defined(cap_dwarf)
typedef Dwarf_Die DebugInfoT;
#else
typedef void* DebugInfoT;
#endif
friend class Symtab;

public:
Expand Down Expand Up @@ -193,9 +202,16 @@ typedef Statement LineNoTuple;
}

bool setLineInfo(Dyninst::SymtabAPI::LineInformation *lineInfo);
void addRange(Dyninst::Address low, Dyninst::Address high);
bool containsOffset(Dyninst::Offset offset) const;
void setDebugInfo(Module::DebugInfoT info) {info_is_valid_ = true; info_ = info; }
Module::DebugInfoT getDebugInfo();
private:
Dyninst::SymtabAPI::LineInformation* lineInfo_;
typeCollection* typeInfo_;
IBSTree<SimpleInterval> ranges;
bool info_is_valid_;
Module::DebugInfoT info_;


std::string fileName_; // short file
Expand Down
4 changes: 4 additions & 0 deletions symtabAPI/src/Function.C
Original file line number Diff line number Diff line change
Expand Up @@ -475,3 +475,7 @@ unsigned InlinedFunction::getSize() const
{
return functionSize_;//inline_parent->getSize();
}

Module* Function::getModule() const {
return module_;
}
21 changes: 19 additions & 2 deletions symtabAPI/src/Module.C
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ Module::Module() :
fullName_(""),
language_(lang_Unknown),
addr_(0),
exec_(NULL)
exec_(NULL),
info_is_valid_(false)
{
}

Expand All @@ -315,7 +316,9 @@ Module::Module(const Module &mod) :
fullName_(mod.fullName_),
language_(mod.language_),
addr_(mod.addr_),
exec_(mod.exec_)
exec_(mod.exec_),
info_is_valid_(false),
info_(mod.info_)
{
}

Expand Down Expand Up @@ -419,3 +422,17 @@ bool Module::findVariablesByName(std::vector<Variable *> &ret, const std::string
return succ;
}

void Module::addRange(Dyninst::Address low, Dyninst::Address high)
{
ranges.insert(new SimpleInterval(low, high, this));
}

bool Module::containsOffset(Dyninst::Offset offset) const {
std::set<SimpleInterval*> found_entries;
return ranges.find(offset, found_entries) > 0;
}

Module::DebugInfoT Module::getDebugInfo()
{
if(!info_is_valid_) exec_->parseTypesNow(); return info_;
}
107 changes: 13 additions & 94 deletions symtabAPI/src/Object-elf.C
Original file line number Diff line number Diff line change
Expand Up @@ -4185,7 +4185,8 @@ void Object::parseStabFileLineInfo(Symtab *st)
// haveParsedFileMap[ key ] = true;
} /* end parseStabFileLineInfo() */

bool Object::addrInCU(Dwarf_Debug dbg, Dwarf_Die cu, Address to_check)

bool Object::addrInCU(Dwarf_Debug dbg, Dwarf_Die cu, Address to_check, Module *mod_for_cu)
{
Dwarf_Addr tempLow = 0, tempHigh = -1;
Address low = 0, high = -1;
Expand Down Expand Up @@ -4304,11 +4305,13 @@ void Object::parseLineInfoForCU(Dwarf_Die cuDIE, LineInformation* li_for_module)
Dwarf_Debug *dbg_ptr = dwarf->line_dbg();
if (!dbg_ptr)
return;
Dwarf_Debug &dbg = *dbg_ptr;
if(!cuDIE) return;
Dwarf_Debug dbg = *dbg_ptr;
/* Acquire this CU's source lines. */
Dwarf_Line * lineBuffer;
Dwarf_Signed lineCount;
int status = dwarf_srclines( cuDIE, & lineBuffer, & lineCount, NULL );
Dwarf_Error ignored;
int status = dwarf_srclines( cuDIE, & lineBuffer, & lineCount, &ignored );

/* See if we can get anything useful out of the next CU
if this one is corrupt. */
Expand Down Expand Up @@ -4421,11 +4424,9 @@ void Object::parseLineInfoForCU(Dwarf_Die cuDIE, LineInformation* li_for_module)
/* If the current line ends the sequence, invalidate previous; otherwise, update. */
if ( isEndOfSequence )
{
dwarf_dealloc( dbg, lineSource, DW_DLA_STRING );
isPreviousValid = false;
}
else {
if( isPreviousValid ) { dwarf_dealloc( dbg, previousLineSource, DW_DLA_STRING ); }
previousLineNo = lineNo;
previousLineSource = lineSource;
previousLineAddr = lineAddr;
Expand All @@ -4448,105 +4449,23 @@ void Object::parseLineInfoForAddr(Symtab* obj, Offset addr_to_find)
return;
Module* mod_for_offset = NULL;
obj->findModuleByOffset(mod_for_offset, addr_to_find);
std::string mod_to_check;
if(mod_for_offset)

{
if(mod_for_offset->hasLineInformation()) // already parsed
{
return;
}
mod_to_check = mod_for_offset->fileName();
}

Dwarf_Debug &dbg = *dbg_ptr;

/* Only .debug_info for now, not .debug_types */
Dwarf_Bool is_info = 1;

/* Itereate over the CU headers. */
Dwarf_Unsigned header;
while ( dwarf_next_cu_header_c( dbg, is_info,
NULL, NULL, NULL, // len, stamp, abbrev
NULL, NULL, NULL, // address, offset, extension
NULL, NULL, // signature, typeoffset
& header, NULL ) == DW_DLV_OK )
{
/* Acquire the CU DIE. */
Dwarf_Die cuDIE;
int status = dwarf_siblingof_b( dbg, NULL, is_info, & cuDIE, NULL);
if ( status != DW_DLV_OK ) {
/* If we can get no (more) CUs, we're done. */
break;
}

char * cuName;
const char *moduleName;
status = dwarf_diename( cuDIE, &cuName, NULL );
if ( status == DW_DLV_NO_ENTRY ) {
cuName = NULL;
moduleName = "DEFAULT_MODULE";
}
else {
moduleName = strrchr(cuName, '/');
if (!moduleName)
moduleName = strrchr(cuName, '\\');
if (moduleName)
moduleName++;
else
moduleName = cuName;
}
if(cuName && modules_parsed_for_line_info.find(cuName) != modules_parsed_for_line_info.end())
{
dwarf_dealloc(dbg, cuDIE, DW_DLA_DIE);
continue;
}
if(mod_to_check != "" && strcmp(moduleName, mod_to_check.c_str()) != 0)
{
dwarf_dealloc(dbg, cuDIE, DW_DLA_DIE);
continue;
}
// Parse line info for each CU once, completely, if a user has asked for something within
// that CU
if(!addrInCU(dbg, cuDIE, addr_to_find))
{
dwarf_dealloc(dbg, cuDIE, DW_DLA_DIE);
continue;
}
Module* mod = NULL;
for(auto found_mod = modules_.begin();
found_mod != modules_.end();
++found_mod)
{
if(found_mod->first == moduleName) {
obj->getOrCreateModule(found_mod->first, found_mod->second);
break;
}
}

if(!obj->findModuleByName(mod, moduleName))
{
mod = obj->getDefaultModule();
// cout << "Default module filename is " << mod->fileName() << endl;
}
LineInformation* li_for_module = mod->getLineInformation();
Dwarf_Die cuDIE = mod_for_offset->getDebugInfo();
LineInformation* li_for_module = mod_for_offset->getLineInformation();
if(!li_for_module)
{
li_for_module = new LineInformation;
mod->setLineInfo(li_for_module);
}
// cout << "Parsing line info for " << mod->fileName() << endl;
parseLineInfoForCU(cuDIE, li_for_module);
if (cuName)
{
modules_parsed_for_line_info.insert(cuName);
dwarf_dealloc( dbg, cuName, DW_DLA_STRING );
mod_for_offset->setLineInfo(li_for_module);
}

/* Free this CU's DIE. */
dwarf_dealloc( dbg, cuDIE, DW_DLA_DIE );
} /* end CU header iteration */
/* Note that we've parsed this file. */
parseLineInfoForCU(cuDIE, li_for_module);
}
// no mod for offset means no line info for sure if we've parsed all ranges...
}


Expand All @@ -4558,7 +4477,7 @@ void Object::parseDwarfFileLineInfo(Symtab* st)
Dwarf_Debug *dbg_ptr = dwarf->line_dbg();
if (!dbg_ptr)
return;
Dwarf_Debug &dbg = *dbg_ptr;
Dwarf_Debug dbg = *dbg_ptr;

/* Only .debug_info for now, not .debug_types */
Dwarf_Bool is_info = 1;
Expand Down
6 changes: 2 additions & 4 deletions symtabAPI/src/Object-elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,11 +522,9 @@ class Object;
void parseLineInfoForAddr(Symtab* obj, Offset addr_to_find);

private:
bool addrInCU(Dwarf_Debug dbg, Dwarf_Die cu, Address to_find);
bool addrInCU(Dwarf_Debug dbg, Dwarf_Die cu, Address to_find, Module *mod_for_cu);
void parseLineInfoForCU(Dwarf_Die cuDIE, LineInformation* li);


void createLineInfoForModules(dyn_hash_map<std::string, LineInformation> &li);

void parseDwarfTypes(Symtab *obj);
void parseStabTypes(Symtab *obj);

Expand Down
6 changes: 1 addition & 5 deletions symtabAPI/src/Symtab-lookup.C
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,10 @@ bool module_less(Module* lhs, Module* rhs)

bool Symtab::findModuleByOffset(Module *&ret, Offset off)
{
std::sort(_mods.begin(), _mods.end(), module_less);
// this should be a hash, really
for(size_t i = 0; i < _mods.size(); i++)
{
// cout << *(_mods[i]) << endl;
if(_mods[i]->addr() == off)
//&& i < _mods.size() - 1 &&
// off < _mods[i+1]->addr())
if(_mods[i]->containsOffset(off))
{
ret = _mods[i];
return true;
Expand Down
34 changes: 23 additions & 11 deletions symtabAPI/src/dwarfWalker.C
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ bool DwarfWalker::parseModule(Dwarf_Bool is_info, Module *&fixUnknownMod) {


if (!parse_int(moduleDIE, true)) return false;
if(mod()) mod()->setDebugInfo(moduleDIE);

return true;

Expand Down Expand Up @@ -649,6 +650,7 @@ void DwarfWalker::setFuncRanges() {
last_high = high;

curFunc()->ranges.push_back(FuncRange(low, high - low, curFunc()));
if(mod()) mod()->addRange(low, high);
}
}
}
Expand Down Expand Up @@ -676,6 +678,7 @@ bool DwarfWalker::parseHighPCLowPC(Dwarf_Die entry)
}
dwarf_printf("(0x%lx) Lexical block from 0x%lx to 0x%lx\n", id(), low, high);
setRange(make_pair(low, high));
if(mod()) mod()->addRange(low, high);
return true;

}
Expand Down Expand Up @@ -709,6 +712,7 @@ bool DwarfWalker::parseRangeTypes() {
Address high = cur->dwr_addr2 + cur_base;
dwarf_printf("(0x%lx) Lexical block from 0x%lx to 0x%lx\n", id(), low, high);
setRange(make_pair(low, high));
mod()->addRange(low, high);
break;
}
case DW_RANGES_ADDRESS_SELECTION:
Expand Down Expand Up @@ -1021,8 +1025,11 @@ bool DwarfWalker::parseTypedef() {
if (!fixName(curName(), referencedType)) return false;
}

typeTypedef * typedefType = new typeTypedef( type_id(), referencedType, curName());
typedefType = tc()->addOrUpdateType( typedefType );
if(tc())
{
typeTypedef * typedefType = new typeTypedef( type_id(), referencedType, curName());
typedefType = tc()->addOrUpdateType( typedefType );
}

return true;
}
Expand Down Expand Up @@ -1233,16 +1240,20 @@ bool DwarfWalker::parseConstPackedVolatile() {

if (!findName(curName())) return false;

Type *type = NULL;
if (!findType(type, true)) return false;

if (!nameDefined()) {
if (!fixName(curName(), type)) return false;
}
if(tc())
{
Type *type = NULL;
if (!findType(type, true)) return false;

typeTypedef * modifierType = new typeTypedef(type_id(), type, curName());
assert( modifierType != NULL );
modifierType = tc()->addOrUpdateType( modifierType );
if (!nameDefined()) {
if (!fixName(curName(), type)) return false;
}
typeTypedef * modifierType = new typeTypedef(type_id(), type, curName());
assert( modifierType != NULL );
modifierType = tc()->addOrUpdateType( modifierType );

}
return true;
}

Expand Down Expand Up @@ -1273,7 +1284,8 @@ bool DwarfWalker::parseTypeReferences() {
return false;
}

assert( indirectType != NULL );
assert( indirectType != NULL );
}
return true;
}

Expand Down

0 comments on commit 8580fba

Please sign in to comment.