elf格式的可执行文件和可重定位文件有什么区别?

时间:2014-07-09 14:03:19

标签: elf

elf格式的可执行文件和elf格式的可重定位文件有什么区别?

4 个答案:

答案 0 :(得分:12)

从下图中可以看出,可重定位的ELF作为链接器的输入,而可执行的ELF是链接器的产品。

Freescale SC100 development tools example diagram

答案 1 :(得分:6)

如您所知,每个编译的可执行文件都是具有地址相对和绝对的二进制文件,因此可重定位格式是一种格式,其中函数和其他符号在其他字函数中仍然有名称定义,并且变量不绑定到任何特定地址。相反,地址仍然是符号

看:

unix > gcc -c main.c
unix > readelf --symbols main.o
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   OBJECT    GLOBAL   DEFAULT     3    buf
  3:  00000000      0   OBJECT    GLOBAL   DEFAULT     1    main

unix > gcc main.c -o main
unix > readelf --symbols main
Num:     Value   Size     Type      Bind       Vis     Ndx  Name
 53:  08048460      2     FUNC    GLOBAL   DEFAULT     13   __libc_csu_fini
 54:  08048462      0     FUNC    GLOBAL   HIDDEN      13   __i686.get_pc_thunk.bx
 55:  0804a018      4     OBJECT  GLOBAL   DEFAULT     13   bufp0

你看到我在说什么

大多数时候我们将它们用作静态库

查看此处的示例:

#ifndef MATH_H
#define MATH_H
int add(int a, int b);
#endif

/* math_test.c */
#include <stdio.h>
#include "math.h"

int main(void)
{
  int result = add(1, 2);
  printf("result: %d\n", result);
  return 0;
}

尝试编译它

unix > gcc math_test.c -o math_test
/tmp/cclRibQq.o: In function `main':
math_test.c:(.text+0x19): undefined reference to `add'
collect2: ld returned 1 exit status

由于函数addmath_test.c中没有正文,所以我们可以做到流动:

int add(int a, int b)
{
  return a + b;
}

然后使用gcc将其编译为可重定位

unix > gcc -c math.c                      # Create relocatable obj file (math.o)
unix > readelf -h math.o | grep Type      # Read math.o with readelf
Type:            REL (Relocatable file)   # and verify its type

然后您可以将它与链接器链接,如下所示:

unix > gcc math_test.c math.o -o math_test
unix > ./math_test
result: 3

一篇很棒的文章,关于elf格式的可执行文件和elf格式的可重定位文件之间的区别,你可以找到here

答案 2 :(得分:5)

ELF可执行文件,正如我们可以从其名称中理解的那样,是一个可以执行的文件。例如,可以从C代码生成此文件。

重定位过程是修复代码中创建的标签和符号的地址。例如,如果您使用汇编语言编写程序并查看源代码的列表文件,则会找到一些写入[00000000]的位置而不是此行中提到的标签。这个零表示链接器使用重定位来修复地址的未来值。

答案 3 :(得分:5)

Relocatable没有任何Load地址,它只有带偏移量的二进制代码序列(例如与main()func相关的偏移量)。但是,具有加载地址的可执行文件不仅仅与任何函数相关的偏移。

它们之间的另一个根本区别是Executable有bootstrap应用程序,但是可重定位没有它。