binutils工具集
1.addr2line
作用:用于得到程序指令地址所对应的函数,以及函数所在的源文件名和行号。
addr2line 例:
-------------------------------------------------------------
//文件名:addr2line_test.c
#include<stdio.h>
void foo()
{
printf("The address of foo() %#x\n",foo);
}
int main(void)
{
foo();
return 0;
}
-------------------------------------------------------------
编译:gcc -g addr2line_test.c -o addr2line_test
执行:./addr2line_test
结果:The address of foo() 0x80483e4
-------------------------------------------------------------
null@ubuntu:~/c-test$ addr2line 0x80483e4 -f -e addr2line_test
foo
/home/null/c-test/addr2line_test.c:4
--------------------------------------------------------------
nm 符号显示器
--------------------------------------------------------------
null@ubuntu:~/c-test$ nm -n addr2line_test
............
080483e4 T foo
08048401 T main
............
--------------------------------------------------------------
对于c++可以使用addr2line的--demangle选项获得函数名
addr2line 地址 --demangle=gnu-v3 -f -e 可执行文件
--------------------------------------------------------------
2.ar,静态库生成器
先看下生成一个静态库和解压一个静态库的方法:
会在当前目录下生成一个libtest.a静态库文件。-c表示只编译,不链接
--------------------------------------------------------------
2.1生成一个静态库
gcc -c addr2line_test.c
//生成一个addr2line_test.o 文件
ar cr libtest.a addr2line_test.o
libtest.a //生成
--------------------------------------------------------------
2.2解压一个静态库
ar x libtest.a //将libtest.a解压 生成上面的 addr2line_test.o
--------------------------------------------------------------
2.3静态库的查看和删除
ar t xxx.a//查看
ar d libxx.a xx.o//删除静态库中的xx.o
--------------------------------------------------------------
2.4实验:
新建两个函数foo.c bar.c
----------------------------------
#include<stdio.h>
// foo.c function
void foo()
{
printf("This is foo()\n");
}
----------------------------------
#include<stdio.h>
// bar.c function
void bar()
{
printf("This is bar()\n");
}
----------------------------------
然后分别编译这两个文件生成.o文件
gcc -c bar.c
gcc -c foo.c
bar.c bar.o foo.c foo.o//生成的.o文件
然后用ar命令来生成libmy.a静态库
ar crs libmy.a foo.o bar.o
//c参数表示创建一个档案文件,r参数指示将文件增加到创建的库文件中
//s参数是为了生成库索引以提高库被链接时的效率
库文件已经生成,现在就该怎么使用这个库文件了。
新建一个main.c文件
-----------------------------------
#include<stdio.h>
extern void foo();
extern void bar();
int main()
{
foo();
bar();
return 0;
}
-----------------------------------
编译链接静态库:gcc main.c libmy.a -o main
./main
This is foo()
This is bar()
--------------------------------------------------------------
3.nm,符号显示器
nm用于列出程序文件的符号
--------------------------------------------------------------
先看一个例子: nm -n main
函数或变量的开始地址 相应的符号存放在哪一个段中 符号的名字
080482b0 T _init
08048320 T _start
08048350 t __do_global_dtors_aux
080483b0 t frame_dummy
080483d4 T main
080483ec T foo
08048400 T bar
08048420 T __libc_csu_init
08048490 T __libc_csu_fini
08048492 T __i686.get_pc_thunk.bx
080484a0 t __do_global_ctors_aux
080484cc T _fini
080484e8 R _fp_hw
080484ec R _IO_stdin_used
08048650 r __FRAME_END__
08049f14 d __CTOR_LIST__
08049f14 d __init_array_end
08049f14 d __init_array_start
08049f18 d __CTOR_END__
08049f1c d __DTOR_LIST__
08049f20 D __DTOR_END__
08049f24 d __JCR_END__
08049f24 d __JCR_LIST__
08049f28 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
0804a00c D __data_start
0804a00c W data_start
0804a010 D __dso_handle
0804a014 A __bss_start
0804a014 A _edata
0804a014 b completed.6159
0804a018 b dtor_idx.6161
0804a01c A _end
--------------------------------------------------------------
符号的含义
字母 说明
A 表示符号所对应的的值是绝对的且在以后的连接过程中也不会改变
B或b 未初始化的.bss段
C 表示没有被初始化的公共符号
D或d 表示位于初始化的.data段
N 表示符号是调试用的
P 表示符号位于一个栈回溯段中
R或r 表示位于只读数据段(.rdata)中
T或t 表示符号位于代码段(.text)
U 表示符号没有被定义
--------------------------------------------------------------
新建一个main.c文件:
---------------------------------
#include<time.h>
int global1;
int global2 = 1;
static int static_global1;
static int static_global2 = 1;
void foo()
{
int internal1;
int internal2 = 1;
static int static_internal1;
static int static_internal2 = 1;
time(0);
}
int main(void)
{
int local1;
int local2 = 1;
static int static_local1;
staitc int static_local2 =1;
foo();
return 0;
}
---------------------------------
gcc -c -g main.c
nm -n main.o
//注意输出结果是0地址开始,由于程序没有完成链接,所以是指符号在对应段中的相对偏移位置
U time //没用被定义的符号,原因是在c的标准库中
00000000 T foo //.test
00000000 D global2 //.data
00000000 b static_global1 //.bss
00000004 C global1 //未初始化的公共符号
00000004 d static_global2 //.data
00000004 b static_local1.1419 //.bss
00000008 b static_internal1.1412//.bss
00000008 d static_local2.1420 //.data
0000000c d static_internal2.1413//.data
0000001b T main //.text
------------------------------------------------------------
总结:
1.静态变量初始话后放在.data,没有被初始话则放在.bss段
2.非静态的全局变量初始化后放在.data,否则放在.bss
3.函数无论是静态还是动态都是放在.text段。字母“t”的大小写表示
了符号是否为静态函数,小写表示静态
4.函数内的局部变量由于被分配到了栈上,nm中是看不到他们的
--------------------------------------------------------------
链接后看变化:1.地址变化 2.global1变化了
080483d4 T foo
080483ef T main
0804a014 D global2
0804a018 d static_global2
0804a01c d static_local2.1420
0804a020 d static_internal2.1413
0804a02c b static_global1
0804a030 b static_local1.1419
0804a034 b static_internal1.1412
0804a038 B global1 //这里变化
--------------------------------------------------------------
binutils工具集1
最新推荐文章于 2023-10-16 14:49:15 发布