Elf形式の実行可能ファイルとelf形式の再配置可能ファイルの違いは何ですか?
下の画像に示されているように、再配置可能なELFはリンカーへの入力として使用されますが、実行可能なELFはリンカーの製品です。
ご存知のように、コンパイルされたすべての実行可能ファイルは相対アドレスと絶対アドレスを持つバイナリファイルであるため、再配置可能形式は、関数や他のシンボルに他のWord関数での名前定義があり、変数が特定のアドレスにバインドされていない形式です。代わりに、アドレスはまだシンボルです
見て:
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形式の再配置可能ファイルの違いに関するすばらしい記事 ここ
Relocatableには、オフセット付きの唯一のバイナリコードシーケンス(たとえば、main()関数に関連するオフセット)のロードアドレスがありません。ただし、関数のいずれかに関連するオフセットだけでなく、ロードアドレスを持つ実行可能ファイル。
それらの間のもう1つの基本的な違いは、Executable have bootstrap applicationですが、relocatableにはありません。
ELF実行可能ファイルは、その名前から理解できるように、実行可能なファイルです。このファイルは、たとえばCコードから生成できます。
再配置のプロセスは、コードで作成されたラベルとシンボルのアドレスを修正することです。たとえば、アセンブリ言語でプログラムを作成し、ソースコードのリストファイルを見ると、この行に記載されているラベルの代わりに[00000000]が記述されている場所がいくつかあります。このゼロは、リンカーがアドレスをその将来の値に固定するために再配置を使用することを意味します。