第十周链接概述和目标文件格式
第1讲 可执行文件生成概述
可执行文件生成过程概述(21分钟)
链接器的由来(17分钟)
注意:静态链接需要包含所调用函数的代码,而动态链接不需要。
第2讲 目标文件格式概述
链接过程的本质(14分钟)
guangwudi@debian:~/csapp$ vim main.c
guangwudi@debian:~/csapp$ vim swap.c
guangwudi@debian:~/csapp$ gcc -O2 -g -o p main.c swap.c
guangwudi@debian:~/csapp$ ./p
目标文件的两种视图(16分钟)
第3讲 ELF可重定位目标文件
可重定位文件概述(10分钟)
ELF头和节头表(26分钟)
Usage: readelf <option(s)> elf-file(s)
Display information about the contents of ELF format files
Options are:
-a --all Equivalent to: -h -l -S -s -r -d -V -A -I
-h --file-header Display the ELF file header
-l --program-headers Display the program headers
--segments An alias for --program-headers
-S --section-headers Display the sections' header
--sections An alias for --section-headers
-g --section-groups Display the section groups
-t --section-details Display the section details
-e --headers Equivalent to: -h -l -S
-s --syms Display the symbol table
--symbols An alias for --syms
--dyn-syms Display the dynamic symbol table
--lto-syms Display LTO symbol tables
--sym-base=[0|8|10|16]
Force base for symbol sizes. The options are
mixed (the default), octal, decimal, hexadecimal.
-C --demangle[=STYLE] Decode mangled/processed symbol names
STYLE can be "none", "auto", "gnu-v3", "java",
"gnat", "dlang", "rust"
--no-demangle Do not demangle low-level symbol names. (default)
--recurse-limit Enable a demangling recursion limit. (default)
--no-recurse-limit Disable a demangling recursion limit
-U[dlexhi] --unicode=[default|locale|escape|hex|highlight|invalid]
Display unicode characters as determined by the current locale
(default), escape sequences, "<hex sequences>", highlighted
escape sequences, or treat them as invalid and display as
"{hex sequences}"
-n --notes Display the core notes (if present)
-r --relocs Display the relocations (if present)
-u --unwind Display the unwind info (if present)
-d --dynamic Display the dynamic section (if present)
-V --version-info Display the version sections (if present)
-A --arch-specific Display architecture specific information (if any)
-c --archive-index Display the symbol/file index in an archive
-D --use-dynamic Use the dynamic section info when displaying symbols
-L --lint|--enable-checks
Display warning messages for possible problems
-x --hex-dump=<number|name>
Dump the contents of section <number|name> as bytes
-p --string-dump=<number|name>
Dump the contents of section <number|name> as strings
-R --relocated-dump=<number|name>
Dump the relocated contents of section <number|name>
-z --decompress Decompress section before dumping it
-w --debug-dump[a/=abbrev, A/=addr, r/=aranges, c/=cu_index, L/=decodedline,
f/=frames, F/=frames-interp, g/=gdb_index, i/=info, o/=loc,
m/=macro, p/=pubnames, t/=pubtypes, R/=Ranges, l/=rawline,
s/=str, O/=str-offsets, u/=trace_abbrev, T/=trace_aranges,
U/=trace_info]
Display the contents of DWARF debug sections
-wk --debug-dump=links Display the contents of sections that link to separate
debuginfo files
-P --process-links Display the contents of non-debug sections in separate
debuginfo files. (Implies -wK)
-wK --debug-dump=follow-links
Follow links to separate debug info files (default)
-wN --debug-dump=no-follow-links
Do not follow links to separate debug info files
--dwarf-depth=N Do not display DIEs at depth N or greater
--dwarf-start=N Display DIEs starting at offset N
--ctf=<number|name> Display CTF info from section <number|name>
--ctf-parent=<name> Use CTF archive member <name> as the CTF parent
--ctf-symbols=<number|name>
Use section <number|name> as the CTF external symtab
--ctf-strings=<number|name>
Use section <number|name> as the CTF external strtab
--sframe[=NAME] Display SFrame info from section NAME, (default '.sframe')
-I --histogram Display histogram of bucket list lengths
-W --wide Allow output width to exceed 80 characters
-T --silent-truncation If a symbol name is truncated, do not add [...] suffix
@<file> Read options from <file>
-H --help Display this information
-v --version Display the version number of readelf
#include <stdio.h>
int main()
{
printf("guangfuzhonghua!\n");
return 0;
}
guangwudi@debian:~/csapp$ readelf -h hello.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 660 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 15
Section header string table index: 14
-S
輸出節頭表
guangwudi@debian:~/csapp$ readelf -S hello.o
There are 15 section headers, starting at offset 0x294:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .group GROUP 00000000 000034 000008 04 12 6 4
[ 2] .text PROGBITS 00000000 00003c 00003c 00 AX 0 0 1
[ 3] .rel.text REL 00000000 0001e0 000020 08 I 12 2 4
[ 4] .data PROGBITS 00000000 000078 000000 00 WA 0 0 1
[ 5] .bss NOBITS 00000000 000078 000000 00 WA 0 0 1
[ 6] .rodata PROGBITS 00000000 000078 000011 00 A 0 0 1
[ 7] .text.__x86.[...] PROGBITS 00000000 000089 000004 00 AXG 0 0 1
[ 8] .comment PROGBITS 00000000 00008d 000020 01 MS 0 0 1
[ 9] .note.GNU-stack PROGBITS 00000000 0000ad 000000 00 0 0 1
[10] .eh_frame PROGBITS 00000000 0000b0 000060 00 A 0 0 4
[11] .rel.eh_frame REL 00000000 000200 000010 08 I 12 10 4
[12] .symtab SYMTAB 00000000 000110 000090 10 13 5 4
[13] .strtab STRTAB 00000000 0001a0 00003f 00 0 0 1
[14] .shstrtab STRTAB 00000000 000210 000082 00 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),
D (mbind), p (processor specific)
-s
輸出符號表
guangwudi@debian:~/csapp$ readelf -s hello.o
Symbol table '.symtab' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS hello.c
2: 00000000 0 SECTION LOCAL DEFAULT 2 .text
3: 00000000 0 SECTION LOCAL DEFAULT 6 .rodata
4: 00000000 0 SECTION LOCAL DEFAULT 7 .text.__x86.get_[...]
5: 00000000 60 FUNC GLOBAL DEFAULT 2 main
6: 00000000 0 FUNC GLOBAL HIDDEN 7 __x86.get_pc_thunk.ax
7: 00000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
8: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
第4讲 ELF可执行目标文件
可执行文件概述(13分钟)
guangwudi@debian:~/csapp$ readelf -h hello
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x1060
Start of program headers: 52 (bytes into file)
Start of section headers: 13784 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 11
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 29
程序头表和存储器映像(21分钟)
guangwudi@debian:~/csapp$ readelf -l hello
Elf file type is DYN (Position-Independent Executable file)
Entry point 0x1060
There are 11 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x00160 0x00160 R 0x4
INTERP 0x000194 0x00000194 0x00000194 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x00000000 0x00000000 0x003d4 0x003d4 R 0x1000
LOAD 0x001000 0x00001000 0x00001000 0x001e0 0x001e0 R E 0x1000
LOAD 0x002000 0x00002000 0x00002000 0x00118 0x00118 R 0x1000
LOAD 0x002ee8 0x00003ee8 0x00003ee8 0x00128 0x0012c RW 0x1000
DYNAMIC 0x002ef0 0x00003ef0 0x00003ef0 0x000f0 0x000f0 RW 0x4
NOTE 0x0001a8 0x000001a8 0x000001a8 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x00201c 0x0000201c 0x0000201c 0x00034 0x00034 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x002ee8 0x00003ee8 0x00003ee8 0x00118 0x00118 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt
03 .init .plt .plt.got .text .fini
04 .rodata .eh_frame_hdr .eh_frame
05 .init_array .fini_array .dynamic .got .got.plt .data .bss
06 .dynamic
07 .note.gnu.build-id .note.ABI-tag
08 .eh_frame_hdr
09
10 .init_array .fini_array .dynamic .got
第十周小测验
1以下是有关使用GCC生成C语言程序的可执行文件的叙述,其中错误的是(D )。
A.第三步汇编,将汇编语言代码汇编转换为机器指令表示的机器语言代码
B.第四步链接,将多个模块的机器语言代码链接生成可执行目标程序文件
C.第一步预处理,对#include、#define、#ifdef等预处理命令进行处理
D.第二步编译,将预处理结果编译转换为二进制形式的汇编语言程序代码
解釋:第二步编译,将预处理结果编译转换为文本形式的汇编语言程序代码
2以下是有关使用GCC生成C语言程序的可执行文件的叙述,其中错误的是(B )。
A.预处理的结果还是一个C语言源程序文件,属于可读的文本文件
B.只要在链接命令中指定所有的相关可重定位目标文件就能生成可执行文件
C.经过预处理、编译和汇编处理的结果是一个可重定位目标文件
D.每个C语言源程序文件生成一个对应的可重定位目标文件
解释:只要……就……
3以下是有关链接所带来的好处和不足的叙述,错误的是( A )。
A.使得所生成的可执行目标代码中包含了更多公共库函数代码,所占空间大
B.使得公共函数库可以为所有程序共享使用,有利于代码重用和提高效率
C.使得程序员仅需重新编译修改过的源程序模块,从而节省程序开发时间
D.使得程序员可以分模块开发程序,有利于提高大规模程序的开发效率
解释:所生成的可执行目标代码不包含公共库函数代码
4以下关于ELF目标文件格式的叙述中,错误的是( D )。
A.可重定位和可执行两种目标文件中的代码都是二进制表示的指令形式
B.可执行目标文件是ELF格式的执行视图,由不同的段组成
C.可重定位目标文件是ELF格式的链接视图,由不同的节组成
D.可重定位和可执行两种目标文件中的数据都是二进制表示的补码形式
解释:可重定位和可执行两种目标文件中的数据都是十六进制表示的补码形式
5以下关于链接器基本功能的叙述中,错误的是( C )。
A.将每个.o文件中的.data节、.text节和.bss节合并
B.根据所定义符号的首地址对符号的引用进行重定位
C.确定每个符号(包括全局变量和局部变量)的首地址
D.将每个符号引用与唯一的一个符号定义进行关联
解释:局部变量不属于符号定义
6以下关于可重定位目标文件的叙述中,错误的是( B )。
A.在.rodata节中包含相应模块内所有只读数据
B.在.data节中包含相应模块内所有变量的初始值
C.在.rel.text节和.rel.data节中包含相应模块内所有可重定位信息
D.在.text节中包含相应模块内所有机器代码
解释:.data节只包括已初始化的全局变量或静态局部变量,不包括已初始化的非静态局部变量和未初始化的变量。
7以下关于ELF目标文件的ELF头的叙述中,错误的是( D )。
A.数据结构在可重定位和可执行两种目标文件中完全一样
B.包含了节头表和程序头表各自的起始位置和长度
C.包含了操作系统版本和机器结构类型等信息
D.包含了ELF头本身的长度和目标文件的长度
解释:不包含目标文件的长度
8以下关于ELF目标文件的节头表的叙述中,错误的是( B )。
A.通过节头表可获得节的名称、类型、起始地址和长度
B.每个表项用来记录某个节的内容以及相关描述信息
C.数据结构在可重定位和可执行两种目标文件中完全一样
D.描述了每个可装入节的起始虚拟地址、对齐和存取方式
解释:没有记录某个节的内容
9以下关于ELF可重定位和可执行两种目标文件格式比较的叙述中,错误的是( B )。
A.可执行目标文件的ELF头中有具体程序入口地址,而在可重定位目标文件中则为0
B.可重定位目标文件中有初始化程序段.init节,而在可执行目标文件中则没有
C.可执行目标文件中有程序头表(段头表),而在可重定位目标文件中则没有
D.可重定位目标文件中有可重定位节.rel.text和.rel.data,而在可执行目标文件中则没有
解释:可执行目标文件中有初始化程序段.init节,而可重定位目标文件中没有
10以下关于ELF可执行目标文件的程序头表(段头表)的叙述中,错误的是( C )。
A..text节和.rodata节都包含在只读代码段,而.data节和.bss节都包含在读写数据段
B.通过段头表可获得可装入段或特殊段的类型、在文件中的偏移位置及长度
C.用于描述可执行文件中的节与主存中的存储段之间的映射关系
D.描述了每个可装入段的起始虚拟地址、存储长度、存取方式和对齐方式
解释:ELF可执行目标文件的程序头表(段头表)用于描述可执行文件中的节与虚拟空间中的存储段之间的映射关系