elf格式的可执行文件和elf格式的可重定位文件有什么区别?
答案 0 :(得分:12)
从下图中可以看出,可重定位的ELF作为链接器的输入,而可执行的ELF是链接器的产品。
答案 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
由于函数add
在math_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应用程序,但是可重定位没有它。