关于目标文件里的东西
另外这个也是读后感
目标文件是什么 在vs程序经过编译链接之后可以成为可执行文件 但是有没有想过 只编译不链接是什么 vs上要将编译和链接分开(我问了很多人都说不知道没办法只能在linux上实现只编译不链接)
写一段很简单的程序如果我在linux main.c文件中写下面这段代码
#include<stdio.h>
int add(int,int);//这个函数是表示两个数字相加 但是我不定义
int main()
{
int a=10;
int b=20;
printf("%d\n",add(a,b));
return 0;
}
在linux 上可以用 gcc -o main.c 来编译一下
会出现一个文件就是main.o 这个.o文件就是目标文件 目标文件分为4种 (可重定位文件在linux上为.o window下为obj ,可执行文件这个应该还是熟悉吧.exe,共享文件linux.so window .dll,核心转储文件(不知道什么文章不讲本人也不知道)ps书上就只这样介绍了一下 程序意外终止时,系统帮忙存一下终止时的信息)
就单说这个文件如果在linux 上就是.o文件 在window下也就是.obj文件
那么目标文件里面存储了什么 在linux上 可以用objdump -h main.o可以查看
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000052 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000088 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000088 2**2
ALLOC
3 .rodata 0000000a 00000000 00000000 00000088 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 0000002d 00000000 00000000 00000092 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 00000000 00000000 000000bf 2**0
CONTENTS, READONLY
这个时候就可以画一张图 这个里面只会列一写常用的段
等等 但是这个是不全的 信息都在ELEHeader头里面
所以我们得找文件头 readelf -h main.o
这些文件头记录了一个值为start of headers 272 也就是说这个段的起始位置存的就是个个段的信息
272的16进制110 这个就是段的起始位置
这个需要计算一下 用readelf -S main.o 就是段的信息
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000052 00 AX 0 0 4
[ 2] .rel.text REL 00000000 000390 000028 08 9 1 4
[ 3] .data PROGBITS 00000000 000088 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 000088 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 00000000 000088 00000a 00 A 0 0 1
[ 6] .comment PROGBITS 00000000 000092 00002d 01 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 00000000 0000bf 000000 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 0000bf 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 0002c8 0000b0 10 10 8 4
[10] .strtab STRTAB 00000000 000378 000018 00 0 0 1
就在.shstrtab 的下面bf +51=110
就在这个段的下面 里面存的所有段信息
再看其他的段symtab在段就是符号表放的段 也就是一个全局变量的符号的信息就放在这个里面
用readelf -s main.o小写的s
Symbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS main.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 6
8: 00000000 82 FUNC GLOBAL DEFAULT 1 main
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND fun
fun没有找到那么这个类型显示的就是UND 没有找到
一旦我们再链接了一个文件 然后就开始分配地址了 然后在.rel.text这个段里面进行符号的重定位 也就是段地址加上偏移量
如果没有找到这个文件也就无法分配地址没有分配地址那么就不会链接成功
其实做一个很简单的例子就是
即使是这个函数永远不会执行 他还是会报错 也就是在链接时期会报错
当你找到了这个符号那么在全局的符号表里面就会有这个符号然后进行重新定位 然后就可以运行了