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 tSymbol table '.dynsym' contains 4 entries:Num:    Value          Size Type    Bind   Vis      Ndx Name0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND1: 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 _start49: 00000000004004c4     6 FUNC    GLOBAL DEFAULT   13 bar
...53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND putchar@@GLIBC_2.2.554: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_55: 00000000004005e8     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used56: 00000000004004d0     6 FUNC    GLOBAL DEFAULT   13 foo
...64: 00000000004004d6    31 FUNC    GLOBAL DEFAULT   13 main65: 0000000000400390     0 FUNC    GLOBAL DEFAULT   11 _init66: 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 Name0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND1: 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_RegisterClasses4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)5: 0000000000400724     6 FUNC    GLOBAL DEFAULT   13 bar6: 0000000000400730     6 FUNC    GLOBAL DEFAULT   13 foo7: 0000000000600b68     0 NOTYPE  GLOBAL DEFAULT   24 __data_start8: 0000000000600b80     0 NOTYPE  GLOBAL DEFAULT  ABS _end9: 0000000000600b6c     0 NOTYPE  GLOBAL DEFAULT  ABS _edata10: 0000000000600b68     0 NOTYPE  WEAK   DEFAULT   24 data_start11: 0000000000400640     0 FUNC    GLOBAL DEFAULT   13 _start12: 0000000000400848     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used13: 0000000000400770   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init14: 0000000000600b6c     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start15: 0000000000400736    39 FUNC    GLOBAL DEFAULT   13 main16: 00000000004005f0     0 FUNC    GLOBAL DEFAULT   11 _init17: 0000000000400760     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini18: 0000000000400838     0 FUNC    GLOBAL DEFAULT   14 _fini19: 000000000040072a     6 FUNC    GLOBAL DEFAULT   13 bazSymbol table '.symtab' contains 67 entries:Num:    Value          Size Type    Bind   Vis      Ndx Name
...50: 0000000000400640     0 FUNC    GLOBAL DEFAULT   13 _start51: 0000000000400724     6 FUNC    GLOBAL DEFAULT   13 bar
...55: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND putchar@@GLIBC_2.2.556: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_57: 0000000000400848     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used58: 0000000000400730     6 FUNC    GLOBAL DEFAULT   13 foo
...64: 0000000000400736    31 FUNC    GLOBAL DEFAULT   13 main65: 00000000004005f0     0 FUNC    GLOBAL DEFAULT   11 _init66: 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.rdSymbol table '.dynsym' contains 20 entries:Num:    Value          Size Type    Bind   Vis      Ndx Name0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND1: 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_RegisterClasses4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)5: 0000000000400724     6 FUNC    GLOBAL DEFAULT   13 bar6: 0000000000400730     6 FUNC    GLOBAL DEFAULT   13 foo7: 0000000000600b68     0 NOTYPE  GLOBAL DEFAULT   24 __data_start8: 0000000000600b80     0 NOTYPE  GLOBAL DEFAULT  ABS _end9: 0000000000600b6c     0 NOTYPE  GLOBAL DEFAULT  ABS _edata10: 0000000000600b68     0 NOTYPE  WEAK   DEFAULT   24 data_start11: 0000000000400640     0 FUNC    GLOBAL DEFAULT   13 _start12: 0000000000400848     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used13: 0000000000400770   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init14: 0000000000600b6c     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start15: 0000000000400736    39 FUNC    GLOBAL DEFAULT   13 main16: 00000000004005f0     0 FUNC    GLOBAL DEFAULT   11 _init17: 0000000000400760     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini18: 0000000000400838     0 FUNC    GLOBAL DEFAULT   14 _fini19: 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_usedw _Jv_RegisterClasses
0000000000600b6c A __bss_start
0000000000600b68 D __data_startw __gmon_start__
0000000000400760 T __libc_csu_fini
0000000000400770 T __libc_csu_initU __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 mainU printf
[root@www c]#
[root@www c]# objdump -T t.rdt.rd:     file format elf64-x86-64DYNAMIC 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的异同相关推荐

  1. gcc或g++的编译选项 -shared -fPIC 与 -g -rdynamic 部分转载

    动态库 Linux 下动态链接库(shared object file,共享对象文件)的文件后缀为.so,它是一种特殊的目标文件(object file),可以在程序运行时被加载(链接)进来.使用动态 ...

  2. gcc 和 g++ 的联系和区别,使用 gcc 编译 c++

    GCC 编译器已经为我们提供了调用它的接口,对于 C 语言或者 C++ 程序,可以通过执行 gcc 或者 g++ 指令来调用 GCC 编译器. 实际使用中我们更习惯使用 gcc 指令编译 C 语言程序 ...

  3. gcc和g++是什么,有什么区别?

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 机器算法学习那些事 目前(2020-09)GCC 编译器已经更新至 ...

  4. linux下gcc、g++不同版本的安装和切换

    Ubuntu 18.04预装GCC版本为7.3,但有时在编译是需要用的不同gcc版本,下面介绍,如何安装不同的gcc 和g++,并设置根据不同的需要在不同版本之间切换. 1. 可以通过如下命令查看当前 ...

  5. gcc选项 和 gdb 使用

    CC 编译详解 GNU CC(简称为Gcc)是GNU项目中符合ANSI C标准的编译系统,能够编译用C.C++和Object C等语言编写的程序.Gcc不仅功能强大,而且可以编译如C.C++.Obje ...

  6. 第七章 进程环境 | 001 命令形参、gcc与g++的使用

    命令形参 命令行参数是使用main()函数参数来处理的,其中,argc是指传入参数的个数,argv[]是一个指针数组,指向传递给程序的每个参数. 应当指出的是, argv[0]存储程序的名称,argv ...

  7. gcc和g++有什么区别?

    来源 | C语言中文网 发展至今,GCC 编译器已经更新至 V10 版本,其功能也由最初仅能编译 C 语言,扩增至可以编译多种编程语言,其中就包括 C++ . 除此之外,当下的 GCC 编译器还支持编 ...

  8. 【Linux】-- 开发工具yum、vim、gcc、g++、gdb、make、makefile使用介绍

    目录 一.yum 1.了解yum (1)RPM (2)yum 2.yum使用 (1)查看软件包 (2)安装软件 (3)卸载软件 二.Linux编辑器-vim 1. vim概念 (1)命令模式 (2)插 ...

  9. 更改Ubuntu gcc、g++默认编译器版本

    更改Ubuntu gcc.g++默认编译器版本 转一篇文章: 升级Ubuntu到11.10,但在编译Android的时候出错了.这个Android在升级系统之前编译是没有错误的,对比发现升级到Ubun ...

最新文章

  1. silverlight实现2D人物动画
  2. MySQL高级 大批量插入数据
  3. webpack实用配置
  4. Ubuntu 18.04 - 启动时停留在 start bpfilter
  5. 苹果发布2019年上半年透明度报告,收到数万条政府请求
  6. ReentrantLock与Condition构造有界缓存队列与数据栈
  7. idea类文件前面有个小叉号
  8. Python 列表和元组学习
  9. php保存pdf旋转90度,怎么把pdf旋转90度 多个pdf文件页面旋转的方法|支持选择要旋转的页面及旋转角度...
  10. mac系统ps快捷键大全-来自三人行慕课
  11. 外汇汇率接口 java_免费的货币汇率API
  12. 使用WebGL 自定义 3D 摄像头监控模型
  13. 移动开发者如何获取免费流量
  14. web实例之电子日历
  15. 如何让Markdown 表格整体居中?
  16. php+挖矿病毒,Kdevtmpfsi 挖矿病毒处理方式
  17. 五、无限法则roe-滑雪高级进阶训练
  18. zuk 科学计算机,充电也有黑科技了解ZUK手机电池的秘密
  19. Kubernetes 版本升级
  20. 二十一世纪大学英语读写教程(第二册)学习笔记(原文)——6 - A Brief History of Stephen Hawking(斯蒂夫·霍金简传)

热门文章

  1. Python 进阶_OOP 面向对象编程_self 的实例绑定
  2. java doc 文档,注解详解
  3. 单点登录 - 修改CAS服务器的一些配置( 陆续添加)
  4. 三座”大山“或让谷歌无人机送货项目被冻结
  5. Activiti工作流实战-2
  6. SGU 113 Nearly prime numbers
  7. 初探Object Pascal的类(三)
  8. LTE上行加扰的目的是什么?
  9. git文件生命周期以及如何管理文件
  10. camelot工具进行pdf表格解析重建