唉,当初怎么就选择用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_pc
get_addr(t_attr, &lowpc);
res = dwarf_attr(die, DW_AT_high_pc, &t_attr, &error);
if (res == DW_DLV_OK) // 获取DW_AT_high_pc
get_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);
else
printf("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);
} else
printf("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);
} else
printf("error in get base type size \n");
} else
printf("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);
else
printf("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的,,,