使用libdwraf写的一个读取GCC -g参数编译生成的调试信息的例子

来源:互联网 发布:桥接模式下centos联网 编辑:程序博客网 时间:2024/05/16 03:05

唉,当初怎么就选择用libdwarf做了  艹。做完发现它远没BFD好用。。。


只处理了标准C 在X86下有可能碰到的变量和其作用范围(就是函数和局部块的范围)  其他的   用不到 不关心


好多地方需要dwarf_dealloc的我都偷懒没管,这只是个例子  例子而已........


#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <errno.h>#include <string.h>#include "dwarf.h"#include "libdwarf.h"static const char *const dwarf_regnames_i386[] ={  "eax", "ecx", "edx", "ebx",  "esp", "ebp", "esi", "edi",  "eip", "eflags", NULL,  "st0", "st1", "st2", "st3",  "st4", "st5", "st6", "st7",  NULL, NULL,  "xmm0", "xmm1", "xmm2", "xmm3",  "xmm4", "xmm5", "xmm6", "xmm7",  "mm0", "mm1", "mm2", "mm3",  "mm4", "mm5", "mm6", "mm7",  "fcw", "fsw", "mxcsr",  "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,  "tr", "ldtr"};//从GDB源代码里copy过来的。。。static void get_addr(Dwarf_Attribute attr, Dwarf_Addr *val) {Dwarf_Error error = 0;int res;Dwarf_Addr uval = 0;res = dwarf_formaddr(attr, &uval, &error);if (res == DW_DLV_OK) {*val = uval;return;}return;}static void print_subprog(Dwarf_Debug dbg, Dwarf_Die die, int level) {int res;Dwarf_Error error = 0;Dwarf_Addr lowpc = 0;Dwarf_Addr highpc = 0;Dwarf_Attribute t_attr;res = dwarf_attr(die, DW_AT_inline, &t_attr, &error);if (res == DW_DLV_OK) { // inline 函数  没 范围printf("< %2d >", level);printf("inline sub !\n");return;}res = dwarf_attr(die, DW_AT_low_pc, &t_attr, &error);if (res == DW_DLV_OK) // 获取DW_AT_low_pcget_addr(t_attr, &lowpc);res = dwarf_attr(die, DW_AT_high_pc, &t_attr, &error);if (res == DW_DLV_OK) // 获取DW_AT_high_pcget_addr(t_attr, &highpc);if (lowpc) {printf("< %2d >", level);printf("low_pc : 0x%" DW_PR_DUx "\n", (Dwarf_Unsigned) lowpc);}if (highpc) {printf("< %2d >", level);printf("high_pc: 0x%" DW_PR_DUx "\n", (Dwarf_Unsigned) highpc);}}static void get_location(Dwarf_Debug dbg, Dwarf_Attribute attr, int level) {Dwarf_Error error = 0;int res;Dwarf_Locdesc *llbuf;Dwarf_Signed lcnt;res = dwarf_loclist(attr, &llbuf, &lcnt, &error);if (res == DW_DLV_OK) {printf("< %2d >", level);//只处理了和标准C相关的位置信息if ( DW_OP_addr == llbuf->ld_s->lr_atom)printf("直接地址: %x \n",(int) llbuf->ld_s->lr_number);else if(llbuf->ld_s->lr_atom >= DW_OP_breg0 && llbuf->ld_s->lr_atom <= DW_OP_breg31)printf("寄存器偏移: %s %d \n",*(dwarf_regnames_i386+llbuf->ld_s->lr_atom-DW_OP_breg0),((int)llbuf->ld_s->lr_number));else if(llbuf->ld_s->lr_atom >= DW_OP_reg0 && llbuf->ld_s->lr_atom <= DW_OP_reg31)printf("通用寄存器: reg%d \n",llbuf->ld_s->lr_atom - DW_OP_reg0);else if(llbuf->ld_s->lr_atom == DW_OP_fbreg)printf("寄存器偏移: %s %d \n","ebp",((int)llbuf->ld_s->lr_number)+8);elseprintf("Unknow location \n");//不是C的不管丫的dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);}return;}static Dwarf_Die get_die(Dwarf_Debug dbg, Dwarf_Attribute attr, Dwarf_Half* tag) {//通过偏移量取die和对应的标签Dwarf_Error error = 0;int res;Dwarf_Off offset;Dwarf_Die typeDie = 0;res = dwarf_global_formref(attr, &offset, &error);if (res == DW_DLV_OK) {res = dwarf_offdie(dbg, offset, &typeDie, &error);if (res == DW_DLV_OK) {res = dwarf_tag(typeDie, tag, &error);if (res == DW_DLV_OK) {return typeDie;}}}return NULL ;}static int get_array_length(Dwarf_Debug dbg, Dwarf_Die die, int *length) {//数组类型的长度。。int res;Dwarf_Error error;Dwarf_Die child;Dwarf_Attribute tmp;res = dwarf_child(die, &child, &error);*length = 1;Dwarf_Unsigned utmp;if (res == DW_DLV_OK) {while (1) {res = dwarf_attr(child, DW_AT_upper_bound, &tmp, &error);if (res == DW_DLV_OK) {res = dwarf_formudata(tmp, &utmp, &error);if (res != DW_DLV_OK)return DW_DLV_ERROR;else*length *= (utmp + 1);}res = dwarf_siblingof(dbg, child, &child, &error);if (res == DW_DLV_ERROR)return DW_DLV_ERROR;if (res == DW_DLV_NO_ENTRY)return DW_DLV_OK;}}return DW_DLV_ERROR;}static void get_type(Dwarf_Debug dbg, Dwarf_Attribute attr) {char *name = 0;Dwarf_Half tag;Dwarf_Unsigned size;Dwarf_Error error = 0;Dwarf_Attribute t_attr;int res;Dwarf_Die typeDie = get_die(dbg, attr, &tag);if (typeDie) {switch (tag) {//只处理了和标准C相关的类型case DW_TAG_subroutine_type:printf("subroutine type return ");goto next_type;case DW_TAG_typedef:printf("typedef to ");goto next_type;case DW_TAG_const_type:printf("const ");goto next_type;case DW_TAG_pointer_type:printf("pointer ");goto next_type;case DW_TAG_volatile_type:printf("volatile ");next_type: res = dwarf_attr(typeDie, DW_AT_type, &t_attr, &error);if (res == DW_DLV_OK) {get_type(dbg, t_attr);} elseprintf("void \n");break;case DW_TAG_base_type:res = dwarf_diename(typeDie, &name, &error);if (res == DW_DLV_OK) {printf("%s ", name);res = dwarf_bytesize(typeDie, &size, &error);if (res == DW_DLV_OK) {printf("\n大小: %d \n", (int)size);} elseprintf("error in get base type size \n");} elseprintf("error in get base type name \n");break;case DW_TAG_array_type:printf("array ");int length;res = get_array_length(dbg, typeDie, &length);if (res == DW_DLV_OK)printf("数组长度: %d ", length);goto next_type;case DW_TAG_union_type:printf("union ");goto get_size;case DW_TAG_structure_type:printf("structure ");get_size: res = dwarf_bytesize(typeDie, &size, &error);if (res == DW_DLV_OK)printf("\n大小: %d\n", (int)size);elseprintf("error in get bytesize\n");break;default:printf("Unknow tag \n");break;}}return;}static void print_variable(Dwarf_Debug dbg, Dwarf_Die die, int level) {int res;Dwarf_Error error = 0;Dwarf_Attribute t_attr;res = dwarf_attr(die, DW_AT_declaration, &t_attr, &error);if (res == DW_DLV_OK) { //extern变量,没有位置信息printf("< %2d >", level);printf("extern变量! \n");return;}res = dwarf_attr(die, DW_AT_location, &t_attr, &error);if (res == DW_DLV_OK) //变量位置get_location(dbg, t_attr, level);res = dwarf_attr(die, DW_AT_type, &t_attr, &error);if (res == DW_DLV_OK) { // 类型printf("< %2d >变量类型:", level);get_type(dbg, t_attr);}}static void print_die_data(Dwarf_Debug dbg, Dwarf_Die print_me, int level) {char *name = 0;Dwarf_Error error = 0;Dwarf_Half tag = 0;const char *tagname = 0;int localname = 0;if (level == 0)return;int res = dwarf_diename(print_me, &name, &error);if (res == DW_DLV_ERROR) {printf("Error in dwarf_diename , level %d \n", level);exit(1);}if (res == DW_DLV_NO_ENTRY) {name = "<no name>";localname = 1;}res = dwarf_tag(print_me, &tag, &error);if (res != DW_DLV_OK) {printf("Error in dwarf_tag , level %d \n", level);exit(1);}if (tag == DW_TAG_lexical_block) { //局部块printf("\n< %2d >", level);printf("局部块\n");print_subprog(dbg, print_me, level);}if (tag == DW_TAG_subprogram) { //子程序Dwarf_Attribute attr;printf("\n< %2d >", level);printf("函数名: %s\n", name);print_subprog(dbg, print_me, level);res = dwarf_attr(print_me, DW_AT_frame_base, &attr, &error);}if (tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) { //函数参数和普通变量,其他的像指针函数什么的   没管。。。printf("\n< %2d >", level);printf("变量名: %s\n", name);print_variable(dbg, print_me, level);}res = dwarf_get_TAG_name(tag, &tagname);if (res != DW_DLV_OK) {printf("Error in dwarf_get_TAG_name , level %d \n", level);exit(1);}if (!localname) {dwarf_dealloc(dbg, name, DW_DLA_STRING);}}static void get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level) {//从simplereader.c里面复制的int res = DW_DLV_ERROR;Dwarf_Die cur_die = in_die;Dwarf_Die child = 0;Dwarf_Error error;Dwarf_Half tag;int get_child = 0;print_die_data(dbg, in_die, in_level);for (;;) {Dwarf_Die sib_die = 0;get_child = 0;if (in_level) {res = dwarf_tag(cur_die, &tag, &error);if (res != DW_DLV_OK) {printf("Error in dwarf_tag , level %d \n", in_level);exit(1);}if (tag == DW_TAG_lexical_block || tag == DW_TAG_subprogram)get_child = 1;}if ( !in_level || get_child ) { //只遍历第0层节点和函数&局部块节点的孩子节点,因为别的节点下面没有变量信息res = dwarf_child(cur_die, &child, &error);if (res == DW_DLV_ERROR) {printf("Error in dwarf_child , level %d \n", in_level);exit(1);}if (res == DW_DLV_OK) {get_die_and_siblings(dbg, child, in_level + 1);}}/* res == DW_DLV_NO_ENTRY */res = dwarf_siblingof(dbg, cur_die, &sib_die, &error);if (res == DW_DLV_ERROR) {printf("Error in dwarf_siblingof , level %d \n", in_level);exit(1);}if (res == DW_DLV_NO_ENTRY) {/* Done at this level. */break;}/* res == DW_DLV_OK */if (cur_die != in_die) {dwarf_dealloc(dbg, cur_die, DW_DLA_DIE);}cur_die = sib_die;print_die_data(dbg, cur_die, in_level);}return;}static void read_cu_list(Dwarf_Debug dbg) {//从simplereader.c里面复制的Dwarf_Unsigned cu_header_length = 0;Dwarf_Half version_stamp = 0;Dwarf_Unsigned abbrev_offset = 0;Dwarf_Half address_size = 0;Dwarf_Unsigned next_cu_header = 0;Dwarf_Error error;int cu_number = 0;for (;; ++cu_number) {Dwarf_Die no_die = 0;Dwarf_Die cu_die = 0;int res = DW_DLV_ERROR;res = dwarf_next_cu_header(dbg, &cu_header_length, &version_stamp,&abbrev_offset, &address_size, &next_cu_header, &error);if (res == DW_DLV_ERROR) {printf("Error in dwarf_next_cu_header\n");exit(1);}if (res == DW_DLV_NO_ENTRY) {/* Done. */return;}/* The CU will have a single sibling, a cu_die. */res = dwarf_siblingof(dbg, no_die, &cu_die, &error);if (res == DW_DLV_ERROR) {printf("Error in dwarf_siblingof on CU die \n");exit(1);}if (res == DW_DLV_NO_ENTRY) {/* Impossible case. */printf("no entry! in dwarf_siblingof on CU die \n");exit(1);}get_die_and_siblings(dbg, cu_die, 0/*,&sf*/);dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);}}int main(int argc, char **argv) {//从simplereader.c里面复制的Dwarf_Debug dbg = 0;int fd = -1;const char *filepath = "<stdin>";int res = DW_DLV_ERROR;Dwarf_Error error;Dwarf_Handler errhand = 0;Dwarf_Ptr errarg = 0;if (argc < 2) {fd = 0; /* stdin */} else {filepath = argv[1];//fd = open("/home/paw/work/d/ao0",O_RDONLY);fd = open(filepath, O_RDONLY);}if (fd < 0) {printf("Failure attempting to open \"%s\"\n", filepath);}res = dwarf_init(fd, DW_DLC_READ, errhand, errarg, &dbg, &error);if (res != DW_DLV_OK) {printf("Giving up, cannot do DWARF processing\n");exit(1);}read_cu_list(dbg);res = dwarf_finish(dbg, &error);if (res != DW_DLV_OK) {printf("dwarf_finish failed!\n");}close(fd);return 0;}

下图是用这程序处理加上-g参数编译出来的mentohust的部分输出


这东西有嘛用???

这只是个演示用的例子,没啥用学习libdwraf可以看看

真用到项目里面不是这样直接输出了,而是把信息保存的一定的数据结构里,用于双工冗余时对比变量了


参考:

http://dwarfstd.org/ 

dwraf调试信息的官网

http://reality.sgiweb.org/davea/dwarf.html

libdwraf官网,好山寨的说。。。

http://godorz.info/2011/02/how-debuggers-work-part-3-debugging-information/

我就是上这文章的当去看libdwraf的,,,


原创粉丝点击