📄 dwarf2.c
字号:
result |= -( 1 << shift );
}
* bytes_read_ptr = num_read;
return result;
}
static char * dwarf_form_name ( register unsigned form )
{
switch ( form )
{
case DW_FORM_addr:
return "DW_FORM_addr";
case DW_FORM_block2:
return "DW_FORM_block2";
case DW_FORM_block4:
return "DW_FORM_block4";
case DW_FORM_data2:
return "DW_FORM_data2";
case DW_FORM_data4:
return "DW_FORM_data4";
case DW_FORM_data8:
return "DW_FORM_data8";
case DW_FORM_string:
return "DW_FORM_string";
case DW_FORM_block:
return "DW_FORM_block";
case DW_FORM_block1:
return "DW_FORM_block1";
case DW_FORM_data1:
return "DW_FORM_data1";
case DW_FORM_flag:
return "DW_FORM_flag";
case DW_FORM_sdata:
return "DW_FORM_sdata";
case DW_FORM_strp:
return "DW_FORM_strp";
case DW_FORM_udata:
return "DW_FORM_udata";
case DW_FORM_ref_addr:
return "DW_FORM_ref_addr";
case DW_FORM_ref1:
return "DW_FORM_ref1";
case DW_FORM_ref2:
return "DW_FORM_ref2";
case DW_FORM_ref4:
return "DW_FORM_ref4";
case DW_FORM_ref8:
return "DW_FORM_ref8";
case DW_FORM_ref_udata:
return "DW_FORM_ref_udata";
case DW_FORM_indirect:
return "DW_FORM_indirect";
default:
return "DW_FORM_<unknown>";
}
}
static unsigned int dwarf2_get_ref_die_offset ( struct attribute * attr )
{
unsigned int result = 0;
switch ( attr->form )
{
case DW_FORM_ref_addr:
result = DW_ADDR ( attr );
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
result = cu_header_offset + DW_UNSND ( attr );
break;
default:
/*complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form));*/
break;
}
return result;
}
static struct die_info * follow_die_ref ( unsigned int offset )
{
struct die_info * die;
int h;
h = ( offset % REF_HASH_SIZE );
die = die_ref_table[h];
while ( die )
{
if ( die->offset == offset )
{
return die;
}
die = die->next_ref;
}
die = first_comp_ref_table[h];
while ( die )
{
if ( die->offset == offset )
{
return die;
}
die = die->next_ref;
}
return NULL;
}
/* Return the named attribute or NULL if not there. */
static struct attribute * dwarf_attr ( struct die_info * die, unsigned int name )
{
unsigned int i;
struct attribute * spec = NULL;
for ( i = 0; i < die->num_attrs; ++ i )
{
if (( unsigned int )die->attrs[i].name == name )
{
return & die->attrs[i];
}
if ( die->attrs[i].name == DW_AT_specification
|| die->attrs[i].name == DW_AT_abstract_origin )
spec = & die->attrs[i];
}
if ( spec )
{
struct die_info * ref_die =
follow_die_ref ( dwarf2_get_ref_die_offset ( spec ));
if ( ref_die )
return dwarf_attr ( ref_die, name );
}
return NULL;
}
static int die_is_declaration ( struct die_info * die )
{
return ( dwarf_attr ( die, DW_AT_declaration )
&& ! dwarf_attr ( die, DW_AT_specification ));
}
/* Empty the abbrev table for a new compilation unit. */
/* ARGSUSED */
static void dwarf2_empty_abbrev_table ( void * ignore )
{
int i;
struct abbrev_info * abbrev, * next;
for ( i = 0; i < ABBREV_HASH_SIZE; ++ i )
{
next = NULL;
abbrev = dwarf2_abbrevs[i];
while ( abbrev )
{
next = abbrev->next;
free ( abbrev->attrs );
free ( abbrev );
abbrev = next;
}
dwarf2_abbrevs[i] = NULL;
}
}
static struct abbrev_info *
dwarf_alloc_abbrev ( void )
{
struct abbrev_info * abbrev;
abbrev = ( struct abbrev_info *) malloc_in_die_mem ( sizeof ( struct abbrev_info ));
memset ( abbrev, 0, sizeof ( struct abbrev_info ));
return ( abbrev );
}
/* Lookup an abbrev_info structure in the abbrev hash table. */
static struct abbrev_info * dwarf2_lookup_abbrev ( unsigned int number )
{
unsigned int hash_number;
struct abbrev_info * abbrev;
hash_number = number % ABBREV_HASH_SIZE;
abbrev = dwarf2_abbrevs[hash_number];
while ( abbrev )
{
if ( abbrev->number == number )
return abbrev;
else
abbrev = abbrev->next;
}
return NULL;
}
/* In DWARF version 2, the description of the debugging information is
stored in a separate .debug_abbrev section. Before we read any
dies from a section we read in all abbreviations and install them
in a hash table. */
static void dwarf2_read_abbrevs ( unsigned int offset )
{
char * abbrev_ptr;
struct abbrev_info * cur_abbrev;
unsigned int abbrev_number, bytes_read, abbrev_name;
unsigned int abbrev_form, hash_number;
char * old_abbrev_ptr;
/* empty the table */
dwarf2_empty_abbrev_table ( NULL );
abbrev_ptr = dwarf_abbrev_buffer + offset;
abbrev_number = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
/* loop until we reach an abbrev number of 0 */
while ( abbrev_number )
{
cur_abbrev = dwarf_alloc_abbrev ();
/* read in abbrev header */
cur_abbrev->number = abbrev_number;
cur_abbrev->tag = ( enum dwarf_tag )read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
cur_abbrev->has_children = ( unsigned short )read_1_byte ( abbrev_ptr );
abbrev_ptr += 1;
old_abbrev_ptr = abbrev_ptr; /* 保存开始时地址 */
/* now read in declarations */
abbrev_name = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
while ( abbrev_name )
{
cur_abbrev->num_attrs ++; /* 计数, 有多少个属性 */
abbrev_name = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
}
if( cur_abbrev->num_attrs )
{
int num = 0;
abbrev_ptr = old_abbrev_ptr ; /* 恢复开始时地址 */
cur_abbrev->attrs = ( struct attr_abbrev *)malloc_in_die_mem(( cur_abbrev->num_attrs )
* sizeof ( struct attr_abbrev ));
/* now read in declarations */
abbrev_name = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
while ( abbrev_name )
{
cur_abbrev->attrs[num].name = ( enum dwarf_attribute )abbrev_name;
cur_abbrev->attrs[num ++ ].form = ( enum dwarf_form )abbrev_form;
abbrev_name = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
}
}
hash_number = abbrev_number % ABBREV_HASH_SIZE;
cur_abbrev->next = dwarf2_abbrevs[hash_number];
dwarf2_abbrevs[hash_number] = cur_abbrev;
/* Get next abbreviation.
Under Irix6 the abbreviations for a compilation unit are not
always properly terminated with an abbrev number of 0.
Exit loop if we encounter an abbreviation which we have
already read (which means we are about to read the abbreviations
for the next compile unit) or if the end of the abbreviation
table is reached. */
if (( unsigned int ) ( abbrev_ptr - dwarf_abbrev_buffer ) >= dwarf_abbrev_size )
break;
abbrev_number = read_unsigned_leb128 ( abbrev_ptr, & bytes_read );
abbrev_ptr += bytes_read;
if ( dwarf2_lookup_abbrev ( abbrev_number ) != NULL )
break;
}
}
static void dwarf2_empty_hash_tables ( void )
{
memset ( die_ref_table, 0, sizeof ( die_ref_table ));
}
static void store_in_ref_table ( unsigned int offset, struct die_info * die )
{
int h;
struct die_info * old;
h = ( offset % REF_HASH_SIZE );
old = die_ref_table[h];
die->next_ref = old;
die_ref_table[h] = die;
}
unsigned int die_already_malloced = 0; /* 实际分配的内存 */
void * malloc_in_die_mem( unsigned int size )
{
void * ptr;
ptr = malloc( size );
if( ptr )
{
die_already_malloced += size;
return ptr;
}
if( ! ptr )
printf( "no memory malloc\r\n" );
return ptr;
}
/* 预先扫描DIE,决定每个DIE在整个内存空间的位置以及需要分配数据的大小 */
#define DIE_STEP_MALLOC 10
static int * die_index = NULL;
static int total_die_per_unit = 0;
static int index = 0;
static char * end_ptr = NULL;
void init_scan( void )
{
die_index = 0;
total_die_per_unit = 0;
index = 0;
}
void uninit_scan( void )
{
if( die_index )
free( die_index );
}
static char * scan_full_die( int * nest_level, struct die_info ** diep, char * info_ptr,
const struct comp_unit_head * cu_header )
{
unsigned int abbrev_number, bytes_read, i, offset;
struct abbrev_info * abbrev;
struct die_info * die;
int mod_die = 0;
int retry_die = 0;
mod_die = total_die_per_unit & ( ( 1 << DIE_STEP_MALLOC ) - 1 ); /* 取余数 */
if( mod_die == 0 ) /* 是否需要分配内存 */
{
if( die_index )
{
/* 重新分配内存 */
retry_die = ( total_die_per_unit >> 10 ) ;/* 需要分配多少个DIE_STEP_MALLOC空间 */
die_index = ( int *)realloc( die_index, (( retry_die + 1 ) * sizeof( int )) * ( 1 << DIE_STEP_MALLOC ));
}
else
die_index = ( int *)malloc( sizeof( int ) * ( 1 << DIE_STEP_MALLOC ));
}
offset = info_ptr - dwarf_info_buffer;
abbrev_number = read_unsigned_leb128 ( info_ptr, & bytes_read );
info_ptr += bytes_read;
if (! abbrev_number )
{
* nest_level -= 1;
if( info_ptr < end_ptr && !* nest_level )
{
* nest_level += 1;
* diep = NULL;
return info_ptr;
}
die = ( struct die_info *) malloc_in_die_mem ( sizeof ( struct die_info ));
die_index[total_die_per_unit] = index;
index += sizeof ( struct die_info );
memset ( die, 0, sizeof ( struct die_info ));
die->tag = ( enum dwarf_tag )0;
die->abbrev = abbrev_number;
die->offset = offset;
die->ptype = NULL;
* diep = die;
total_die_per_unit ++;
return info_ptr;
}
abbrev = dwarf2_lookup_abbrev ( abbrev_number );
if (! abbrev )
{
printf ( "Dwarf Error: could not find abbrev number %d. offset = %d\r\n", abbrev_number, offset );
return info_ptr;
}
die = ( struct die_info *) malloc_in_die_mem ( sizeof ( struct die_info ) +
sizeof( struct attribute ) * abbrev->num_attrs );
memset ( die, 0, sizeof ( struct die_info ));
die->offset = offset;
die->tag = abbrev->tag;
die->has_children = abbrev->has_children;
if( die->has_children )
* nest_level += 1;
die->abbrev = abbrev_number;
die->ptype = NULL;
die->num_attrs = abbrev->num_attrs;
die->attrs = ( struct attribute * )( die + 1 );
for ( i = 0; i < abbrev->num_attrs; ++ i )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -