gcc选项-g与-rdynamic的异同_转
转自:http://www.tuicool.com/articles/EvIzUn
gcc 的 -g ,应该没有人不知道它是一个调试选项,因此在一般需要进行程序调试的场景下,我们都会加上该选项,并且根据调试工具的不同,还能直接选择更有针对性的说明,比如 -ggdb 。-g是一个编译选项,即在源代码编译的过程中起作用,让gcc把更多调试信息(也就包括符号信息)收集起来并将存放到最终的可执行文件内。
相比-g选项, -rdynamic 却是一个 连接选项 ,它将指示连接器把所有符号(而不仅仅只是程序已使用到的外部符号)都添加到动态符号表(即.dynsym表)里,以便那些通过 dlopen() 或 backtrace() (这一系列函数使用.dynsym表内符号)这样的函数使用。
看示例:
[root@www c]# cat t.c
#include <stdio.h>
void bar() {}
void baz() {}
void foo() {}
int main() { foo(); printf("test"); return 0; }
对于上面的示例代码,普通和加-g编译:
[root@www c]# uname -a
Linux www.t1.com 2.6.38.8 #2 SMP Wed Nov 2 07:52:53 CST 2011 x86_64 x86_64
x86_64 GNU/Linux
[root@www c]# gcc -O0 -o t t.c
[root@www c]# gcc -O0 -g -o t.g t.c
[root@www c]# readelf -a t > t.elf
[root@www c]# readelf -a t.g > t.g.elf
[root@www c]# ls -lh *.elf t t.g
-rwxr-xr-x. 1 root root 6.6K Jul 24 06:50 t
-rw-r--r--. 1 root root 15K Jul 24
06:51 t.elf
-rwxr-xr-x. 1 root root 7.9K Jul 24 06:50 t.g
-rw-r--r--. 1 root root 16K Jul 24
06:51 t.g.elf
加-g编译后,因为包含了debug信息,因此生成的可执行文件偏大(程序本身非常小,所以增加的调试信息不多)。
看-g编译的符号表:
[root@www c]# readelf -s t
Symbol table '.dynsym' contains 4 entries:
Num: Value Size Type Bind
Vis Ndx Name
0: 0000000000000000 0 NOTYPE
LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC
GLOBAL DEFAULT UND
printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE
WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 FUNC
GLOBAL DEFAULT UND
__libc_start_main@GLIBC_2.2.5 (2)
Symbol table '.symtab' contains 67 entries:
Num: Value Size Type Bind
Vis Ndx Name
...
48: 00000000004003e0
0 FUNC GLOBAL DEFAULT
13 _start
49: 00000000004004c4
6 FUNC GLOBAL DEFAULT
13 bar
...
53: 0000000000000000
0 FUNC GLOBAL DEFAULT
UND putchar@@GLIBC_2.2.5
54: 0000000000000000
0 FUNC GLOBAL DEFAULT
UND __libc_start_main@@GLIBC_
55: 00000000004005e8
4 OBJECT GLOBAL DEFAULT
15 _IO_stdin_used
56: 00000000004004d0
6 FUNC GLOBAL DEFAULT
13 foo
...
64: 00000000004004d6
31 FUNC GLOBAL DEFAULT
13 main
65: 0000000000400390
0 FUNC GLOBAL DEFAULT
11 _init
66: 00000000004004ca
6 FUNC GLOBAL DEFAULT
13 baz
注意.dynsym表,只有该程序用到的几个外部动态符号存在。
加-rdynamic选项编译,readelf查看:
[root@www c]# gcc -O0 -rdynamic -o t.rd t.c
[root@www c]# readelf -s t.rd
Symbol table '.dynsym' contains 20 entries:
Num: Value Size Type Bind
Vis Ndx Name
0: 0000000000000000 0 NOTYPE
LOCAL DEFAULT UND
1: 0000000000000000 0
FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE
WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE
WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC
GLOBAL DEFAULT UND
__libc_start_main@GLIBC_2.2.5 (2)
5: 0000000000400724 6 FUNC
GLOBAL DEFAULT 13 bar
6: 0000000000400730 6 FUNC
GLOBAL DEFAULT 13 foo
7: 0000000000600b68 0 NOTYPE
GLOBAL DEFAULT 24 __data_start
8: 0000000000600b80 0 NOTYPE
GLOBAL DEFAULT ABS _end
9: 0000000000600b6c 0 NOTYPE
GLOBAL DEFAULT ABS _edata
10: 0000000000600b68 0 NOTYPE
WEAK DEFAULT 24 data_start
11: 0000000000400640 0 FUNC
GLOBAL DEFAULT 13 _start
12: 0000000000400848 4 OBJECT
GLOBAL DEFAULT 15 _IO_stdin_used
13: 0000000000400770 137 FUNC
GLOBAL DEFAULT 13
__libc_csu_init
14: 0000000000600b6c 0 NOTYPE
GLOBAL DEFAULT ABS __bss_start
15: 0000000000400736 39 FUNC
GLOBAL DEFAULT 13 main
16: 00000000004005f0 0 FUNC
GLOBAL DEFAULT 11 _init
17: 0000000000400760 2 FUNC
GLOBAL DEFAULT 13
__libc_csu_fini
18: 0000000000400838 0 FUNC
GLOBAL DEFAULT 14 _fini
19: 000000000040072a 6 FUNC
GLOBAL DEFAULT 13 baz
Symbol table '.symtab' contains 67 entries:
Num: Value Size Type Bind
Vis Ndx Name
...
50: 0000000000400640 0 FUNC
GLOBAL DEFAULT 13 _start
51: 0000000000400724 6
FUNC GLOBAL DEFAULT 13 bar
...
55: 0000000000000000 0 FUNC
GLOBAL DEFAULT UND
putchar@@GLIBC_2.2.5
56: 0000000000000000 0 FUNC
GLOBAL DEFAULT UND
__libc_start_main@@GLIBC_
57: 0000000000400848 4 OBJECT
GLOBAL DEFAULT 15 _IO_stdin_used
58: 0000000000400730 6 FUNC
GLOBAL DEFAULT 13 foo
...
64: 0000000000400736 31 FUNC
GLOBAL DEFAULT 13 main
65: 00000000004005f0 0 FUNC
GLOBAL DEFAULT 11 _init
66: 000000000040072a 6 FUNC
GLOBAL DEFAULT 13 baz
[root@www c]#
可以看到添加-rdynamic选项后,.dynsym表就包含了所有的符号,不仅是已使用到的外部动态符号,还包括本程序内定义的符号,比如bar、foo、baz等。
.dynsym表里的数据并不能被strip掉:
[root@www c]# strip t.rd
[root@www c]# readelf -s t.rd
Symbol table '.dynsym' contains 20 entries:
Num: Value Size Type Bind
Vis Ndx Name
0: 0000000000000000 0 NOTYPE
LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC
GLOBAL DEFAULT UND
printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE
WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE
WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC
GLOBAL DEFAULT UND
__libc_start_main@GLIBC_2.2.5 (2)
5: 0000000000400724 6 FUNC
GLOBAL DEFAULT 13 bar
6: 0000000000400730 6 FUNC
GLOBAL DEFAULT 13 foo
7: 0000000000600b68 0 NOTYPE
GLOBAL DEFAULT 24 __data_start
8: 0000000000600b80 0 NOTYPE
GLOBAL DEFAULT ABS _end
9: 0000000000600b6c 0 NOTYPE
GLOBAL DEFAULT ABS _edata
10: 0000000000600b68 0 NOTYPE
WEAK DEFAULT 24 data_start
11: 0000000000400640 0 FUNC
GLOBAL DEFAULT 13 _start
12: 0000000000400848 4 OBJECT
GLOBAL DEFAULT 15 _IO_stdin_used
13: 0000000000400770 137 FUNC
GLOBAL DEFAULT 13
__libc_csu_init
14: 0000000000600b6c 0 NOTYPE
GLOBAL DEFAULT ABS __bss_start
15: 0000000000400736 39 FUNC
GLOBAL DEFAULT 13 main
16: 00000000004005f0 0 FUNC
GLOBAL DEFAULT 11 _init
17: 0000000000400760 2 FUNC
GLOBAL DEFAULT 13
__libc_csu_fini
18: 0000000000400838 0 FUNC
GLOBAL DEFAULT 14 _fini
19: 000000000040072a 6 FUNC
GLOBAL DEFAULT 13 baz
简单总结一下-g选项与-rdynamic选项的差别:
1,-g选项新添加的是调试信息(一系列.debug_xxx段),被相关调试工具,比如gdb使用,可以被strip掉。
2,-rdynamic选项新添加的是动态连接符号信息,用于动态连接功能,比如dlopen()系列函数、backtrace()系列函数使用,不能被strip掉,即强制strip将导致程序无法执行:
[root@www c]# ./t.rd
test[root@www c]# strip -R .dynsym t.rd
[root@www c]# ./t.rd
./t.rd: relocation error: ./t.rd: symbol , version GLIBC_2.2.5 not defined
in file libc.so.6 with link time reference
[root@www c]#
3,.symtab表在程序加载时会被加载器 丢弃 ,gdb等调试工具由于可以直接访问到磁盘上的二进制程序文件:
[root@www c]# gdb t.g -q
Reading symbols from /home/work/dladdr/c/t.g...done.
(gdb)
因此可以使用所有的调试信息,这包括.symtab表;而backtrace()系列函数作为程序执行的逻辑功能,无法去读取磁盘上的二进制程序文件,因此只能使用.dynsym表。
其它几个工具可以动态指定查看,比如nm、objdump:
[root@www c]# nm t.rd
nm: t.rd: no symbols
[root@www c]# nm -D t.rd
0000000000400848 R _IO_stdin_used
w
_Jv_RegisterClasses
0000000000600b6c A __bss_start
0000000000600b68 D __data_start
w __gmon_start__
0000000000400760 T __libc_csu_fini
0000000000400770 T __libc_csu_init
U __libc_start_main
0000000000600b6c A _edata
0000000000600b80 A _end
0000000000400838 T _fini
00000000004005f0 T _init
0000000000400640 T _start
0000000000400724 T bar
000000000040072a T baz
0000000000600b68 W data_start
0000000000400730 T foo
0000000000400736 T main
U printf
[root@www c]#
[root@www c]# objdump -T t.rd
t.rd: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 printf
0000000000000000 w D
*UND* 0000000000000000 __gmon_start__
0000000000000000 w D
*UND* 0000000000000000 _Jv_RegisterClasses
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __libc_start_main
0000000000400724 g DF .text 0000000000000006 Base
bar
0000000000400730 g DF .text 0000000000000006 Base
foo
0000000000600b68 g D .data 0000000000000000 Base
__data_start
0000000000600b80 g D *ABS* 0000000000000000 Base
_end
0000000000600b6c g D *ABS* 0000000000000000 Base
_edata
0000000000600b68 w D
.data 0000000000000000 Base
data_start
0000000000400640 g DF .text 0000000000000000 Base
_start
0000000000400848 g DO .rodata 0000000000000004 Base
_IO_stdin_used
0000000000400770 g DF .text 0000000000000089 Base
__libc_csu_init
0000000000600b6c g D *ABS* 0000000000000000 Base
__bss_start
0000000000400736 g DF .text 0000000000000027 Base
main
00000000004005f0 g DF .init 0000000000000000 Base
_init
0000000000400760 g DF .text 0000000000000002 Base
__libc_csu_fini
0000000000400838 g DF .fini 0000000000000000 Base
_fini
000000000040072a g DF .text 0000000000000006 Base
baz
4,-rdynamic选项不产生任何调试信息,因此在一般情况下,新增的附加信息比-g选项要少得多。除非是完全的静态连接,否则即便是没有加-rdynamic选项,程序使用到的外部动态符号,比如前面示例里的printf,也会被自动加入到.dynsym表。
完全参考:
http://stackoverflow.com/questions/8623884/gcc-debug-symbols-g-flag-vs-linkers-rdynamic-option
gcc选项-g与-rdynamic的异同_转的更多相关文章
- gcc选项-g与-rdynamic的异同
摘自http://www.tuicool.com/articles/EvIzUn gcc选项-g与-rdynamic的异同 gcc 的 -g ,应该没有人不知道它是一个调试选项,因此在一般需要进行程序 ...
- gcc和g++
一.GCC GNU编译器套件(GNU Compiler Collection)包括C.C++.Objective-C.Fortran.Java.Ada和Go语言的前端,也包括了这些语言的库(如libs ...
- gcc、g++
http://hi.baidu.com/zhangcunli8499/item/257e187360b48b2bd6a89cc6 g++ src/*.cpp -I include/ -I includ ...
- -g vs -rdynamic
[-g vs -rdynamic] -g选项与-rdynamic选项的差别:1,-g选项新添加的是调试信息(一系列.debug_xxx段),被相关调试工具,比如gdb使用,可以被strip掉. 2,- ...
- gcc与g++的区别
一:gcc与g++比较 编译c/c++代码的时候,有人用gcc,有人用g++,于是各种说法都来了,譬如c代码用gcc,而 c++代码用g++,或者说编译用gcc,链接用g++,一时也不知哪个说法正确, ...
- gcc和g++编译c或者c++文件碰到的问题
gcc和g++都是GNU(组织)的一个编译器. 误区一:gcc只能编译c代码,g++只能编译c++代码 两者都可以,但是请注意: 1.后缀为.c的,gcc把它当作是C ...
- gcc与g++的编译链接的示例详解
一.编译方式的示例详解 1. 编译C代码 代码如下:main.c /*! ************************************************************** ...
- gcc and g++ 常用参数解释
程序编译运行的过程 预处理.处理一些#include,#define命令,生成.i或者.ii文件: 编译.编译器进行语法分析,语义分析,中间代码生成,目标代码生成,优化,生成.s文件 汇编.汇编器把汇 ...
- cc、gcc、g++、CC的区别概括
gcc是C编译器:g++是C++编译器:linux下cc一般是一个符号连接,指向gcc:gcc和g++都是GUN(组织)的编译器.而CC则一般是makefile里面的一个名字,即宏定义,嘿,因为Lin ...
随机推荐
- [转]Entity Framework走马观花之把握全局
本文转自:http://blog.csdn.net/bitfan/article/details/12887007 Entity Framework走马观花 之 把握全局 ============== ...
- 1. Nginx
参考: http://www.darrenfang.com/2014/02/install-php-with-nginx-on-ubuntu/ 安装: apt-get install python ...
- POJ 1511 最短路spfa
题很简单 就是有向图中求给出的源点到其余所有点的最短路的和与其余所有点到源点的最短路之和 一开始以为dij对于正权图的单源最短路是最快的 写了一发邻接表的dij 结果超时 把所有的cin改成scanf ...
- Web 在线文件管理器学习笔记与总结(1)初始文件以及获取首层目录信息
在线文件管理器即使用浏览器管理和操作项目中的目录和文件 文件相关操作包括: 1.创建文件 2.判断文件的权限 3.文件的大小 4.文件的创建时间.修改时间.访问时间 5.查看文件的内容 6.修改文件的 ...
- 让Win8自动登录免输入密码的小技巧
按Win+R键,输出“netplwiz”,单击“确定”,弹出“用户帐户”窗口.将第一个画框上的勾选去掉——应用——弹出自动登录输入你的密码——确定——确定完成.重启看看电脑是不是不用输入密码也可以自动 ...
- 语艺杂谈1 – MAP赋值与插入
MAP赋值和插入,对于相同ID的处理方式不同,前者为替换 后者为插入失败 #include <map> #include <string> #include <iostr ...
- Ruby--String
--全部转为小写:[STR].downcase --全部转为大写:[STR].upcase --仅仅首字母为大写:[STR].capitalize --每个单词首字母为大写:[STR].titleiz ...
- 使用 html5 postMessage 实现跨域
英文原文 中文翻译 因为web的安全机制,浏览器的同源策略.在不同域之间做数据交换就会涉及到跨域.A域如果要实现向B域发关消息,多多少少要有对B域有一定控制权,最起码人家B域要接收你的消息啊. 最近发 ...
- UCenter 通信失败 和 无法同步登陆的调试方法
1. 看请求 2./uc_server/control/admin/app.php echo "\$url = $url <br />\n \$status = $status& ...
- 7添加一个“X”到HTML:转到XHTML
XHTML中的X代表extensible,是以XML为基础的另一种说法.XML表示可扩展的标记语言. XML是一种可以用来开发新的标记语言的语言,而HTML只是一门标记语言. HTML转化为XHTML ...