您现在的位置是:首页 >技术教程 >【编译、链接、装载六】汇编——目标文件网站首页技术教程

【编译、链接、装载六】汇编——目标文件

郑同学的笔记 2024-10-25 00:01:07
简介【编译、链接、装载六】汇编——目标文件

一、目标文件_存储格式

  • 目标文件就是源代码编译后但未进行链接的那些中间文件(Windows的.obj和Linux下的.o)

1、生成目标文件

  • 代码
#include<stdio.h>

int global_init_var = 123;
int global_uninit_var;

void show( int i )
{
	printf( "%d
", i );
}

int main()
{
	static int static_var = 456;
	static int static_var2;

	int a = 1;
	int b;

	show(a);

	return -1;
}
  • 生成目标文件的指令
gcc -c hello.c -o hello.o

2、目标文件存储格式

目标文件跟可执行文件的内容与结构很相似,所以一般跟可执行文件格式一起采用一种格式存储。
在Windows下,我们可以统称它们为PECOFF文件格式。
在Linux下,我们可以将它们统称为ELF文件。
其他不太常见的可执行文件格式还有Intel/Microsoft的OMF(Object Module Format)、Unix a.out格式和MS-DOS .COM格式等。

不光是可执行文件(Windows的.exe和Linux下的ELF可执行文件)按照可执行文件格式存储。动态链接库(DLL,Dynamic Linking Library)(Windows的.dll和Linux的.so)及静态链接库(Static Linking Library)(Windows的.lib和Linux的.a)文件都按照可执行文件格式存储。它们在Windows下都按照PE-COFF格式存储,Linux下按照ELF格式存储。静态链接库稍有不同,它是把很多目标文件捆绑在一起形成一个文件,再加上一些索引,你可以简单地把它理解为一个包含有很多目标文件的文件包。
在这里插入图片描述

3、file查看文件格式

  • file:查看文件格式
$file hello.o

二、查看目标文件的内部结构——objdump

一般目标文件将这些信息按不同的属性,以“节”(Section)的形式存储,有时候也叫“段”(Segment).

在一般情况下,它们都表示一个一定长度的区域,基本上不加以区别,唯一的区别是在ELF的链接视图和装载视图的时候,后面会专门提到。

  • objdump指令,参数“-h”就是把ELF文件的各个段的基本信息打印出来。我们也可以使用“objdump –x”把更多的信息打印出来.
$objdump -h hello.o
$objdump -x hello.o

在这里插入图片描述

如上图,目标文件的格式是ELF,从图中可以看到,ELF文件的开头是一个“文件头”,它描述了整个文件的文件属性,包括文件是否可执行、是静态链接还是动态链接及入口地址(如果是可执行文件)、目标硬件、目标操作系统等信息,文件头还包括一个段表(Section Table),段表其实是一个描述文件中各个段的数组。段表描述了文件中各个段在文件中的偏移位置及段的属性等,从段表里面可以得到每个段的所有信息。文件头后面就是各个段的内容,比如代码段保存的就是程序的指令,数据段保存的就是程序的静态变量

段名解释
.code或.text代码段程序源代码编译后的机器指令经常被放在代码段(Code Section)里
.data数据段全局变量和局部静态变量数据经常放在数据段(Data Section)。让我们
.bss数据段未初始化的全局变量和局部静态变量一般放在一个叫.“bss”的段里。
.rodata数据段只读数据段,const的全局变量,#define定义的常量,以及诸如“Hello World”的字符串常量
.comment注释信息段没太懂
.note.GNU-stack编译信息编译器的版本信息段
.en_frame调试信息调试时,栈回溯时用到

const修饰的全局变量在常量区;const修饰的局部变量只是为了防止修改,没有放入常量区(代码区.text)。

未初始化的全局变量和局部静态变量默认值都为0,本来它们也可以被放在.data段的,但是因为它们都是0,所以为它们在.data段分配空间并且存放数据0是没有必要的。程序运行的时候它们的确是要占内存空间的,并且可执行文件必须记录所有未初始化的全局量和局部静态变量的大小总和,记为.bss段。所以.bss段只是为未初始化的全局变量和局部静态变量预留位置而已,它并没有内容,所以它在文件中也不占据空间。

数据段,.bss、.rdata、.data
导出数据段,.edata
导入数据段,.idata
段是导入数据,.idata
.edata段包含了应用程序或DLL的导出数据。在这个段出现的时候,它会包含一个到达导出信息的导出目录。

  • 查看目标文件详细信息

$objdump -x hello.o

在这里插入图片描述

  • size命令
    做“size”,它可以用来查看ELF文件的代码段、数据段和BSS段的长度(dec表示3个段长度的和的十进制,hex表示长度和的十六进制):
    在这里插入图片描述

三、代码段

  • objdump的 “-s”参数可以将所有段的内容以十六进制的方式打印出来 ,“-d ”参数可以将所有包含指令的段反汇编。
$gcc -c hello.c -o hello.o
[dev1@localhost test01]$ gcc -c hello.c -o hello.o
[dev1@localhost test01]$ objdump -s -d hello.o

hello.o:     文件格式 elf64-x86-64

Contents of section .text:
 0000 554889e5 4883ec10 897dfc8b 45fc89c6  UH..H....}..E...
 0010 bf000000 00b80000 0000e800 000000c9  ................
 0020 c3554889 e54883ec 10c745fc 01000000  .UH..H....E.....
 0030 8b45fc89 c7e80000 0000b8ff ffffffc9  .E..............
 0040 c3                                   .               
Contents of section .data:
 0000 7b000000 c8010000                    {.......        
Contents of section .rodata:
 0000 25640a00                             %d..            
Contents of section .comment:
 0000 00474343 3a202847 4e552920 342e382e  .GCC: (GNU) 4.8.
 0010 35203230 31353036 32332028 52656420  5 20150623 (Red 
 0020 48617420 342e382e 352d3434 2900      Hat 4.8.5-44).  
Contents of section .eh_frame:
 0000 14000000 00000000 017a5200 01781001  .........zR..x..
 0010 1b0c0708 90010000 1c000000 1c000000  ................
 0020 00000000 21000000 00410e10 8602430d  ....!....A....C.
 0030 065c0c07 08000000 1c000000 3c000000  ...........<...
 0040 00000000 20000000 00410e10 8602430d  .... ....A....C.
 0050 065b0c07 08000000                    .[......        

Disassembly of section .text:

0000000000000000 <show>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	48 83 ec 10          	sub    $0x10,%rsp
   8:	89 7d fc             	mov    %edi,-0x4(%rbp)
   b:	8b 45 fc             	mov    -0x4(%rbp),%eax
   e:	89 c6                	mov    %eax,%esi
  10:	bf 00 00 00 00       	mov    $0x0,%edi
  15:	b8 00 00 00 00       	mov    $0x0,%eax
  1a:	e8 00 00 00 00       	callq  1f <show+0x1f>
  1f:	c9                   	leaveq 
  20:	c3                   	retq   

0000000000000021 <main>:
  21:	55                   	push   %rbp
  22:	48 89 e5             	mov    %rsp,%rbp
  25:	48 83 ec 10          	sub    $0x10,%rsp
  29:	c7 45 fc 01 00 00 00 	movl   $0x1,-0x4(%rbp)
  30:	8b 45 fc             	mov    -0x4(%rbp),%eax
  33:	89 c7                	mov    %eax,%edi
  35:	e8 00 00 00 00       	callq  3a <main+0x19>
  3a:	b8 ff ff ff ff       	mov    $0xffffffff,%eax
  3f:	c9                   	leaveq 
  40:	c3                   	retq   
[dev1@localhost test01]$ 

跟前面我们了解到的“.text”段长度相符合,最左面一列是偏移量,中间4列是十六进制内容,最右面一列是.text段的ASCII码形式。对照下面的反汇编结果,可以很明显地看到,.text段里所包含的正是hello.c里两个函数 func1() 和 main() 的指令

四、 数据段和只读数据段

  • .data段保存的是那些已经初始化了的全局静态变量和局部静态变量。前面的SimpleSection.c代码里面一共有两个这样的变量,分别是global_init_varabal 与 static_var 。这两个变量每个4个字节,一共刚好8个字节,所以“.data”这个段的大小为8个字节。
  • SimpleSection.c里面我们在调用“printf”的时候,用到了一个字符串常量“%d ”,它是一种只读数据,所以它被放到了“.rodata”段,我们可以从输出结果看到“.rodata”这个段的4个字节刚好是这个字符串常量的ASCII字节序,最后以结尾。
  • “.rodata”段存放的是只读数据,一般是程序里面的只读变量(如const修饰的变量)和字符串常量。单独设立“.rodata”段有很多好处,不光是在语义上支持了C++的const关键字,而且操作系统在加载的时候可以将“.rodata”段的属性映射成只读,

有时候编译器会把字符串常量放到“.data”段,而不会单独放在“.rodata”段。

objdump -x -s -d hello.o
[dev1@localhost test01]$ objdump -x -s -d hello.o

hello.o:     文件格式 elf64-x86-64
hello.o
体系结构:i386:x86-64,标志 0x00000011:
HAS_RELOC, HAS_SYMS
起始地址 0x0000000000000000

节:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000041  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  0000000000000000  0000000000000000  00000084  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000004  0000000000000000  0000000000000000  0000008c  2**2
                  ALLOC
  3 .rodata       00000004  0000000000000000  0000000000000000  0000008c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .comment      0000002e  0000000000000000  0000000000000000  00000090  2**0
                  CONTENTS, READONLY
  5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000be  2**0
                  CONTENTS, READONLY
  6 .eh_frame     00000058  0000000000000000  0000000000000000  000000c0  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l    df *ABS*	0000000000000000 hello.c
0000000000000000 l    d  .text	0000000000000000 .text
0000000000000000 l    d  .data	0000000000000000 .data
0000000000000000 l    d  .bss	0000000000000000 .bss
0000000000000000 l    d  .rodata	0000000000000000 .rodata
0000000000000000 l     O .bss	0000000000000004 static_var2.2184
0000000000000004 l     O .data	0000000000000004 static_var.2183
0000000000000000 l    d  .note.GNU-stack	0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame	0000000000000000 .eh_frame
0000000000000000 l    d  .comment	0000000000000000 .comment
0000000000000000 g     O .data	0000000000000004 global_init_var
0000000000000004       O *COM*	0000000000000004 global_uninit_var
0000000000000000 g     F .text	0000000000000021 show
0000000000000000         *UND*	0000000000000000 printf
0000000000000021 g     F .text	0000000000000020 main


Contents of section .text:
 0000 554889e5 4883ec10 897dfc8b 45fc89c6  UH..H....}..E...
 0010 bf000000 00b80000 0000e800 000000c9  ................
 0020 c3554889 e54883ec 10c745fc 01000000  .UH..H....E.....
 0030 8b45fc89 c7e80000 0000b8ff ffffffc9  .E..............
 0040 c3                                   .               
Contents of section .data:
 0000 7b000000 c8010000                    {.......        
Contents of section .rodata:
 0000 25640a00                             %d..            
Contents of section .comment:
 0000 00474343 3a202847 4e552920 342e382e  .GCC: (GNU) 4.8.
 0010 35203230 31353036 32332028 52656420  5 20150623 (Red 
 0020 48617420 342e382e 352d3434 2900      Hat 4.8.5-44).  
Contents of section .eh_frame:
 0000 14000000 00000000 017a5200 01781001  .........zR..x..
 0010 1b0c0708 90010000 1c000000 1c000000  ................
 0020 00000000 21000000 00410e10 8602430d  ....!....A....C.
 0030 065c0c07 08000000 1c000000 3c000000  ...........<...
 0040 00000000 20000000 00410e10 8602430d  .... ....A....C.
 0050 065b0c07 08000000                    .[......        

Disassembly of section .text:

0000000000000000 <show>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	48 83 ec 10          	sub    $0x10,%rsp
   8:	89 7d fc             	mov    %edi,-0x4(%rbp)
   b:	8b 45 fc             	mov    -0x4(%rbp),%eax
   e:	89 c6                	mov    %eax,%esi
  10:	bf 00 00 00 00       	mov    $0x0,%edi
			11: R_X86_64_32	.rodata
  15:	b8 00 00 00 00       	mov    $0x0,%eax
  1a:	e8 00 00 00 00       	callq  1f <show+0x1f>
			1b: R_X86_64_PC32	printf-0x4
  1f:	c9                   	leaveq 
  20:	c3                   	retq   

0000000000000021 <main>:
  21:	55                   	push   %rbp
  22:	48 89 e5             	mov    %rsp,%rbp
  25:	48 83 ec 10          	sub    $0x10,%rsp
  29:	c7 45 fc 01 00 00 00 	movl   $0x1,-0x4(%rbp)
  30:	8b 45 fc             	mov    -0x4(%rbp),%eax
  33:	89 c7                	mov    %eax,%edi
  35:	e8 00 00 00 00       	callq  3a <main+0x19>
			36: R_X86_64_PC32	show-0x4
  3a:	b8 ff ff ff ff       	mov    $0xffffffff,%eax
  3f:	c9                   	leaveq 
  40:	c3                   	retq   
[dev1@localhost test01]$ 

下一篇文章,详细的展示下全局变量、局部变量、常量、static、const,分别存储在哪儿?

五、 ELF文件结构描述

1、头文件

我们已经通过SimpleSection.o的结构大致了解了ELF文件的轮廓,接着就来看看ELF文件的结构格式。
ELF目标文件格式的最前部是ELF文件头(ELF Header),它包含了描述整个文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址等。

  • 我们可以用readelf命令来详细查看ELF文件
[dev1@localhost test01]$ readelf -h hello.o
ELF 头:
  Magic:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  类别:                              ELF64
  数据:                              2 补码,小端序 (little endian)
  版本:                              1 (current)
  OS/ABI:                            UNIX - System V
  ABI 版本:                          0
  类型:                              REL (可重定位文件)
  系统架构:                          Advanced Micro Devices X86-64
  版本:                              0x1
  入口点地址:              0x0
  程序头起点:              0 (bytes into file)
  Start of section headers:          984 (bytes into file)
  标志:             0x0
  本头的大小:       64 (字节)
  程序头大小:       0 (字节)
  Number of program headers:         0
  节头大小:         64 (字节)
  节头数量:         13
  字符串表索引节头: 12

从上面输出的结果可以看到,ELF的文件头中定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度及段的数量等。
在这里插入图片描述

  • 类型
    在这里插入图片描述

2、段表

我们知道ELF文件中有很多各种各样的段,这个段表(Section Header Table)就是保存这些段的基本属性的结构。

前文中我们使用了“objudmp -h”来查看ELF文件中包含的段,结果是SimpleSection里面看到了总共有6个段,分别是 “.code”、“.data”、“.bss ”、“.rodata ”、“. comment ”和“. note.GNU-stack ”。实际上的情况却有所不同,“objdump -h”命令只是把ELF文件中关键的段显示了出来,而省略了其他的辅助性的段,比如:符号表、字符串表、段名字符串表、重定位表等。我们可以使用readelf工具来查看ELF文件的段,它显示出来的结果才是真正的段表结构:

注意:这是大写的-S

[dev1@localhost test01]$ readelf -S hello.o
共有 13 个节头,从偏移量 0x3d8 开始:

节头:
  [] 名称              类型             地址              偏移量
       大小              全体大小          旗标   链接   信息   对齐
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000041  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  000002f8
       0000000000000048  0000000000000018   I      10     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000084
       0000000000000008  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  0000008c
       0000000000000004  0000000000000000  WA       0     0     4
  [ 5] .rodata           PROGBITS         0000000000000000  0000008c
       0000000000000004  0000000000000000   A       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  00000090
       000000000000002e  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000be
       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  000000c0
       0000000000000058  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  00000340
       0000000000000030  0000000000000018   I      10     8     8
  [10] .symtab           SYMTAB           0000000000000000  00000118
       0000000000000180  0000000000000018          11    11     8
  [11] .strtab           STRTAB           0000000000000000  00000298
       000000000000005d  0000000000000000           0     0     1
  [12] .shstrtab         STRTAB           0000000000000000  00000370
       0000000000000061  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

  • 目标文件——常用段名
常用段名Value
.text代码段,存放代码和局部const变量
.rela.text重定位表,重定位的信息
.data保存的是那些已经初始化了的全局静态变量和局部静态变量
.bbs存放的是未初始化的全局变量和局部静态变量
.rodataread only data 。存放的是只读数据,比如字符串常量,全局const变量。
.comment存放的是编译器的版本信息,比如字符串:
.note额外的编译器信息。比如程序的公司名,发布版本号等。
.en_frame调用栈信息
.rela…en_frame重定位的调用栈信息
.systabsymbol table 符号表
.strtabstring table ,字符串表,用于存储ELE文件中用到的字符串
.shstrtabsection string table 段名表

2.1、重定位表

链接器在处理目标文件时,须要对目标文件中某些部位进行重定位,即代码段和数据段中那些对绝对地址的引用的位置。这些重定位的信息都记录在ELF文件的重定位表里面,对于每个须要重定位的代码段或数据段,都会有一个相应的重定位表。

“.data”段则没有对绝对地址的引用,它只包含了几个常量,所以hello.o中没有针对“.data”段的重定位表“.rel.data”

2.2、字符串表

常见的段名为“.strtab”或“.shstrtab”。这两个字符串表分别为字符串表(String Table)和段表字符串表(Section Header String Table)。

  • 字符串表用来保存普通的字符串,比如符号的名字;
  • 段表字符串表用来保存段表中用到的字符串,最常见的就是段名( sh_name )。

我们可以使用很多工具来查看ELF文件的符号表,比如readelf、objdump、nm等,比如使用“nm”来查看“hello.o”的符号结果如下

[dev1@localhost test01]$ nm hello.o
0000000000000000 D global_init_var
0000000000000004 C global_uninit_var
0000000000000021 T main
                 U printf
0000000000000000 T show
0000000000000004 d static_var.2183
0000000000000000 b static_var2.2184
[dev1@localhost test01]$

2.3、查看重定位表 和 字符串表

[dev1@localhost test01]$ readelf -a hello.o
ELF 头:
  Magic:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  类别:                              ELF64
  数据:                              2 补码,小端序 (little endian)
  版本:                              1 (current)
  OS/ABI:                            UNIX - System V
  ABI 版本:                          0
  类型:                              REL (可重定位文件)
  系统架构:                          Advanced Micro Devices X86-64
  版本:                              0x1
  入口点地址:              0x0
  程序头起点:              0 (bytes into file)
  Start of section headers:          984 (bytes into file)
  标志:             0x0
  本头的大小:       64 (字节)
  程序头大小:       0 (字节)
  Number of program headers:         0
  节头大小:         64 (字节)
  节头数量:         13
  字符串表索引节头: 12

节头:
  [] 名称              类型             地址              偏移量
       大小              全体大小          旗标   链接   信息   对齐
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000041  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  000002f8
       0000000000000048  0000000000000018   I      10     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000084
       0000000000000008  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  0000008c
       0000000000000004  0000000000000000  WA       0     0     4
  [ 5] .rodata           PROGBITS         0000000000000000  0000008c
       0000000000000004  0000000000000000   A       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  00000090
       000000000000002e  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000be
       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  000000c0
       0000000000000058  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  00000340
       0000000000000030  0000000000000018   I      10     8     8
  [10] .symtab           SYMTAB           0000000000000000  00000118
       0000000000000180  0000000000000018          11    11     8
  [11] .strtab           STRTAB           0000000000000000  00000298
       000000000000005d  0000000000000000           0     0     1
  [12] .shstrtab         STRTAB           0000000000000000  00000370
       0000000000000061  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

There are no section groups in this file.

本文件中没有程序头。

重定位节 '.rela.text' 位于偏移量 0x2f8 含有 3 个条目:
  偏移量          信息           类型           符号值        符号名称 + 加数
000000000011  00050000000a R_X86_64_32       0000000000000000 .rodata + 0
00000000001b  000e00000002 R_X86_64_PC32     0000000000000000 printf - 4
000000000036  000d00000002 R_X86_64_PC32     0000000000000000 show - 4

重定位节 '.rela.eh_frame' 位于偏移量 0x340 含有 2 个条目:
  偏移量          信息           类型           符号值        符号名称 + 加数
000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
000000000040  000200000002 R_X86_64_PC32     0000000000000000 .text + 21

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.

Symbol table '.symtab' contains 16 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    4 static_var2.2184
     7: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    3 static_var.2183
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    8 
    10: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
    11: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_init_var
    12: 0000000000000004     4 OBJECT  GLOBAL DEFAULT  COM global_uninit_var
    13: 0000000000000000    33 FUNC    GLOBAL DEFAULT    1 show
    14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
    15: 0000000000000021    32 FUNC    GLOBAL DEFAULT    1 main

No version information found in this file.
[dev1@localhost test01]$ 

六、调试信息

如果我们在GCC编译时加上“-g”参数,编译器就会在产生的目标文件里面加上调试信息,我们通过readelf等工具可以看到,目标文件里多了很多“debug”相关的段:

[dev1@localhost test01]$ gcc -c hello.c -o hello.o -g
[dev1@localhost test01]$ objdump -h hello.o

hello.o:     文件格式 elf64-x86-64

节:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000041  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  0000000000000000  0000000000000000  00000084  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000004  0000000000000000  0000000000000000  0000008c  2**2
                  ALLOC
  3 .rodata       00000004  0000000000000000  0000000000000000  0000008c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .debug_info   00000129  0000000000000000  0000000000000000  00000090  2**0
                  CONTENTS, RELOC, READONLY, DEBUGGING
  5 .debug_abbrev 000000a9  0000000000000000  0000000000000000  000001b9  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_aranges 00000030  0000000000000000  0000000000000000  00000262  2**0
                  CONTENTS, RELOC, READONLY, DEBUGGING
  7 .debug_line   00000041  0000000000000000  0000000000000000  00000292  2**0
                  CONTENTS, RELOC, READONLY, DEBUGGING
  8 .debug_str    00000119  0000000000000000  0000000000000000  000002d3  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .comment      0000002e  0000000000000000  0000000000000000  000003ec  2**0
                  CONTENTS, READONLY
 10 .note.GNU-stack 00000000  0000000000000000  0000000000000000  0000041a  2**0
                  CONTENTS, READONLY
 11 .eh_frame     00000058  0000000000000000  0000000000000000  00000420  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

参考
1、《程序员的自我修养链接装载与库》

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。