gccでコンパイルされたCプログラムのエントリポイントを変更するにはどうすればよいですか?
次のコードのように
#include<stdio.h>
int entry() //entry is the entry point instead of main
{
return 0;
}
gccでコンパイルされたCプログラムのエントリポイントを変更するにはどうすればよいですか?
次のコードのように
#include<stdio.h>
int entry() //entry is the entry point instead of main
{
return 0;
}
これはリンカー設定です:
-Wl,-eentry
物事はリンカに引数を渡し、-Wl,...
リンカは-e
エントリ関数を設定するために引数を取ります
ソースコードは次のように変更できます。
#include<stdio.h>
const char my_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
int entry() //entry is the entry point instead of main
{
exit(0);
}
「.interp」セクションを使用すると、プログラムで外部共有ライブラリを呼び出すことができます。exit呼び出しは、returnではなくexitプログラムへのエントリ関数を作成します。
次に、実行可能な共有ライブラリとしてプログラムをビルドします。
$ gcc -shared -fPIC -e entry test_main.c -o test_main.so
$ ./test_main
GNU Binutils(Linuxなど)を提供するシステムを使用している場合は、このobjcopy
コマンドを使用して、任意の関数を新しいエントリポイントにすることができます。
関数program.c
を含むと呼ばれるファイルを想定します。entry
$ cat > program.c
#include <stdio.h>
int entry()
{
return 0;
}
^D
まず、を使用してコンパイルし-c
、再配置可能なオブジェクトファイルを生成します。
$ gcc -c program.c -o program.o
次に、次のように再定義entry
しますmain
。
$ objcopy --redefine-sym entry=main program.o
次に、gccを使用して新しいオブジェクトファイルをコンパイルします。
$ gcc program.o -o program
注:プログラムにすでに「」という関数がある場合は、手順2の前に、別の呼び出しmain
を実行できます。objcopy
objcopy --redefine-sym oldmain=main program.o
最小限の実行可能な例と他の回答に関する注記
main.c
#include <stdio.h>
#include <stdlib.h>
int mymain(void) {
puts("hello");
exit(0);
}
コンパイルして実行します。
gcc -nostartfiles -Wl,--entry=mymain -o main.out main.c
# or -Wl,-emymain
./main.out 1 2 3
注釈:
がない-nostartfiles
と、リンクは次のように失敗します。
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
おそらく、mainの前に実行されるglibcセットアップコードが_start
通常はを呼び出すためmain
です。
コマンドライン引数は設定されていません。おそらく、mainの前に実行されるglibcコードによって設定されるため、これらを使用しようとすると、未定義の値が出力されます。私は彼らのために働く方法を見つけていません。
Ubuntu20.10でテスト済み。