📄 dwarf2.c
字号:
/**************************************************************
** Copyright (C) 2002-2007 基础技术开发部
** All right reserved
***************************************************************
**
** 项目名称:DWARF解析
** 功能简介:根据DWARF2规范定义解析 debug_info 与 debug_abbrev 数据结构
**
** 原始作者:段太钢 Email:duantaigang@xjgc.com
** 组织部门:许继集团 许继电气技术中心嵌入式软件开发部
** 备 注:
** 建立时间:2007-3-22 17:11
** 完成时间:2007-3-22 17:11
** 版 本:1.0
***************************************************************
** 单元标识:$Id: dwarf2.c,v 1.7 2007/11/15 00:14:51 dtg Exp $
** 版本历史:
** 修 改 者:
** 最近修改:
**************************************************************/
#include "dwarf2.h"
#include "term.h"
#include "channel.h"
#include "sys_layer.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* Blocks are a bunch of untyped bytes. */
struct dwarf_block
{
unsigned int size;
char * data;
};
/* Attributes have a name and a value. */
struct attribute
{
enum dwarf_attribute name;
enum dwarf_form form;
union
{
char * str;
struct dwarf_block blk;
unsigned int unsnd;
int snd;
unsigned int addr;
}
u;
};
/* Get at parts of an attribute structure. */
#define DW_STRING(attr) ((attr)->u.str)
#define DW_UNSND(attr) ((attr)->u.unsnd)
#define DW_BLOCK(attr) ((attr)->u.blk)
#define DW_SND(attr) ((attr)->u.snd)
#define DW_ADDR(attr) ((attr)->u.addr)
/* This data structure holds the information of an abbrev. */
struct abbrev_info
{
unsigned int number; /* Number identifying abbrev. */
int has_children; /* Boolean. */
unsigned int num_attrs; /* Number of attributes. */
struct attr_abbrev * attrs; /* An array of attribute descriptions. */
struct abbrev_info * next; /* Next in chain. */
enum dwarf_tag tag; /* DWARF tag. */
};
struct attr_abbrev
{
enum dwarf_attribute name;
enum dwarf_form form;
};
struct funcinfo
{
struct funcinfo * prev_func;
char * name;
unsigned int low;
unsigned int high;
};
/* A minimal decoding of DWARF2 compilation units. We only decode
what's needed to get to the line number information. */
struct comp_unit
{
/* Chain the previously read compilation units. */
struct comp_unit * next_unit;
/* Keep the bdf convenient (for memory allocation). not used */
/* bfd* abfd; */
/* The lowest and higest addresses contained in this compilation
unit as specified in the compilation unit header. */
// struct arange arange;
/* The DW_AT_name attribute (for error messages). */
char * name;
/* The abbrev hash table. */
struct abbrev_info ** abbrevs;
/* Note that an error was found by comp_unit_find_nearest_line. */
int error;
/* The DW_AT_comp_dir attribute. */
char * comp_dir;
/* True if there is a line number table associated with this comp. unit. */
int stmtlist;
/* The offset into .debug_line of the line number table. not used */
/* unsigned int line_offset; */
/* Pointer to the first child die for the comp unit. */
char * first_child_die_ptr;
/* The end of the comp unit. */
char * end_ptr;
/* The decoded line number, NULL if not yet decoded. not used */
/* struct line_info_table* line_table; */
/* A list of the functions found in this comp. unit. */
struct funcinfo * function_table;
/* Pointer to dwarf2_debug structure. */
struct dwarf2_debug * stash;
/* Address size for this unit - from unit header. */
unsigned char addr_size;
/* Offset size for this unit - from unit header. */
unsigned char offset_size;
};
#ifndef ABBREV_HASH_SIZE
#define ABBREV_HASH_SIZE 121 /* HASH表大小 */
#endif
#ifndef ATTR_ALLOC_CHUNK
#define ATTR_ALLOC_CHUNK 4 /* 4组成一块 */
#endif
/* The data in a compilation unit header, after target2host
translation, looks like this. */
struct comp_unit_head
{
unsigned int length;
short version;
unsigned int abbrev_offset;
unsigned char addr_size;
unsigned char signed_addr_p;
unsigned int offset_size; /* size of file offsets; either 4 or 8 */
unsigned int initial_length_size; /* size of the length field; either
4 or 12 */
};
/* This data structure holds a complete die structure. */
struct die_info
{
unsigned int abbrev; /* Abbrev number */
unsigned int offset; /* Offset in .debug_info section */
unsigned int num_attrs; /* Number of attributes */
struct attribute * attrs; /* An array of attributes */
struct die_info * next_ref; /* Next die in ref hash table */
struct die_info * next; /* Next die in linked list */
struct type * ptype; /* Cached type information */
unsigned short has_children; /* Does the die have children */
enum dwarf_tag tag; /* Tag indicating type of die */
};
static unsigned int cu_header_offset;
static char * dwarf_info_buffer;
static char * dwarf_abbrev_buffer;
static unsigned int dwarf_info_size;
static unsigned int dwarf_abbrev_size;
static char * dwarf_str_buffer;
static unsigned int dwarf_str_size;
#define DW_FIELD_ALLOC_CHUNK 4 /* DW分配块大小 */
static struct abbrev_info * dwarf2_abbrevs[ABBREV_HASH_SIZE];
/* A hash table of die offsets for following references. */
#ifndef REF_HASH_SIZE
#define REF_HASH_SIZE 1021 /* hash表大小 */
#endif
static struct die_info * die_ref_table[REF_HASH_SIZE];
static struct die_info * first_comp_ref_table[REF_HASH_SIZE]; /* 保存第一个comp unit hash 表 */
void * malloc_in_die_mem( unsigned int size );
void print_sym_name_value( struct type * ptype, char * name, CORE_ADDR * address , int nestlevl );
struct type * create_array_type ( struct type * result_type, struct type * element_type,
struct type * range_type );
static void read_base_type ( struct die_info * die );
static void smash_type ( struct type * ptype );
static struct type * die_containing_type ( struct die_info * die, const struct comp_unit_head * cu_header );
static void read_tag_pointer_type ( struct die_info * die, const struct comp_unit_head * cu_header );
static void read_enumeration ( struct die_info * die, const struct comp_unit_head * cu_header );
struct type * init_type ( enum type_code code, int length, int flags, char * name );
struct type * check_typedef ( struct type * type );
void add_symbol_to_list ( struct symbol * psymbol, struct pending ** listhead );
struct type * alloc_type ( void );
static void read_subroutine_type ( struct die_info * die,
const struct comp_unit_head * cu_header );
static struct type * die_type ( struct die_info * die, const struct comp_unit_head * cu_header );
struct type * c_create_fundamental_type ( int typeid );
static void dwarf2_add_field ( struct field_info * fip, struct die_info * die,
const struct comp_unit_head * cu_header );
static char * read_attribute_value ( struct attribute * attr, unsigned form,
char * info_ptr, const struct comp_unit_head * cu_header );
static char * read_attribute ( struct attribute * attr, struct attr_abbrev * abbrev, char * info_ptr,
const struct comp_unit_head * cu_header );
static struct die_info * sibling_die ( struct die_info * die );
static void dwarf2_attach_fields_to_type ( struct field_info * fip, struct type * ptype );
static void dwarf2_attach_fn_fields_to_type ( struct field_info * fip, struct type * ptype );
static struct symbol * new_symbol ( struct die_info * die, struct type * ptype,
const struct comp_unit_head * cu_header );
static void process_die ( struct die_info * die, const struct comp_unit_head * cu_header );
/* Read dwarf information from a buffer. */
static unsigned int read_1_byte( char * buf )
{
return *( unsigned char *)buf;
}
static int read_1_signed_byte( char * buf )
{
return (((*( unsigned char *) ( buf ) & 0xff ) ^ 0x80 ) - 0x80 ); /* 读取无符号数 */
}
static unsigned int read_2_bytes ( char * buf )
{
unsigned int s;
unsigned char * ptr = ( unsigned char *)buf;
s = ( unsigned short )( ptr[0] | ptr[1] << 8 );/* 读取无符号数 */
return s;
}
static int read_2_signed_bytes ( char * buf )
{
unsigned short s;
s = ( unsigned short )( buf[0] | buf[1] << 8 );/* 读取有符号数 */
s = s ^ 0x80000 - 0x8000;/* 读取有符号数 */
return ( int )s;
}
static unsigned int read_4_bytes ( char * buf )
{
unsigned int i;
unsigned char * ptr = ( unsigned char *)buf;
i = ( unsigned int )( ptr[0] | ( ptr[1] << 8 ) | ( ptr[2] << 16 ) | ( ptr[3] << 24 ));/* 读取有符号数 */
return i;
}
static int read_4_signed_bytes ( char * buf )
{
unsigned int i;
unsigned char * ptr = ( unsigned char *)buf;
i = ( unsigned int )( ptr[0] | ( ptr[1] << 8 ) | ( ptr[2] << 16 ) | ( ptr[3] << 24 ));/* 读取有符号数 */
return ( i ^ 0x80000000 - 0x80000000 );/* 读取有符号数 */
}
static unsigned int read_address ( char * buf, const struct comp_unit_head * cu_header, int * bytes_read )
{
unsigned int retval = 0;
switch ( cu_header->addr_size )
{
case 2:/* 2 */
retval = read_2_bytes ( buf );
break;
case 4:/* 4 */
retval = read_4_bytes ( buf );
break;
case 8:/* 8 */
default:
printf ( __FILE__, __LINE__,
"read_address: bad switch, unsigned" );
}
* bytes_read = cu_header->addr_size;
return retval;
}
static int read_initial_length ( char * buf, struct comp_unit_head * cu_header, int * bytes_read )
{
int retval = 0;
retval = read_4_bytes ( buf );
* bytes_read = 4; /* 更改当前读出数目 */
if ( cu_header != NULL )
{
cu_header->initial_length_size = 4; /* 长度 */
cu_header->offset_size = 4; /* 偏移量 */
}
return retval;
}
static int read_offset ( char * buf, const struct comp_unit_head * cu_header, int * bytes_read )
{
int retval = 0;
switch ( cu_header->offset_size )
{
case 4: /* 4 */
retval = read_4_bytes ( buf );
* bytes_read = 4; /* 更改读出数目 */
break;
default:
printf ( __FILE__, __LINE__,
"read_offset: bad switch" );
}
return retval;
}
static char * read_string ( char * buf, unsigned int * bytes_read_ptr )
{
/* If the size of a host char is 8 bits, we can return a pointer
to the string, otherwise we have to copy the string to a buffer
allocated on the temporary obstack. */
if (* buf == '\0' )
{
* bytes_read_ptr = 1;
return NULL;
}
* bytes_read_ptr = strlen ( buf ) + 1;
return buf;
}
static char * read_n_bytes ( char * buf, unsigned int size )
{
return buf;
}
static char * read_indirect_string ( char * buf, const struct comp_unit_head * cu_header,
unsigned int * bytes_read_ptr )
{
unsigned int str_offset = ( unsigned int )read_offset ( buf, cu_header,
( int *) bytes_read_ptr );
if ( dwarf_str_buffer == NULL )
{
printf ( "DW_FORM_strp used without .debug_str section" );
return NULL;
}
if ( str_offset >= dwarf_str_size )
{
printf ( "DW_FORM_strp pointing outside of .debug_str section" );
return NULL;
}
if ( dwarf_str_buffer[str_offset] == '\0' )
return NULL;
return dwarf_str_buffer + str_offset;
}
static unsigned int read_unsigned_leb128 ( char * buf, unsigned int * bytes_read_ptr )
{
unsigned long result;
unsigned int num_read;
int shift;
unsigned char byte;
result = 0;
shift = 0;
num_read = 0;
while ( 1 )
{
byte = read_1_byte ( buf );
buf ++;
num_read ++;
result |= (( unsigned int )( byte & 127 ) << shift );/* 读取有符号数 */
if (( byte & 128 ) == 0 )/* 读取有符号数 */
{
break;
}
shift += 7; /* 位移量 */
}
* bytes_read_ptr = num_read;
return result;
}
static int read_signed_leb128 ( char * buf, unsigned int * bytes_read_ptr )
{
int result;
int shift, size, num_read;
unsigned char byte;
result = 0;
shift = 0;
size = 32;/* 读取有符号数 */
num_read = 0;
while ( 1 )
{
byte = read_1_byte ( buf );
buf ++;
num_read ++;
result |= (( long )( byte & 127 ) << shift );/* 读取有符号数 */
shift += 7;/* 读取有符号数 */
if (( byte & 128 ) == 0 )/* 读取有符号数 */
{
break;
}
}
if (( shift < size ) && ( byte & 0x40 ))/* 读取有符号数 */
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -