求addr2line原理

ganjianh8 2011-07-27 02:42:00
addr2line非常强大,因而我想了解一下addr2line原理
希望大家可以贴一下原理或给源码地址也行
...全文
1146 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
threeleafzerg007 2011-08-02
  • 打赏
  • 举报
回复
楼上应该是对的,要想知道具体source line,必须加 -g
把俺的忽略吧
lvyinghong 2011-08-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 threeleafzerg007 的回复:]

addr2line隶属于binutils,是交叉编译工具里比较重要的一个命令:

源代码在:
http://download.chinaunix.net/download/0001000/900.shtml
binutils-2.15.94-20050118-1-src.tar.gz


个人理解,它还是像objdump一样,读出elf文件的文件头里的符号表,
比如 objdu……
[/Quote]

呵呵,楼上的比我先来一步阿。通过这个应该是可以得到 出错的是哪一个函数里面偏移多少位置的,但不能得到源码行数,backtrace那些显示出函数名应该可以根据symbol table就知道了
threeleafzerg007 2011-08-02
  • 打赏
  • 举报
回复
如果 这个地址是来自于.so的话,就需要先知道 /proc/`pidof <youprogram>`/maps里,那个so的.text被加载的起始地址 , 再加上 具体函数在so里.text的相对偏移地址,也就能推导出是.so的具体哪个函数了。
lvyinghong 2011-08-02
  • 打赏
  • 举报
回复
因为你用-g选项生成的可执行文件,最终的elf文件多生成了几个段,
可以使用 readelf --sections a.out 看的出来
00000000 l d .debug_aranges 00000000 .debug_aranges
00000000 l d .debug_pubnames 00000000 .debug_pubnames
00000000 l d .debug_info 00000000 .debug_info
00000000 l d .debug_abbrev 00000000 .debug_abbrev
00000000 l d .debug_line 00000000 .debug_line
00000000 l d .debug_frame 00000000 .debug_frame
00000000 l d .debug_str 00000000 .debug_str
00000000 l d .debug_loc 00000000 .debug_loc
00000000 l d .debug_pubtypes 00000000 .debug_pubtypes


.debug_line 这个段里面就包含了每条汇编指令的地址和对应的源代码行数,源代码名字等信息,
使用readelf -wl a.out 命令就可以查看这个段的内容,比如


readelf -wl a.out
Raw dump of debug contents of section .debug_line:

Offset: 0x0
Length: 277
DWARF Version: 2
Prologue Length: 29
Minimum Instruction Length: 1
Initial value of 'is_stmt': 1
Line Base: -5
Line Range: 14
Opcode Base: 13

Opcodes:
Opcode 1 has 0 args
Opcode 2 has 1 args
Opcode 3 has 1 args
Opcode 4 has 1 args
Opcode 5 has 1 args
Opcode 6 has 0 args
Opcode 7 has 0 args
Opcode 8 has 0 args
Opcode 9 has 1 args
Opcode 10 has 0 args
Opcode 11 has 0 args
Opcode 12 has 1 args

The Directory Table is empty.

The File Name Table:
Entry Dir Time Size Name
1 0 0 0 main.c //////////////这个是文件名

Line Number Statements:
Extended opcode 2: set Address to 0x8048444
Advance Line by 12 to 13
Copy
Special opcode 90: advance Address by 6 to 0x804844a and Line by 1 to 14
Special opcode 202: advance Address by 14 to 0x8048458 and Line by 1 to 15
Special opcode 174: advance Address by 12 to 0x8048464 and Line by 1 to 16
Special opcode 90: advance Address by 6 to 0x804846a and Line by 1 to 17
Special opcode 132: advance Address by 9 to 0x8048473 and Line by 1 to 18
Advance PC by constant 17 to 0x8048484
Special opcode 76: advance Address by 5 to 0x8048489 and Line by 1 to 19
Advance PC by constant 17 to 0x804849a
Special opcode 146: advance Address by 10 to 0x80484a4 and Line by 1 to 20
Special opcode 62: advance Address by 4 to 0x80484a8 and Line by 1 to 21
Special opcode 160: advance Address by 11 to 0x80484b3 and Line by 1 to 22

等等,应该是每条指令的都有了
这里有一个对格式简单的说明 http://hi.baidu.com/piaoling_sky/blog/item/f9654ad21a6ed43d970a169c.html


addr2line 应该也是使用了这几个段的信息的,objdump gdb等也都可以解析这个段的。

使用
strip -d a.out
命令去除掉 这个几个debug 段的话,addr2line 也就无能为力了

你可以自己试一下


threeleafzerg007 2011-08-02
  • 打赏
  • 举报
回复
addr2line隶属于binutils,是交叉编译工具里比较重要的一个命令:

源代码在:
http://download.chinaunix.net/download/0001000/900.shtml
binutils-2.15.94-20050118-1-src.tar.gz


个人理解,它还是像objdump一样,读出elf文件的文件头里的符号表,
比如 objdump -t ./test| grep text

0000000000400500 l d .text 0000000000000000 .text
000000000040052c l F .text 0000000000000000 call_gmon_start
0000000000400550 l F .text 0000000000000000 __do_global_dtors_aux
00000000004005c0 l F .text 0000000000000000 frame_dummy
00000000004006a0 l F .text 0000000000000000 __do_global_ctors_aux
0000000000400600 g F .text 0000000000000002 __libc_csu_fini
0000000000400500 g F .text 0000000000000000 _start
0000000000400610 g F .text 0000000000000089 __libc_csu_init
00000000004005ec g F .text 0000000000000012 main

第一项是这个函数在文件的起始地址,第5项是大小,
所以给定一个正文区的地址,它总能算出它是那个函数地址区间里的。

希望这样能使你明白。
ganjianh8 2011-08-02
  • 打赏
  • 举报
回复
求各位高手解惑。
ganjianh8 2011-08-02
  • 打赏
  • 举报
回复
谢谢楼上各位,动态加载找偏移这个我会,一般我用ldd去看的
ganjianh8 2011-07-31
  • 打赏
  • 举报
回复
backtrace我也知道一点,但只能查到函数的进口
至于函数内部的地址就无法查找
譬如
int func() 地址是0x8000
{
int a = 2; 这个地址是0x8004
int b = 3; 这个地址是0x8008
a = a + b;
return a;
}
我的问题是怎么知道0x8008是func的。
李迟 2011-07-27
  • 打赏
  • 举报
回复
有段时间我研究backtrace,还将汇编代码、栈帧这些东西一起研究,有空再研究吧。
李迟 2011-07-27
  • 打赏
  • 举报
回复
据说是根据backtrace原理来搞的,IBM上有篇文章,现在忘了。找到下面两个文章:
http://my.chinaunix.net/space.php?uid=26009500&do=blog&id=1585782
http://www.cnblogs.com/shanzy/articles/1439370.html
后面那篇基本上是英文的。

23,217

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧