读书-程序员的自我修养-链接、封装与库(7: 第三章:目标文件里有什么(2)readelf,链接的本质,符号/表,extern “C“,强/弱符号

6: 第三章:目标文件里有什么(1) 参考上个博客
https://blog.csdn.net/lqy971966/article/details/100068205

1. ELF文件结构描述

在这里插入图片描述

1.1 readelf -h simple.o

root@ubuntu-admin-a1:/home# readelf -h simple.o

ELF Header:
Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
Class:                             ELF64
Data:                              2's complement, little endian
Version:                           1 (current)
OS/ABI:                            UNIX - System V
ABI Version:                       0
Type:                              REL (Relocatable file)
Machine:                           Advanced Micro Devices X86-64
Version:                           0x1
Entry point address:               0x0
Start of program headers:          0 (bytes into file)
Start of section headers:          1056 (bytes into file)
Flags:                             0x0
Size of this header:               64 (bytes)
Size of program headers:           0 (bytes)
Number of program headers:         0
Size of section headers:           64 (bytes)
Number of section headers:         13
Section header string table index: 10
root@ubuntu-admin-a1:/home#

1.1.1 ELF头文件说明

ELF的文件头中定义了ELF魔数,文件机器字节长度,数据存储方式,版本,平台,ABI版本,硬件版本/平台,入口地址,程序头入口和长度,段表的位置/长度/数量等。

1.2 readelf 命令

  1. 功能
    用于显示elf格式文件的信息
  2. 参数-h
    –file-header 显示elf文件开始的文件头信息.
    //查看文件头信息
    readelf -h [file]
  3. 参数-d
    readelf -d [file]
    //查看文件依赖的动态库
  4. 参数-S
    //查看文件中的符号
    readelf -s [file]
  5. -S
    –section-headers ;
    –sections 显示节头信息

1.3 readelf -S simple.o 查看各个段

root@ubuntu-admin-a1:/home# readelf -S simple.o
There are 13 section headers, starting at offset 0x420:

Section Headers:
[Nr] Name              Type             Address           Offset
	Size              EntSize          Flags  Link  Info  Align
[ 0]                   NULL             0000000000000000  00000000
	0000000000000000  0000000000000000           0     0     0
[ 1] .text             PROGBITS         0000000000000000  00000040
	0000000000000057  0000000000000000  AX       0     0     1
[ 2] .rela.text        RELA             0000000000000000  00000310
	0000000000000078  0000000000000018   I      11     1     8
[ 3] .data             PROGBITS         0000000000000000  00000098
	0000000000000008  0000000000000000  WA       0     0     4
[ 4] .bss              NOBITS           0000000000000000  000000a0
	0000000000000004  0000000000000000  WA       0     0     4
[ 5] .rodata           PROGBITS         0000000000000000  000000a0
	0000000000000004  0000000000000000   A       0     0     1
[ 6] .comment          PROGBITS         0000000000000000  000000a4
	0000000000000035  0000000000000001  MS       0     0     1
[ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000d9
	0000000000000000  0000000000000000           0     0     1
[ 8] .eh_frame         PROGBITS         0000000000000000  000000e0
	0000000000000058  0000000000000000   A       0     0     8
[ 9] .rela.eh_frame    RELA             0000000000000000  00000388
	0000000000000030  0000000000000018   I      11     8     8
[10] .shstrtab         STRTAB           0000000000000000  000003b8
	0000000000000061  0000000000000000           0     0     1
[11] .symtab           SYMTAB           0000000000000000  00000138
	0000000000000180  0000000000000018          12    11     8
[12] .strtab           STRTAB           0000000000000000  000002b8
	0000000000000054  0000000000000000           0     0     1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
root@ubuntu-admin-a1:/home# 

1.3.1 simple.o 各个段位置图

在这里插入图片描述

1.3.2 .rel.text 重定位表

代码中需要重定位的代码段和数据段,存放在这里。

1.3.3 .strtab/.shstrtab 字符串表

把ELF文件中的很多字符串,比如段名,变量名存放在这里

2. 链接的接口-符号

2.1 链接的本质

  1. 链接的本质:
    把多个不同的目标文件之间相互粘到一起。
  2. 目标文件直接相互拼合实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用。

2.2 符号

  1. 符号(Symbol):我们将函数和变量统称为符号。
    表示一个地址,这个地址可以是一段子程序/函数,也可以是一个变量的起始地址。
  2. 符号表(Symbol Table):一个目标文件中所有符号的集合。
  3. 符号名(Symbol Name):函数名或变量名就是符号名。
  4. 符号值(Symbol Value): 符号(函数名或变量名)的地址

链接的过程:有一部分是符号的管理,每一个目标文件都会有一个相应的符号表(Symbol Table),这个表里面记录了目标文件中所用到的所有符号。

2.3 .symtab 符号表

它是ELF文件中的一个段。
它的结构很简单,是一个Elf32_Sym结构的数组。

2.4 readelf -s simple.o 查看符号表

root@ubuntu-admin-a1:/home# readelf -s simple.o

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 simple.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: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    3 iStaticVar.2290
	7: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    4 iStaticVar2.2291
	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 g_init_var
	12: 0000000000000004     4 OBJECT  GLOBAL DEFAULT  COM g_uinit_var
	13: 0000000000000000    34 FUNC    GLOBAL DEFAULT    1 func1
	14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
	15: 0000000000000022    53 FUNC    GLOBAL DEFAULT    1 main
root@ubuntu-admin-a1:/home# 

在这里插入图片描述

2.5 符号修饰

2.5.1 UNIX规范:

为了防止符号名重名冲突,UNIX规定C语言下的所有全局变量和函数经过编译后,符号钱加上_下划线,如 _foo

2.5.2. C++符号修饰和符号改编

2.5.3. 函数签名(Function Signature):

函数签名包含一个函数的信息,包括函数名,参数类型,名称空间等信息。
如: int C::func(int) -> _ZN1C4funcEi

2.5.4. extern “C”

C++代码调用C代码
C++编译器会将extern "C"的大括号内部的代码当作C语言代码处理。
所以C++代码的名称修饰将不起作用。

2.5.5. __cplusplus

判断当前编译单元是不是c++代码
C++编译器会在编译C++的程序的时候默认定义这个宏。
这个宏判断当前编译器是不是C++。

2.5.6 强符号和弱符号

编译器默认函数和初始化了的全局变量为强符号。
未初始化的全局变量为弱符号。
在这里插入图片描述

5. 调试信息 objdump -h debug_simple.o

root@ubuntu-admin-a1:/home# objdump -h debug_simple.o

debug_simple.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
……
……
27 .debug_aranges 00000030  0000000000000000  0000000000000000  00001074  2**0
				CONTENTS, READONLY, DEBUGGING
28 .debug_info   0000012c  0000000000000000  0000000000000000  000010a4  2**0
				CONTENTS, READONLY, DEBUGGING
29 .debug_abbrev 0000009c  0000000000000000  0000000000000000  000011d0  2**0
				CONTENTS, READONLY, DEBUGGING
30 .debug_line   00000043  0000000000000000  0000000000000000  0000126c  2**0
				CONTENTS, READONLY, DEBUGGING
31 .debug_str    000000e7  0000000000000000  0000000000000000  000012af  2**0
				CONTENTS, READONLY, DEBUGGING
root@ubuntu-admin-a1:/home# 

6. 相关的linux命令

6.1 file

file 命令 显示文件类型

6.2 objdump

objdump 查看目标文件内部结构,-h-s-d\

6.3 size

size用来查看ELF文件的代码段、数据段和BSS

7 句子

  1. 很多问题在表面上看似很简单,其实深入内部会发现很多鲜为人知的秘密,或者发现以前自己认为理所当然的 居然是错误的,或者是有偏差的。
  2. 真正了不起的程序员对自己的程序的每一个字节都了如指掌。
  3. 马屁股决定航天飞机

参考

https://blog.csdn.net/yasi_xi/article/details/45197583

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值