关于目标文件里的东西

来源:互联网 发布:mac 局域网ip 编辑:程序博客网 时间:2024/06/10 05:04

另外这个也是读后感 

目标文件是什么 在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这个段里面进行符号的重定位 也就是段地址加上偏移量 

如果没有找到这个文件也就无法分配地址没有分配地址那么就不会链接成功 

其实做一个很简单的例子就是

即使是这个函数永远不会执行 他还是会报错 也就是在链接时期会报错 

当你找到了这个符号那么在全局的符号表里面就会有这个符号然后进行重新定位 然后就可以运行了


原创粉丝点击