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

唉,当初怎么就选择用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的,,,


  • 0
    点赞
  • 2
    收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 1

打赏作者

warriorpaw

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值