Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions include/dwarfstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ extern "C" {
// funcname: function name
// context: user-provided pointer (callbackContext)
// columnno: column number
// For an address inside inlined code, the callback is called once per
// inlined function (innermost first) and finally for the containing
// function; addr is 0 for all but the first of these calls.
typedef void dwstCallback(
uint64_t addr,const char *filename,int lineno,const char *funcname,
void *context,int columnno );
Expand Down Expand Up @@ -75,6 +78,19 @@ typedef void dwstCallbackW(
// filename: executable location
#define DWST_NOT_FOUND -3

// DWST_LINE_ADDR: start address of the source line (only dwstOfModule())
// addr: line address
// (0 for the outer frames of inlined code)
// filename: NULL
// funcname: function name
#define DWST_LINE_ADDR -4

// DWST_FUNC_ADDR: start address of the function (only dwstOfModule())
// addr: function address
// filename: NULL
// funcname: function name
#define DWST_FUNC_ADDR -5


// dwstOfFile(): stack information of file
// name: executable location
Expand All @@ -95,6 +111,42 @@ EXPORT int dwstOfFileW(
dwstCallbackW *callbackFunc,void *callbackContext );


typedef struct dwst_module dwst_module;

// dwstModuleOpen(): prepare debug information for repeated lookups
// dbg: Dwarf_Debug of the executable
// (has to stay valid until dwstModuleClose())
// imageBase_dbg: preferred image base address of the executable
EXPORT dwst_module *dwstModuleOpen(
void *dbg,uint64_t imageBase_dbg );

// dwstModuleClose(): free module created by dwstModuleOpen()
// (dbg itself is not freed)
// module: module handle
EXPORT void dwstModuleClose(
dwst_module *module );

// dwstOfModule(): stack information of module
// (like dwstOfFile(), but additionally reports DWST_FUNC_ADDR and
// DWST_LINE_ADDR before each resolved frame)
// module: module handle from dwstModuleOpen()
// name: executable location
// imageBase: used image base address
// addr: stack addresses
// count: number of addresses
// callbackFunc: callback function
// callbackContext: user-provided pointer (context)
EXPORT int dwstOfModule(
dwst_module *module,const char *name,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallback *callbackFunc,void *callbackContext );

EXPORT int dwstOfModuleW(
dwst_module *module,const wchar_t *name,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallbackW *callbackFunc,void *callbackContext );


// dwstOfProcess(): stack information of current process
// addr: stack addresses
// count: number of addresses
Expand Down
158 changes: 135 additions & 23 deletions src/dwst-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,29 @@ typedef struct inline_info
uint64_t ptrOrig;
int fileno,lineno,columnno;
int fileno_offs;
Dwarf_Addr lineaddr;
uint64_t baseOffs;
int reportAddrs;
} inline_info;

// report start addresses of function and source line
static void dwarf_callback_addrs( inline_info *cuInfo,
Dwarf_Addr low,const char *funcname )
{
if( !cuInfo->reportAddrs ) return;

if( low )
dwarf_callback( cuInfo->callbackFunc,cuInfo->callbackFuncW,
low - cuInfo->baseOffs,NULL,NULL,
DWST_FUNC_ADDR,funcname,cuInfo->callbackContext,cuInfo->columnno );

// lineaddr is 0 for the outer frames of inlined code, DWARF doesn't
// store where the code of the call line starts
dwarf_callback( cuInfo->callbackFunc,cuInfo->callbackFuncW,
cuInfo->lineaddr ? cuInfo->lineaddr - cuInfo->baseOffs : 0,NULL,NULL,
DWST_LINE_ADDR,funcname,cuInfo->callbackContext,cuInfo->columnno );
}

// find the calling-location of inlined functions
static int findInlined( Dwarf_Debug dbg,Dwarf_Die die,inline_info *cuInfo )
{
Expand Down Expand Up @@ -353,6 +374,7 @@ static int findInlined( Dwarf_Debug dbg,Dwarf_Die die,inline_info *cuInfo )
if( cuInfo->ptr<lowpc || cuInfo->ptr>=highpc )
continue;

low = lowpc;
break;
}

Expand All @@ -366,6 +388,8 @@ static int findInlined( Dwarf_Debug dbg,Dwarf_Die die,inline_info *cuInfo )
{
char *funcname = dwarf_name_of_func_linked( dbg,die );

dwarf_callback_addrs( cuInfo,low,funcname );

dwarf_callback( cuInfo->callbackFunc,cuInfo->callbackFuncW,
cuInfo->ptrOrig,cuInfo->files[cuInfo->fileno],NULL,
cuInfo->lineno,funcname,cuInfo->callbackContext,cuInfo->columnno );
Expand Down Expand Up @@ -394,6 +418,8 @@ static int findInlined( Dwarf_Debug dbg,Dwarf_Die die,inline_info *cuInfo )
{
char *funcname = dwarf_name_of_func_linked( dbg,die );

dwarf_callback_addrs( cuInfo,low,funcname );

dwarf_callback( cuInfo->callbackFunc,cuInfo->callbackFuncW,
cuInfo->ptrOrig,cuInfo->files[cuInfo->fileno],NULL,
cuInfo->lineno,funcname,cuInfo->callbackContext,cuInfo->columnno );
Expand All @@ -402,6 +428,7 @@ static int findInlined( Dwarf_Debug dbg,Dwarf_Die die,inline_info *cuInfo )
cuInfo->lineno = lineno;
cuInfo->columnno = 0;
cuInfo->ptrOrig = 0;
cuInfo->lineaddr = 0;

Dwarf_Attribute callcolumn;
if( dwarf_attr(die,DW_AT_call_column,&callcolumn,NULL)==DW_DLV_OK )
Expand Down Expand Up @@ -444,30 +471,21 @@ typedef struct cu_info
int rangeCount;
} cu_info;

int dwstOfFileExt(
const char *name,const wchar_t *nameW,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallback *callbackFunc,dwstCallbackW *callbackFuncW,
void *callbackContext )
struct dwst_module
{
if( !nameW || !addr || !count || (!callbackFunc && !callbackFuncW) )
return( 0 );

if( imageBase )
dwarf_callback( callbackFunc,callbackFuncW,imageBase,name,nameW,
DWST_BASE_ADDR,NULL,callbackContext,0 );

Dwarf_Addr imageBase_dbg;
Dwarf_Debug dbg;
if( dwarf_pe_init(nameW,&imageBase_dbg,0,0,&dbg,NULL)!=DW_DLV_OK )
{
int i;
for( i=0; i<count; i++ )
dwarf_callback( callbackFunc,callbackFuncW,addr[i],name,nameW,
DWST_NO_DBG_SYM,NULL,callbackContext,0 );
Dwarf_Addr imageBase_dbg;
cu_info *cuArr;
int cuQty;
};

return( count );
}
dwst_module *dwstModuleOpen(
void *dbg,uint64_t imageBase_dbg )
{
if( !dbg ) return( NULL );

dwst_module *module = malloc( sizeof(dwst_module) );
if( !module ) return( NULL );

cu_info *cuArr = NULL;
int cuQty = 0;
Expand Down Expand Up @@ -608,6 +626,28 @@ int dwstOfFileExt(
dwarf_dealloc( dbg,die,DW_DLA_DIE );
}

module->dbg = dbg;
module->imageBase_dbg = imageBase_dbg;
module->cuArr = cuArr;
module->cuQty = cuQty;

return( module );
}

static int dwstOfModuleExt(
dwst_module *module,const char *name,const wchar_t *nameW,
uint64_t imageBase,uint64_t *addr,int count,
dwstCallback *callbackFunc,dwstCallbackW *callbackFuncW,
void *callbackContext,int reportAddrs )
{
if( !module || !addr || !count || (!callbackFunc && !callbackFuncW) )
return( 0 );

Dwarf_Debug dbg = module->dbg;
Dwarf_Addr imageBase_dbg = module->imageBase_dbg;
cu_info *cuArr = module->cuArr;
int cuQty = module->cuQty;

uint64_t baseOffs = 0;
if( imageBase )
{
Expand Down Expand Up @@ -664,6 +704,7 @@ int dwstOfFileExt(
Dwarf_Unsigned srcfileno = 0;
Dwarf_Unsigned lineno = 0;
Dwarf_Unsigned columnno = 0;
Dwarf_Addr lineaddr = 0;
if( lines )
{
int c;
Expand All @@ -686,6 +727,7 @@ int dwstOfFileExt(
continue;
}

dwarf_lineaddr( lines[c-1],&lineaddr,NULL );
dwarf_line_srcfileno( lines[c-1],&srcfileno,NULL );
dwarf_lineno( lines[c-1],&lineno,NULL );
dwarf_lineoff_b( lines[c-1],&columnno,NULL );
Expand Down Expand Up @@ -715,7 +757,7 @@ int dwstOfFileExt(
inline_info ii = { ptr,cuInfo->base,
files,fileCount,callbackFunc,callbackFuncW,callbackContext,
ptrOrig,(int)srcfileno+cuInfo->fileno_offs,lineno,columnno,
cuInfo->fileno_offs };
cuInfo->fileno_offs,lineaddr,baseOffs,reportAddrs };
walkChildren( dbg,die,(ChildWalker*)findInlined,&ii );
}
else
Expand All @@ -734,6 +776,18 @@ int dwstOfFileExt(
DWST_NOT_FOUND,NULL,callbackContext,0 );
}

return( i );
}

void dwstModuleClose(
dwst_module *module )
{
if( !module ) return;

Dwarf_Debug dbg = module->dbg;
cu_info *cuArr = module->cuArr;
int cuQty = module->cuQty;
int j;
for( j=0; j<cuQty; j++ )
{
if( cuArr[j].lines )
Expand All @@ -753,10 +807,47 @@ int dwstOfFileExt(
free( cuArr[j].ranges );
}
free( cuArr );
free( module );
}

int dwstOfFileExt(
const char *name,const wchar_t *nameW,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallback *callbackFunc,dwstCallbackW *callbackFuncW,
void *callbackContext )
{
if( !nameW || !addr || !count || (!callbackFunc && !callbackFuncW) )
return( 0 );

if( imageBase )
dwarf_callback( callbackFunc,callbackFuncW,imageBase,name,nameW,
DWST_BASE_ADDR,NULL,callbackContext,0 );

Dwarf_Addr imageBase_dbg;
Dwarf_Debug dbg;
if( dwarf_pe_init(nameW,&imageBase_dbg,0,0,&dbg,NULL)!=DW_DLV_OK )
{
int i;
for( i=0; i<count; i++ )
dwarf_callback( callbackFunc,callbackFuncW,addr[i],name,nameW,
DWST_NO_DBG_SYM,NULL,callbackContext,0 );

return( count );
}

int ret = 0;
dwst_module *module = dwstModuleOpen( dbg,imageBase_dbg );
if( module )
{
ret = dwstOfModuleExt( module,name,nameW,imageBase,addr,count,
callbackFunc,callbackFuncW,callbackContext,0 );

dwstModuleClose( module );
}

dwarf_pe_finish( dbg,NULL );

return( i );
return( ret );
}

int dwstOfFile(
Expand All @@ -779,3 +870,24 @@ int dwstOfFileW(
return( dwstOfFileExt(NULL,name,imageBase,addr,count,
NULL,callbackFunc,callbackContext) );
}

int dwstOfModule(
dwst_module *module,const char *name,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallback *callbackFunc,void *callbackContext )
{
wchar_t *nameW = dwst_ansi2wide( name );
int ret = dwstOfModuleExt( module,name,nameW,imageBase,addr,count,
callbackFunc,NULL,callbackContext,1 );
free( nameW );
return( ret );
}

int dwstOfModuleW(
dwst_module *module,const wchar_t *name,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallbackW *callbackFunc,void *callbackContext )
{
return( dwstOfModuleExt(module,NULL,name,imageBase,addr,count,
NULL,callbackFunc,callbackContext,1) );
}
Loading