libdwarf
Jitreader Demonstrating DWARF without a file.
*/
#include <config.h>
#include <stddef.h> /* NULL */
#include <stdio.h> /* printf() */
#include <stdlib.h> /* exit() */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
/*
This demonstates processing DWARF
from in_memory data. For simplicity
in this example we are using static arrays.
The C source is src/bin/dwarfexample/jitreader.c
The motivation is from JIT compiling, where
at runtime of some application, it generates
code on the file and DWARF information for it too.
This gives an example of enabling all of libdwarf's
functions without actually having the DWARF information
in a file. (If you have a file in some odd format
you can use this approach to have libdwarf access
the format for DWARF data and work normally without
ever exposing the format to libdwarf.)
None of the structures defined here in this source
(or any source using this feature)
are ever known to libdwarf. They are totally
private to your code.
The code you write (like this example) you compile
separate from libdwarf. You never place your code
into libdwarf, you just link your code into
your application and link against libdwarf.
*/
/* Some valid DWARF2 data */
static Dwarf_Small abbrevbytes[] = {
0x01, 0x11, 0x01, 0x25, 0x0e, 0x13, 0x0b, 0x03, 0x08, 0x1b,
0x0e, 0x11, 0x01, 0x12, 0x01, 0x10, 0x06, 0x00, 0x00, 0x02,
0x2e, 0x01, 0x3f, 0x0c, 0x03, 0x08, 0x3a, 0x0b, 0x3b, 0x0b,
0x39, 0x0b, 0x27, 0x0c, 0x11, 0x01, 0x12, 0x01, 0x40, 0x06,
0x97, 0x42, 0x0c, 0x01, 0x13, 0x00, 0x00, 0x03, 0x34, 0x00,
0x03, 0x08, 0x3a, 0x0b, 0x3b, 0x0b, 0x39, 0x0b, 0x49, 0x13,
0x02, 0x0a, 0x00, 0x00, 0x04, 0x24, 0x00, 0x0b, 0x0b, 0x3e,
0x0b, 0x03, 0x08, 0x00, 0x00, 0x00, };
static Dwarf_Small infobytes[] = {
0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x2e, 0x63,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x66, 0x00, 0x01,
0x02, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x00, 0x03, 0x69,
0x00, 0x01, 0x03, 0x08, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x91,
0x6c, 0x00, 0x04, 0x04, 0x05, 0x69, 0x6e, 0x74, 0x00, 0x00, };
static Dwarf_Small strbytes[] = {
0x47, 0x4e, 0x55, 0x20, 0x43, 0x31, 0x37, 0x20, 0x39, 0x2e,
0x33, 0x2e, 0x30, 0x20, 0x2d, 0x6d, 0x74, 0x75, 0x6e, 0x65,
0x3d, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x20, 0x2d,
0x6d, 0x61, 0x72, 0x63, 0x68, 0x3d, 0x78, 0x38, 0x36, 0x2d,
0x36, 0x34, 0x20, 0x2d, 0x67, 0x64, 0x77, 0x61, 0x72, 0x66,
0x2d, 0x32, 0x20, 0x2d, 0x4f, 0x30, 0x20, 0x2d, 0x66, 0x61,
0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75,
0x73, 0x2d, 0x75, 0x6e, 0x77, 0x69, 0x6e, 0x64, 0x2d, 0x74,
0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x2d, 0x66, 0x73, 0x74,
0x61, 0x63, 0x6b, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63,
0x74, 0x6f, 0x72, 0x2d, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
0x20, 0x2d, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2d, 0x63,
0x6c, 0x61, 0x73, 0x68, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x2d, 0x66, 0x63, 0x66,
0x2d, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x00, 0x2f, 0x76, 0x61, 0x72, 0x2f, 0x74, 0x6d, 0x70,
0x2f, 0x74, 0x69, 0x6e, 0x79, 0x64, 0x77, 0x61, 0x72, 0x66,
0x00, };
/* An internals_t , data used elsewhere but
not directly visible elsewhere. One needs to have one
of these but maybe the content here too little
or useless, this is just an example of sorts. */
#define SECCOUNT 4
struct sectiondata_s {
unsigned int sd_addr;
unsigned int sd_objoffsetlen;
unsigned int sd_objpointersize;
Dwarf_Unsigned sd_sectionsize;
const char * sd_secname;
Dwarf_Small * sd_content;
};
/* The secname must not be 0 , pass "" if
there is no name. */
static struct sectiondata_s sectiondata[SECCOUNT] = {
{0,0,0,0,"",0},
{0,32,32,sizeof(abbrevbytes),".debug_abbrev",abbrevbytes},
{0,32,32,sizeof(infobytes),".debug_info",infobytes},
{0,32,32,sizeof(strbytes),".debug_str",strbytes}
};
typedef struct special_filedata_s {
int f_is_64bit;
Dwarf_Small f_object_endian;
unsigned f_pointersize;
unsigned f_offsetsize;
Dwarf_Unsigned f_filesize;
Dwarf_Unsigned f_sectioncount;
struct sectiondata_s * f_sectarray;
} special_filedata_internals_t;
/* Use DW_END_little.
Libdwarf finally sets the file-format-specific
f_object_endianness field to a DW_END_little or
DW_END_big (see dwarf.h).
Here we must do that ourselves. */
static special_filedata_internals_t base_internals =
{ FALSE,DW_END_little,32,32,200,SECCOUNT, sectiondata };
static
int gsinfo(void* obj,
Dwarf_Half section_index,
Dwarf_Obj_Access_Section_a* return_section,
int* error )
{
special_filedata_internals_t *internals =
(special_filedata_internals_t *)(obj);
struct sectiondata_s *finfo = 0;
*error = 0; /* No error. Avoids unused arg */
if (section_index >= SECCOUNT) {
return DW_DLV_NO_ENTRY;
}
finfo = internals->f_sectarray + section_index;
return_section->as_name = finfo->sd_secname;
return_section->as_type = 0;
return_section->as_flags = 0;
return_section->as_addr = finfo->sd_addr;
return_section->as_offset = 0;
return_section->as_size = finfo->sd_sectionsize;
return_section->as_link = 0;
return_section->as_info = 0;
return_section->as_addralign = 0;
return_section->as_entrysize = 1;
return DW_DLV_OK;
}
gborder(void * obj)
{
special_filedata_internals_t *internals =
(special_filedata_internals_t *)(obj);
return internals->f_object_endian;
}
static
Dwarf_Small glensize(void * obj)
{
/* offset size */
special_filedata_internals_t *internals =
(special_filedata_internals_t *)(obj);
return internals->f_offsetsize/8;
}
static
Dwarf_Small gptrsize(void * obj)
{
special_filedata_internals_t *internals =
(special_filedata_internals_t *)(obj);
return internals->f_pointersize/8;
}
static
Dwarf_Unsigned gfilesize(void * obj)
{
special_filedata_internals_t *internals =
(special_filedata_internals_t *)(obj);
return internals->f_filesize;
}
static
Dwarf_Unsigned gseccount(void* obj)
{
special_filedata_internals_t *internals =
(special_filedata_internals_t *)(obj);
return internals->f_sectioncount;
}
static
int gloadsec(void * obj,
Dwarf_Half secindex,
Dwarf_Small**rdata,
int *error)
{
special_filedata_internals_t *internals =
(special_filedata_internals_t *)(obj);
struct sectiondata_s *secp = 0;
*error = 0; /* No Error, avoids compiler warning */
if (secindex >= internals->f_sectioncount) {
return DW_DLV_NO_ENTRY;
}
secp = secindex +internals->f_sectarray;
*rdata = secp->sd_content;
return DW_DLV_OK;
}
const Dwarf_Obj_Access_Methods_a methods = {
gsinfo,
gborder,
glensize,
gptrsize,
gfilesize,
gseccount,
gloadsec,
0 /* no relocating anything */
};
{ &base_internals,&methods };
static const Dwarf_Sig8 zerosignature;
static int
isformstring(Dwarf_Half form)
{
/* Not handling every form string, just the
ones used in simple cases. */
switch(form) {
case DW_FORM_string: return TRUE;
case DW_FORM_GNU_strp_alt: return TRUE;
case DW_FORM_GNU_str_index: return TRUE;
case DW_FORM_strx: return TRUE;
case DW_FORM_strx1: return TRUE;
case DW_FORM_strx2: return TRUE;
case DW_FORM_strx3: return TRUE;
case DW_FORM_strx4: return TRUE;
case DW_FORM_strp: return TRUE;
default: break;
};
return FALSE;
}
static int
print_attr(Dwarf_Attribute atr,
Dwarf_Signed anumber, Dwarf_Error *error)
{
int res = 0;
char *str = 0;
const char *attrname = 0;
const char *formname = 0;
Dwarf_Half form = 0;
Dwarf_Half attrnum = 0;
res = dwarf_whatform(atr,&form,error);
if (res != DW_DLV_OK) {
printf("dwarf_whatform failed! res %d\n",res);
return res;
}
res = dwarf_whatattr(atr,&attrnum,error);
if (res != DW_DLV_OK) {
printf("dwarf_whatattr failed! res %d\n",res);
return res;
}
res = dwarf_get_AT_name(attrnum,&attrname);
if (res == DW_DLV_NO_ENTRY) {
printf("Bogus attrnum 0x%x\n",attrnum);
attrname = "<internal error ?>";
}
res = dwarf_get_FORM_name(form,&formname);
if (res == DW_DLV_NO_ENTRY) {
printf("Bogus form 0x%x\n",attrnum);
attrname = "<internal error ?>";
}
if (!isformstring(form)) {
printf(" [%2d] Attr: %-15s Form: %-15s\n",
(int)anumber,attrname,formname);
return DW_DLV_OK;
}
res = dwarf_formstring(atr,&str,error);
if (res != DW_DLV_OK) {
printf("dwarf_formstring failed! res %d\n",res);
return res;
}
printf(" [%2d] Attr: %-15s Form: %-15s %s\n",
(int)anumber,attrname,formname,str);
return DW_DLV_OK;
}
static int
print_one_die(Dwarf_Die in_die,int level,
Dwarf_Error *error)
{
Dwarf_Attribute *attrbuf = 0;
Dwarf_Signed attrcount = 0;
Dwarf_Half tag = 0;
const char * tagname = 0;
int res = 0;
Dwarf_Signed i = 0;
res = dwarf_tag(in_die,&tag,error);
if (res != DW_DLV_OK) {
printf("dwarf_tag failed! res %d\n",res);
return res;
}
res = dwarf_get_TAG_name(tag,&tagname);
if (res != DW_DLV_OK) {
tagname = "<bogus tag>";
}
printf("%3d: Die: %s\n",level,tagname);
res = dwarf_attrlist(in_die,&attrbuf,&attrcount,error);
if (res != DW_DLV_OK) {
printf("dwarf_attrlist failed! res %d\n",res);
return res;
}
for (i = 0; i <attrcount;++i) {
res =print_attr(attrbuf[i],i,error);
if (res != DW_DLV_OK) {
printf("dwarf_attr print failed! res %d\n",res);
return res;
}
}
return DW_DLV_OK;
}
static int
print_object_info(Dwarf_Debug dbg,Dwarf_Error *error)
{
Dwarf_Bool is_info = TRUE; /* our data is not DWARF4
.debug_types. */
Dwarf_Unsigned cu_header_length = 0;
Dwarf_Half version_stamp = 0;
Dwarf_Off abbrev_offset = 0;
Dwarf_Half address_size = 0;
Dwarf_Half length_size = 0;
Dwarf_Half extension_size = 0;
Dwarf_Sig8 type_signature;
Dwarf_Unsigned typeoffset = 0;
Dwarf_Unsigned next_cu_header_offset = 0;
Dwarf_Half header_cu_type = 0;
int res = 0;
Dwarf_Die cu_die = 0;
int level = 0;
type_signature = zerosignature;
is_info,
&cu_header_length,
&version_stamp,
&abbrev_offset,
&address_size,
&length_size,
&extension_size,
&type_signature,
&typeoffset,
&next_cu_header_offset,
&header_cu_type,
error);
if (res != DW_DLV_OK) {
printf("Next cu header result %d. "
"Something is wrong FAIL, line %d\n",res,__LINE__);
if (res == DW_DLV_ERROR) {
printf("Error is: %s\n",dwarf_errmsg(*error));
}
exit(1);
}
printf("CU header length..........0x%lx\n",
(unsigned long)cu_header_length);
printf("Version stamp.............%d\n",version_stamp);
printf("Address size .............%d\n",address_size);
printf("Offset size...............%d\n",length_size);
printf("Next cu header offset.....0x%lx\n",
(unsigned long)next_cu_header_offset);
res = dwarf_siblingof_b(dbg, NULL,is_info, &cu_die, error);
if (res != DW_DLV_OK) {
/* There is no CU die, which should be impossible. */
if (res == DW_DLV_ERROR) {
printf("ERROR: dwarf_siblingof_b failed, no CU die\n");
printf("Error is: %s\n",dwarf_errmsg(*error));
return res;
} else {
printf("ERROR: dwarf_siblingof_b got NO_ENTRY, "
"no CU die\n");
return res;
}
}
res = print_one_die(cu_die,level,error);
if (res != DW_DLV_OK) {
printf("print_one_die failed! %d\n",res);
if (res == DW_DLV_ERROR) {
printf("Error is: %s\n",dwarf_errmsg(*error));
}
exit(1);
}
return DW_DLV_OK;
}
/* testing interfaces useful for embedding
libdwarf inside another program or library. */
int main(void)
{
int res = 0;
Dwarf_Debug dbg = 0;
Dwarf_Error error = 0;
int fail = FALSE;
/* Fill in iface before this call.
We are using a static area, see above. */
res = dwarf_object_init_b(&interface,
0,0,DW_GROUPNUMBER_ANY,&dbg,
&error);
if (res != DW_DLV_OK) {
if (res == DW_DLV_NO_ENTRY) {
printf("FAIL Cannot dwarf_object_init_b() NO ENTRY. \n");
} else {
printf("FAIL Cannot dwarf_object_init_b(). \n");
printf("msg: %s\n",dwarf_errmsg(error));
}
exit(1);
}
res = print_object_info(dbg,&error);
if (res != DW_DLV_OK) {
printf("FAIL printing, res %d line %d\n",res,__LINE__);
exit(1);
}
if (fail) {
printf("FAIL objectaccess.c\n");
exit(1);
}
return 0;
}
Dwarf_Small
unsigned char Dwarf_Small
Definition: libdwarf.h:217
Dwarf_Bool
int Dwarf_Bool
Definition: libdwarf.h:215
Dwarf_Half
unsigned short Dwarf_Half
Definition: libdwarf.h:216
dwarf_errmsg
char * dwarf_errmsg(Dwarf_Error dw_error)
What message string is in the error?
Dwarf_Obj_Access_Methods_a_s
Definition: libdwarf.h:698
Dwarf_Obj_Access_Interface_a_s
Definition: libdwarf.h:717
Dwarf_Debug
struct Dwarf_Debug_s * Dwarf_Debug
Definition: libdwarf.h:537
dwarf_get_AT_name
int dwarf_get_AT_name(unsigned int dw_val_in, const char **dw_s_out)
dwarf_get_AT_name
dwarf_object_init_b
int dwarf_object_init_b(Dwarf_Obj_Access_Interface_a *dw_obj, Dwarf_Handler dw_errhand, Dwarf_Ptr dw_errarg, unsigned int dw_groupnumber, Dwarf_Debug *dw_dbg, Dwarf_Error *dw_error)
Used to access DWARF information in memory or in an object format unknown to libdwarf.
dwarf_attrlist
int dwarf_attrlist(Dwarf_Die dw_die, Dwarf_Attribute **dw_attrbuf, Dwarf_Signed *dw_attrcount, Dwarf_Error *dw_error)
Gets the full list of attributes.
dwarf_get_TAG_name
int dwarf_get_TAG_name(unsigned int dw_val_in, const char **dw_s_out)
dwarf_get_TAG_name
libdwarf.h
Dwarf_Attribute
struct Dwarf_Attribute_s * Dwarf_Attribute
Definition: libdwarf.h:571
Dwarf_Off
unsigned long long Dwarf_Off
Definition: libdwarf.h:211
dwarf_siblingof_b
int dwarf_siblingof_b(Dwarf_Debug dw_dbg, Dwarf_Die dw_die, Dwarf_Bool dw_is_info, Dwarf_Die *dw_return_siblingdie, Dwarf_Error *dw_error)
Retrieve the first DIE or the next sibling.
dwarf_whatform
int dwarf_whatform(Dwarf_Attribute dw_attr, Dwarf_Half *dw_returned_final_form, Dwarf_Error *dw_error)
Returns the form of the Dwarf_Attribute.
dwarf_get_FORM_name
int dwarf_get_FORM_name(unsigned int dw_val_in, const char **dw_s_out)
dwarf_get_FORM_name
Dwarf_Sig8_s
Definition: libdwarf.h:316
Dwarf_Obj_Access_Section_a_s
Definition: libdwarf.h:680
Dwarf_Unsigned
unsigned long long Dwarf_Unsigned
Definition: libdwarf.h:209
dwarf_next_cu_header_d
int dwarf_next_cu_header_d(Dwarf_Debug dw_dbg, Dwarf_Bool dw_is_info, Dwarf_Unsigned *dw_cu_header_length, Dwarf_Half *dw_version_stamp, Dwarf_Off *dw_abbrev_offset, Dwarf_Half *dw_address_size, Dwarf_Half *dw_length_size, Dwarf_Half *dw_extension_size, Dwarf_Sig8 *dw_type_signature, Dwarf_Unsigned *dw_typeoffset, Dwarf_Unsigned *dw_next_cu_header_offset, Dwarf_Half *dw_header_cu_type, Dwarf_Error *dw_error)
Returns information on the next CU header.
Dwarf_Signed
signed long long Dwarf_Signed
Definition: libdwarf.h:210
dwarf.h
Dwarf_Die
struct Dwarf_Die_s * Dwarf_Die
Definition: libdwarf.h:542
dwarf_whatattr
int dwarf_whatattr(Dwarf_Attribute dw_attr, Dwarf_Half *dw_returned_attrnum, Dwarf_Error *dw_error)
Returns the attribute number of the Dwarf_Attribute.
dwarf_formstring
int dwarf_formstring(Dwarf_Attribute dw_attr, char **dw_returned_string, Dwarf_Error *dw_error)
Returns a pointer to a string.
dwarf_object_finish
int dwarf_object_finish(Dwarf_Debug dw_dbg)
Used to close the object_init dw_dbg.
dwarf_tag
int dwarf_tag(Dwarf_Die dw_die, Dwarf_Half *dw_return_tag, Dwarf_Error *dw_error)
Get TAG value of DIE.
Dwarf_Error
struct Dwarf_Error_s * Dwarf_Error
Definition: libdwarf.h:531