⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dwarf2.c

📁 主要用于在线分析dsp目标代码的调试信息。DSP平台下用CCS调试源代码时
💻 C
📖 第 1 页 / 共 5 页
字号:
/**************************************************************
** 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 + -