著作一覧 |
一部のsoが実行できることはわかったが、実際に自分で作ってみようとしたら、結構、難しかった。
普通に作ってみるとsegvする。
いろいろ試してみたが、man gccやman ldしてオプションをいろいろ変えてみてもうまくいかない。たとえば、--pic-executableを見つけたときは「これだ」と思ったが、そうやって作ったsoを実行しようとすると、bashがNo such file or directoryと言いだす。
はて?
もちろん存在しているから、ダイナミックリンクの過程でファイルが見つからないと考えるのが筋だろう。
面倒になって検索してたら、gcc-helpにそのものずばりの「Executable shared object」というスレッドがあった。
どうやら、.interpセクションを作り、そこにldを指定するのがキモのようだ。
以下を作る。
/* hello.c */ #include <stdio.h> extern void exit(int); /* このシステムはx64 linuxで、ldは以下が使われている */ const char my_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux-x86-64.so.2"; int add_numbers(int argc, int* argv) { int i; int ret = 0; for (i = 0; i < argc; i++) { ret += *argv++; } return ret; } void hello_main(int argc, char* argv[]) { puts("hello world !"); exit(0); }
通常のexecutableのmainと異なりcランタイムによる初期化/クリーンアップがないため、このmain関数(上ではhello_main関数がそれにあたる。リンク時に-e(エントリーポイント指定)で関数名を指定する。下のリスト参照)はexit関数で抜ける必要がある(そうでないと実行後にsegvする)。
$ gcc -Wall -W -fPIC -shared -o libhello.so.1 hello.c -lc -Wl,-e,hello_main,-soname,libhello.so.1 hello.c:13: : unused parameter argc hello.c:13: : unused parameter argv $ ls -l libhello.so.1 -rwxr-xr-x 1 arton arton 9741 2009-10-27 01:41 libhello.so.1 $ ./libhello.so.1 hello world !
確かに実行可能なsoが作れた。
リンクできるか試す。
/* hmain.c */ #include <stdio.h> extern int add_numbers(int argc, int* argv); int main(int argc, char* argv[]) { int arg[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; printf("%d\n", add_numbers(sizeof(arg)/sizeof(arg[0]), arg)); return 0; }
コンパイル/リンクする。
$ ln -s libhello.so.1 libhello.so $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. $ gcc -c hmain.c $ gcc -L. hmain.o -lhello -lc -o hmain $ ./hmain 45
soとしても機能する。
ふつうのコンパイラをつくろう(青木 峰郎)上でsonameで埋め込んだりするのは、ふつパイラで学んだ方法。
ジェズイットを見習え |