Linker && Loader
■ このスレッドは過去ログ倉庫に格納されています
0001さとし ◆k4PcAe16
NGNG難しいような気がするんですが。。。
僕もリンカとローダを作れるようになれますか?
0133デフォルトの名無しさん
NGNG共立出版の雑誌"bit"は、
大学の図書館(工学系)行けば必ずある。
0134デフォルトの名無しさん
NGNG良い奴等はみんな氏んじまった。
0135デフォルトの名無しさん
NGNG文系PGにはTransTechみたいな雑誌が丁度いいかと
思えたけど、あれも直ぐ潰れちゃったよね。
結局コボラー相手の雑誌しか生きのこれないということか。
0136592 ◆m/EAH1Sb4Q
NGNG>>130
>ttp://www.borland.co.jp/bcsuite/tc40j.html
>ここのVROOMMというのは違うのかな?
そうかもしれませんが、どうやってるのか知ることができません。Borlandの独自技術かな?
>>131
>loaderなかったら、program実行できないじゃない。
それはそうですけど、loaderやlinkerに関しての理論や説明が無いってことでした。
>>132
>人がやるかソフトウェアがやるかは環境によるよね。
>オーバーレイだから、組み込み系の人に聞くんがいいんじゃない?
>GCCスレに書いたけど、それやるアセンブラ、リンカ使ったことあるよ。
>大型で動いていたHLISPってLispの処理系も自分でやってたね。
>アドレス空間が狭かったからね。
なるほど、ありがとうございます。
うーむ、どうも最近それほどオーバーレイにこだわる必要はないんじゃないかって気がしてきました。
使用範囲が限られてるようだし..だから次の章に進んでます。
>>133
>共立出版の雑誌"bit"は、
>大学の図書館(工学系)行けば必ずある。
学生ではないんですが、一般の人でも入れるんですか?
0137デフォルトの名無しさん
NGNGゼロから全てのソフトを書き上げる能力を、皆が持っていた
時代から比べれば、今のPGはアホウの集まりのようだ。
原始人て、もの凄く頭悪そうなイメージがあるけど、実はかなり
賢い生き物だったのかもしれないね。生きるための創意工夫を
独自に発案できない椰子は生きていけない世界だったのかもしれない。
0138592 ◆m/EAH1Sb4Q
NGNG>文明が発達すると、人の能力も落ちてくるんじゃないのかな。
>ゼロから全てのソフトを書き上げる能力を、皆が持っていた
>時代から比べれば、今のPGはアホウの集まりのようだ。
>原始人て、もの凄く頭悪そうなイメージがあるけど、実はかなり
>賢い生き物だったのかもしれないね。生きるための創意工夫を
>独自に発案できない椰子は生きていけない世界だったのかもしれない。
そうですね。
人間って弱い生き物なので、一度うまくやってしまうとだんだんと楽をしようとしてしまって、
楽な方へ楽な方へと流されてしまう。
そして気づいたらそれをどうやってすればいいのか、どうなっているのかすらわからなくなってしまっている。
こういうことが最近多くなってきているような気がします。>我も
0139デフォルトの名無しさん
NGNGFORTRANのCOMMONは知っていますか?
これが現在最大派閥のオーバーレイじゃないかな。
それから大学の図書館で外部の人を入れないところなんてほとんどないよ。
大学の目的に反しているからね。身分証明書があればほとんどOK。
貸し出しはしてくれなくても有料コピーサービスは受けられる。
OPACで在庫図書を検索できるし。
気をつけるのは、学科の図書室は入れないことが多いこと。
0140592 ◆m/EAH1Sb4Q
NGNG>FORTRANのCOMMONは知っていますか?
>これが現在最大派閥のオーバーレイじゃないかな。
残念ながら、自分はFORTRANは使用したことがありません。
>それから大学の図書館で外部の人を入れないところなんてほとんどないよ。
>大学の目的に反しているからね。身分証明書があればほとんどOK。
>貸し出しはしてくれなくても有料コピーサービスは受けられる。
>OPACで在庫図書を検索できるし。
>気をつけるのは、学科の図書室は入れないことが多いこと。
わざわざ、知らせてくれてすいません。
そこ大学の学生でなければ見れないと思ってました。
後で気づいたんですけど国会図書館を使うっていう手段もあるなと思いました。
現在は、10章「動的なリンクとロード」を読み終えて、11章へ突入。
10章は、中々面白かったです。一番身近な感覚で勉強できますからね。
今日中に終わるか!?
0141592 ◆m/EAH1Sb4Q
NGNG最後は、Javaでした。ちょこっとしかなかったけど無いよりましか。
全てをざっと読んだ感想は、やはり一筋縄にはいかないものだと思った。
Linker、Loaderを詳細に分かりたい人はこの本だけでなく、
その他の書籍、Web、ソース参照等でカバーしなくてはいけないと思う。
自分もこれからいろいろと調べなくてはならないことが山程あるなと感じた。
0142デフォルトの名無しさん
NGNGをリンクする事は出来ないのでしょうか?
新規作成分のa.o b.o c.o と既存の流用可能な hoge.a があった
時に、a.o, b.o, c.o, hoge.a から libHoge.so を作りたいのですが、
どうしても hoge.a をリンクしても libHoge.soにシンボルがリンク
されません。
0143デフォルトの名無しさん
NGNG*.aはそうなっていないので、*.soに取り込むことはできない。
arで*.oにばらしてもダメ。
外部シンボルへの参照方法が根本的に違う。
0144デフォルトの名無しさん
NGNGそれはつまり、再配置可能な形態(EXE,DLL)と
オブジェクトファイルの違いということですか?
*.aというのは用はオブジェクトファイルの集合体ですよね。
オブジェクトファイル内のアドレス値は、ファイルイメージ内の
相対アドレスすら決定されていない(リンク時にそれは決定される)から。
逆に(EXE,DLL)は、ローダによって実行時に、各セクションごとメモリ上に
割り当てられるとしても、それはオブジェクトファイル形式にのっとった
操作だから、先頭から何バイト目かは分る。つまり相対アドレスが
決定できる。EXEはプロセス中に一つしか有り得ないから、
DLLとはまた少し事情が違うのかな。
0145デフォルトの名無しさん
NGNGLinux って *.a から *.so つくるよね?
ld -shared --whole-archive とかって...
0146デフォルトの名無しさん
NGNGgccの-fpicを調べてください。
>>143の最後の一行の意味がわかるかと。
0147145
NGNGんー、私が知りたいのは
>143 で
「*.aはそうなっていないので、*.soに取り込むことはできない。arで*.oにばらしてもダメ。」
って言ってるけど、-fpic とか -fPIC でコンパイルしててもダメ(ar で *.o にバラしてもダメ)なの?
なんか -fpic とか -fPIC つきでコンパイルしてたら、ar で *.o にバラしてそれから *.so に取り込めそうだけど...
0148デフォルトの名無しさん
NGNGただ、普通は.aだけ作る場合に-fpic付けることはまず無い。
0150デフォルトの名無しさん
NGNG0151デフォルトの名無しさん
NGNG0153デフォルトの名無しさん
NGNG0154デフォルトの名無しさん
NGNG-lhoge とやった際、そのパスに、libhoge.a と libhoge.so の両方が
あった場合、どちらがリンクされるんでしょうか?
またlibhoge.aがリンクされる場合は、静的ライブラリの動的リンクって
事になるんでしょうか?
0156デフォルトの名無しさん
NGNGコードがPICでなくともTEXTRELを処理すれば普通に動きそうだけど。
0157デフォルトの名無しさん
NGNG0158デフォルトの名無しさん
NGNG0159デフォルトの名無しさん
NGNGディスパッチテーブル。
0160デフォルトの名無しさん
NGNG書き換えたらプロセス間で共有出来なくなるが。
そういやWinのDLLって再配置できるけど、あれってメモリ上では共有されないの?
0161デフォルトの名無しさん
NGNG0162デフォルトの名無しさん
NGNGエクスポートする関数やグローバル変数なんじゃなくて、
モジュール内で参照してる、外部シンボルのことなんだよね?
実際、-fPICや-sharedつけても、外部シンボルを一切参照しない
コードなら、readelf -a foo.oの結果が全く同じだし。
0163デフォルトの名無しさん
NGNG内部のみ有効なシンボルであっても絶対番地参照してはならない。
そうして初めて外部シンボルだけ問題なモジュールとなる。
0164デフォルトの名無しさん
NGNGオオボケかましてました。自動変数だけのプログラム書いてました(汗
モジュールローカルなstatic変数とそれを用いるプログラム(宣言だけでは
もちろんダメ)を書いたら、-fPICの有無で、ちゃんとreadelf -aにおいて
異なる結果が得られました。何が違うのかはこれからよく見てみますが。
0165164
NGNGstatic int abc=2;
int foo(void){int i=abc;}
$gcc -c foo.c;readelf -a foo.o > nopic.txt;gcc -c foo.c -fPIC;readelf -a foo.o > pic.txt
$diff nopic.txt pic.txt
いろいろあるけどとりあえず、セクションごとのサイズに注目すると、
< [ 1] .text PROGBITS 00000000 000034 000010 00 AX 0 0 4
< [ 2] .rel.text REL 00000000 0002b0 000008 08 7 1 4
< [ 7] .symtab SYMTAB 00000000 000200 000090 10 8 8 4
< [ 8] .strtab STRTAB 00000000 000290 00001e 00 0 0 1
----
> [ 1] .text PROGBITS 00000000 000034 000024 00 AX 0 0 4
> [ 2] .rel.text REL 00000000 0002e8 000010 08 7 1 4
> [ 7] .symtab SYMTAB 00000000 000214 0000a0 10 8 8 4
> [ 8] .strtab STRTAB 00000000 0002b4 000034 00 0 0 1
この辺りかな。
・.rel.textのエントリが1 -> 2、.symtabが9 -> 10になってる。
・エントリのサイズは.rel.textが8バイト、.symtab16バイト。
・それぞれ、_GLOBAL_OFFSET_TABLE_という名前のエントリが増えてる。
ってな感じですかね。
0166デフォルトの名無しさん
NGNG> 書き換えたらプロセス間で共有出来なくなるが。
勿論そうだけど、動くには動くでしょ。
PICでない*.aを*.soに取り込めないのは不思議。
>>165
shared objectは利用するプロセス毎に違うアドレスへ配置され得る。
だからコード中で直接絶対番地指定するとその部分を再配置しない限り
正常に動作してくれない。
で、再配置(=ここでは読み取り専用領域の書き換え)をしてしまうと>>160にある通り
メモリの共有が出来なくなって、プロセス毎にコピーを持つ必要が出来る。
PICなコードでは絶対番地指定が必要な時に
Global Offset Table(GOT)を通して間接的にアクセスする。
これだと読み取り専用領域を書き換える必要が無くなるので、
異なるプロセス間でその領域を共有出来るようになる。
i386ではGOTの参照に_GLOBAL_OFFSET_TABLE_という名前を使う事が出来る。
因みにdynamic linkerを通して関数を呼び出す時は
Procedure Linkage Table(PLT)ってのが使われる。
i386ではPLTはGOTを参照する変則的なジャンプテーブル。
link editorは外部関数等の呼び出しをPLTの該当エントリの呼び出しに
置き換え、実行時にPLTのコードはGOTを通してdynamic linkerの
シンボル解決ルーチンへジャンプする。
0167デフォルトの名無しさん
NGNG1.GOT経由で2.へジャンプするコード
2.dynamic linkerへジャンプするコード
に分かれている。
dynamic linkerは2.から処理を受け取った時に1.で参照した
GOTのエントリを与えられるので、それを書き換える事により
2度目以降の同じ関数の呼び出しはdynamic linkerを通さずに
1.から直接ジャンプする事が出来る。
0168デフォルトの名無しさん
NGNG>PICでない*.aを*.soに取り込めないのは不思議。
これは、オブジェクトファイルのTYPE=PROGBITSの
.textと.dataセクション、TYPE=RELの.rel.textや.rel.dataを
ちょこっと書き換えればPIC形式のオブジェクトファイルに
変換できるだろう、という意味ですか?
0169デフォルトの名無しさん
NGNG変換しない。
PICがPosition Independent Codeの略なのはオッケー?
コードをPICにする必要があるのは読み取り専用の領域を
プロセス間で使い回す為に再配置を避けたいから。
非PICな(直接絶対番地指定する)コードであっても、
dynamic linkerが読み取り専用領域を一旦書き込み可能にして再配置すれば
プロセス間でメモリ領域の共有が出来ないだけで動作はする筈。
「セクション」って事はlink editorの仕事について言ってるんだろうけど、
link editorはコードが読み取り専用領域のデータの再配置を必要とする場合に
DT_TEXTRELなりDF_TEXTRELなりの情報を載せてdynamic linkerが
正しく処理出来るようにすれば良いんじゃないかな。
0170デフォルトの名無しさん
NGNG>変換しない。
そうはいっても>>165の簡単なCのコードですら、アセンブラにした段階で
.textセクションに異なるコードを生成してますよ。
NON-PIC
foo:
subl $4, %esp
movl abc, %eax
movl %eax, (%esp)
addl $4, %esp
ret
.size foo, .-foo
PIC
foo:
subl $4, %esp
call __i686.get_pc_thunk.cx
addl $_GLOBAL_OFFSET_TABLE_, %ecx
movl abc@GOTOFF(%ecx), %eax
movl %eax, (%esp)
addl $4, %esp
ret
.size foo, .-foo
.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
.globl __i686.get_pc_thunk.cx
.hidden __i686.get_pc_thunk.cx
.type __i686.get_pc_thunk.cx, @function
__i686.get_pc_thunk.cx:
movl (%esp), %ecx
ret
0171デフォルトの名無しさん
NGNGそれで何が問題だと思うの?
0172デフォルトの名無しさん
NGNGアセンブラソースをはりましたが、PICは>>167に書かれている通り、
GOT経由でモジュールローカルな変数(ここではabc)にアクセスしてますよね。
もし仮にNON-PICなモジュールをPICなモジュールとして使おうとすれば、
そのようなGOTへのアクセスルーチンを埋め込み、.rel.textセクションにGOTの
エントリを追加しなくてはならないように思います。
0173デフォルトの名無しさん
NGNG非PICなコードに必要なのは
movl abc, %eax
のabcの再配置であって、GOT経由のアクセスにする事ではないんじゃ。
0174デフォルトの名無しさん
NGNG>非PICなコードに必要なのは
>のabcの再配置であって
非PICコードからEXEを作るなら、static変数の
アドレスはリンク時に確定すると思うけど。
.rel.textセクションにエントリが追加されてるのは、
リンク時に.textセクション内のアドレス解決を行うものの
一覧だと思うし。
0175デフォルトの名無しさん
NGNGEXEではそう。
0176デフォルトの名無しさん
NGNG>>174
実行するアドレスが一意に決まるなら、それでも問題はないですな。
つーかstaticに限らず全てのアドレス参照がリンク時に解決できなきゃいけない。
あと.rel.textはアドレス解決には関係ない。
例外としてDOSみたいに実行時にアドレスが決定される場合は、ロードした時に
ごにょごにょやるしか無いけど。
今時そんなOSはまずないが。
0177デフォルトの名無しさん
NGNG.rel.textセクションというのは、.textセクション内の
コード中における、アドレス値の一覧なのではないでしょうか。
各エントリは.textセクション内のオフセットを示していると思いますがいかがでしょうか。
下は>>167のコードを-fPICをつけてコンパイルしたものの.rel.textセクションです。
Relocation section '.rel.text' at offset 0x3c8 contains 3 entries:
Offset Info Type Sym.Value Sym. Name
00000004 00000a02 R_386_PC32 00000000 __i686.get_pc_thunk.cx
0000000a 00000b0a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
00000010 00000309 R_386_GOTOFF 00000000 .data
↑ここのOffsetとは.textセクションの先頭からのバイト数だと思います。
.rel.textを含む、TYPE=RELであるセクションに登録されている各エントリのデータ構造
/* Relocation table entry without addend (in section of type SHT_REL). */
typedef struct
{
Elf32_Addr r_offset; /* Address */
Elf32_Word r_info; /* Relocation type and symbol index */
} Elf32_Rel;
/* i386 relocs. */ 各エントリのタイプ一覧の抜粋 Elf32_Rel.r_infoの値
#define R_386_PC32 2 /* PC relative 32 bit */
#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
コードはLINUX GLIBC-2.3.3のelf.hを参考にしました。他のOSだと型名などが
微妙に違うと思います。
0178デフォルトの名無しさん
NGNG00000000 <foo>:
0:83 ec 04 sub $0x4,%esp
3:e8 (fc ff ff ff) call 4 <foo+0x4> ;;__i686.get_pc_thunk.cx
8:81 c1 (02 00 00 00) add $0x2,%exc ;;_GLOBAL_OFFSET_TABLE_
e:8b 81 (00 00 00 00) mov 0x0(%ecx),%eax ;;.data
14:89 04 24 mov %eax,(%esp,1)
17:83 c4 04 add $0x4,%esp
1a:c3 ret
00000000 <__i686.get_pc_thunk.cx>:
0:8b 0c 24 mov (%esp,1),%ecx
3:c3 ret
$gcc -fPIC -shared -fomit-frame-pointer -o foo.so foo.c
$objdump -d foo.so から抜粋
00000648 <foo>:
648: 83 ec 04 sub $0x4,%esp
64b: e8 (13 00 00 00) call 663 <__i686.get_pc_thunk.cx>
650: 81 c1 (50 11 00 00) add $0x1150,%ecx ;;GOTのアドレスを%ecxに設定
656: 8b 81 (28 ff ff ff) mov 0xffffff28(%ecx),%eax ;;%eaxにabcの値をコピー
65c: 89 04 24 mov %eax,(%esp,1)
65f: 83 c4 04 add $0x4,%esp
662: c3 ret
00000663 <__i686.get_pc_thunk.cx>:
663: 8b 0c 24 mov (%esp,1),%ecx
666: c3 ret
0179デフォルトの名無しさん
NGNG型名とマクロはELFの本家ドキュメントのと同じで、
i386なら*BSDでも同じ名前を使ってます。
これ以上何と説明すれば良いやら分からないので、
ゼヒとも仕様を読んでくらはい……。
ELFにはrelocatableとexecutable、sharedの三形式があり、
再配置はlink editorとdynamic linkerの両方が扱うもので
それぞれの意味が違うってのは大丈夫ですよね?
>>169に書いた通り、>>173の再配置というのは
dynamic linkerが行う再配置の事を言っています。
0180デフォルトの名無しさん
NGNG>型名とマクロはELFの本家ドキュメントのと同じで、
>i386なら*BSDでも同じ名前を使ってます。
そうでしょうか。私はNetBSDとLinuxを使っていますが、
Elf32_Symに関しては、NetBSDは本家のドキュメントと異なっているように見えます。
ざっと見た印象により、上には書いただけですし、
ちょこっと調べた結果判明したのはここだけだったのでなんとも言えませんが。
CVS-HEAD
/usr/src/sys/sys/exec_elf.h
typedef struct {
Elf32_Wordst_name;/* Symbol name (.symtab index) */
Elf32_Wordst_value;/* value of symbol */
Elf32_Wordst_size;/* size of symbol */
Elf_Bytest_info;/* type / binding attrs */
Elf_Bytest_other;/* unused */
Elf32_Halfst_shndx;/* section index of symbol */
} Elf32_Sym;
GLIBC-2.3.3はこうです。
typedef struct
{
Elf32_Wordst_name;/* Symbol name (string tbl index) */
Elf32_Addrst_value;/* Symbol value */
Elf32_Wordst_size;/* Symbol size */
unsigned charst_info;/* Symbol type and binding */
unsigned charst_other;/* Symbol visibility */
Elf32_Sectionst_shndx;/* Section index */
} Elf32_Sym;
0181デフォルトの名無しさん
NGNGCVS-HEAD
/usr/src/sys/sys/exec_elf.h
typedef struct {
Elf32_Word st_name; /* Symbol name (.symtab index) */
Elf32_Word st_value; /* value of symbol */
Elf32_Word st_size; /* size of symbol */
Elf_Byte st_info; /* type / binding attrs */
Elf_Byte st_other; /* unused */
Elf32_Half st_shndx; /* section index of symbol */
} Elf32_Sym;
GLIBC-2.3.3
typedef struct
{
Elf32_Word st_name; /* Symbol name (string tbl index) */
Elf32_Addr st_value; /* Symbol value */
Elf32_Word st_size; /* Symbol size */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
Elf32_Section st_shndx; /* Section index */
} Elf32_Sym;
あと
>再配置はlink editorとdynamic linkerの両方が扱うもので
>それぞれの意味が違うってのは大丈夫ですよね?
それはいいのですが、
>あと.rel.textはアドレス解決には関係ない。
リンク時において、.rel.textの情報を元に.textセクションのアドレス値を
決定してるように見えますが、これは「アドレス解決」とは呼ばないんですか?
リンク時にGOTへのオフセットを計算してますけど。
0182デフォルトの名無しさん
NGNGそう言えばElf_Byteとかやってたな……。
いい加減な発言をしてもうしわけない。
>>181
>> 再配置はlink editorとdynamic linkerの両方が扱うもので
>> それぞれの意味が違うってのは大丈夫ですよね?
> それはいいのですが
じゃあ何が通じてないんだろう……。
>> あと.rel.textはアドレス解決には関係ない。
これは自分の発言ではないのでなんとも。
dynamic linkerのレベルでは関係ありません。
link editorがnon-PICなrelocatableからsharedを作る話ですよね?
dynamic linkerがDT_RELやDT_RELAを元に見つけるrelocation tableへ
>>170の例で言うabc用のエントリを作ってDT_TEXTRELを彫り込む、
ってので何が問題だと思います?
0183162
NGNG>>182
>じゃあ何が通じてないんだろう……。
えーと、私もこの前からELFについて勉強し始めたばかりで、
ローダーがどうELFを処理するのかについては、何も知らず、
このスレでも一切触れていません。EXE、DYNともにコンパイル時、
リンク時にどういった処理により作成されるかを、一つ一つ見ているわけです。
>link editorがnon-PICなrelocatableからsharedを作る話ですよね?
私はこの話に関しては何も言ってません。
>>169の「変換しない。」という一言がちょっと気になっただけです。
>>170を見ての通り、non-PICなオブジェクトファイルからDYNを作るとなると、
static変数をGOT経由で参照するようプログラムのロジックを書き変える必要が
あるだろうということ。EXEと違い、DYNにおいてはモジュールローカルな
static変数のアドレスが分らない点にあると思います。いつ、セグメント内のどこに
配置されるのか分らないですから。ローダーの動作を見てないので確かなことは
言えないですが、もし仮にローダーがプログラム内のstatic変数の{絶対、相対}アドレスを
計算してくれるなら、そもそもGOTは必要ないですよね?
GNUのツールはプリプロセッサ、コンパイル、アセンブル、リンクといったフェーズに
キッチリ分けることを重視しているように見えます。そこで疑問なのですが、コンパイル
フェーズで確定したプログラムロジックを後から修正するようなツールなどは
存在するのでしょうか?non-PICとはコンパイラによる最適化の一種だと私は
考えています。そして、non-PICオブジェクトファイルをDYNに含められないのは、
上に挙げたGNUツールの特徴のためだと考えてますがいかがでしょう。
ELFの扱いに関して、ディテールを含めた全体をキッチリ理解したいので、
私の勘違いによる批判、大いにWELCOMEです。
0184デフォルトの名無しさん
NGNG○static変数の参照においてはそもそもGOTは必要ないですよね?
0185156
NGNG> EXEと違い、DYNにおいてはモジュールローカルなstatic変数のアドレスが分らない
dynamic linkerは一意に決められますし、決められないと話になりません。
> もし仮にローダーがプログラム内のstatic変数の{絶対、相対}アドレスを
> 計算してくれるなら、そもそもGOTは必要ないですよね?
効率を無視すればこの状況では必要ありません。
i386でのGOTの使い道は>>166-167にある通りです。
dynamic linkerはsharedを配置するアドレスをプロセス毎に一意に決められますが、
普通は利用するプロセス毎に違うアドレスを使います。
>>170で言うabcのアドレスを特定のプロセスでの絶対番地に変換=再配置してしまうと、
同じコードを別のプロセスが利用する事が出来なくなります。
それでもプロセス毎にコードのコピーを持ってプロセス毎に再配置すれば、
メモリ領域が無駄になるだけで矛盾無く動作させる事は可能です。
コードを共有するのにはmmap()等を使います。
> コンパイルフェーズで確定したプログラムロジックを後から修正
abcの再配置情報をリンカが作成した上でDT_TEXTRELってフラグをsharedに付けるだけです。
PICに変換する必要は無いのでロジックはコンパイル以降変わりません。
>>184
> static変数の参照においてはそもそもGOTは必要ないですよね?
動けば良いという発想なら必要ありません。
0186162
NGNG>> EXEと違い、DYNにおいてはモジュールローカルなstatic変数のアドレスが分らない
>dynamic linkerは一意に決められますし、決められないと話になりません。
これはリンク時に限定した話です。
>dynamic linkerはsharedを配置するアドレスをプロセス毎に一意に決められますが、
>普通は利用するプロセス毎に違うアドレスを使います。
>>>170で言うabcのアドレスを特定のプロセスでの絶対番地に変換=再配置してしまうと、
>同じコードを別のプロセスが利用する事が出来なくなります。
・・・
>コードを共有するのにはmmap()等を使います。
おぼろげながらやっと理解できました。straceでローダーの動作を確認してみました。
そこでですが、やはり理解できないのは、
>> コンパイルフェーズで確定したプログラムロジックを後から修正
>abcの再配置情報をリンカが作成した上でDT_TEXTRELってフラグをsharedに付けるだけです。
>PICに変換する必要は無いのでロジックはコンパイル以降変わりません。
上で見た通り、dynamic linkerはメモリ上にプログラムコードを配置する時に
コードに埋め込まれたアドレス値を書き換えることは出来ないわけですよね?
0187162 186の続き
NGNG00000000 <foo>:
0: 83 ec 04 sub $0x4,%esp
3: a1 (00 00 00 00) mov 0x0,%eax
8: 89 04 24 mov %eax,(%esp,1)
b: 83 c4 04 add $0x4,%esp
e: c3 ret
[[[ foo(EXE) ]]]
08048344 <foo>:
8048344: 83 ec 04 sub $0x4,%esp
8048347: a1 (98 94 04 08) mov 0x8049498,%eax
804834c: 89 04 24 mov %eax,(%esp,1)
804834f: 83 c4 04 add $0x4,%esp
8048352: c3 ret
foo.oからEXEを作る上では.rel.textに記載されているRelocation情報をもとに
カッコで囲まれたアドレスを「リンク時」決定することが出来ます。
0x8049498というのは、abcの絶対アドレスだと思われますが、これがリンク時に
確定できるのは、OSが何をどこに配置するのかを、処理系が分っているからですよね?
では、non-PICからDYNを作成するときには
3: a1 (00 00 00 00) mov 0x0,%eax
この一文のアドレス値には何を入れておけばいいのでしょうか?
dynamic linkerがDYNをロードするまではabcの絶対アドレスは確定しない。
dynamic linkerがアドレス値を確定しても、プログラム領域を書き変えるわけにはいかない。
0188156
NGNG> 上で見た通り、dynamic linkerはメモリ上にプログラムコードを配置する時に
> コードに埋め込まれたアドレス値を書き換えることは出来ないわけですよね?
いいえ、出来ます。
例えばmmap()ならMAP_PRIVATEでやってCoWによりプロセス毎にコピーを持つようになるだけです。
メモリの読み取り専用属性は変える必要がありますが。
>>187
> では、non-PICからDYNを作成するときには
>
> 3: a1 (00 00 00 00) mov 0x0,%eax
>
> この一文のアドレス値には何を入れておけばいいのでしょうか?
implicit addendです。
この場合はベースアドレスからのabcのオフセットでしょうね。
jumpのrelocationだと-4だと思います。
0189デフォルトの名無しさん
NGNG>> コードに埋め込まれたアドレス値を書き換えることは出来ないわけですよね?
>いいえ、出来ます。
>例えばmmap()ならMAP_PRIVATEでやってCoWによりプロセス毎にコピーを持つようになるだけです。
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220P\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1183432, ...}) = 0
mmap2(NULL, 1121740, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x40066000
mmap2(0x40172000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10b) = 0x40172000
mmap2(0x40176000, 7628, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40176000
close(3) = 0
straceの出力をよく見れば、ld.soによる全てのmmap2(Linux)において
MAP_PRIVATE指定されていました。しかしO_RDONLYでopenして、PROT_READ|PROT_EXECという
保護属性の中で、MAP_PRIVATEというのはどんな意味があるのかな。。。
またMAP_DENYWRITEに関してはmanに以下のように書いてあるのに、ld-2.3.4.soにおいてもまだ
フラグ指定されてるのは、互換性だけの理由かな。
>このフラグは無視される。 (ずっと前は、マップ元のファイルへの書き込みを行おうとすると、
>エラー ETXTBUSY で失敗するようにシグナルが設定されていたが、これは denial-of-service
>(サービス拒否)攻撃の原因となった)
156さんの言ってることがmmapとCoWによりようやく理解できました。
non-PICをDYNに含めることにおいて「効率を〜」という話が出てくるのは
CoWを前提とした話だったのですね。なるほど。
それから考えるとたしかに、DYNにnon-PICを含むことが出来ないのは、
おかしな話に思えます。ELFの仕様が出来上がったのは10年も昔の話だし、
MMUのないCPUなどの事情も考慮されているのかもしれないですね。
他にはGNUツールの開発者のポリシー、またはセキュリティー的な事情とかも
ありうるのかな。ELFを理解できたら、そのうち調べてみたいです。
0190デフォルトの名無しさん
NGNGページごとにCopyが起きるからね。
実際、関数呼び出しがあるページがコピーされたら、
プログラムの領域はほぼ全部コピーされちゃうんじゃない?
0191162
NGNG>>>185にメモリが無駄になるって書いてあるじゃん。
それは分っています。ローダーがページ境界に収まるように
DYN内の.non-pic.text(仮)セクションをメモリ内にコピー&アドレス値を
上書きすることでは、それ程無駄になら気も。気のせいかな。。。
ただ、CoWとは言っても、実行が開始される前のdynamic linkerが
コード内のアドレス値を書き換える時点において、ページが割り当てられて
しまうんですね。当たり前ですが。そのコードが実行されるかどうかに関係なく。
最近のOSならばページフォルトを利用したVMMによるファイルの遅延ロードは
どれも実装されていると思いますので、下手したら、静的リンクよりも
効率の悪いものになるかも?!
>実際、関数呼び出しがあるページがコピーされたら、
>プログラムの領域はほぼ全部コピーされちゃうんじゃない?
これはどういう意味ですか?できればもう少し詳しくお願いします。
先にPICなセクションを再配置しておいてから、non-PICなセクションを
処理すれば、あまり問題がないような。
DYNにnon-PICなコードを含めるのならば、セクションを別にする必要が
あるだろうと思います。
不勉強なのに適当な印象の話ばかり書き込みました。しばらくELFと
dynamic linkerについて調べてきます。
0192156
NGNGちょうどcygwinでi386のelfを吐けるクロスコンパイラをビルドしたところだったので
試しにやってみたらnon-PICなrelocatableからsharedを作れました。
# ていうか最初に試せ >俺
>>142の人がどういう手順と環境で出来なかったのか気になります……。
0193デフォルトの名無しさん
NGNGおお、それはGOODニュースですね!
で、できればリンカオプションを教えてください・・・orz
0194162
NGNG$gcc -c -fomit-frame-pointer -o foo.o
$ld -o foo.so -shared foo.o
$objdump -d foo.so
000002b8 <foo>:
2b8: 83 ec 04 sub $0x4,%esp
2bb: a1 c8 12 00 00 mov 0x12c8,%eax
2c0: 89 04 24 mov %eax,(%esp,1)
2c3: 83 c4 04 add $0x4,%esp
2c6: c3 ret
なんか今まであれこれ憶測並べてたのが恥かしくなってきた。
もう寝る。。
0195156
NGNG> DYNにnon-PICなコードを含めるのならば、セクションを別にする必要がある
まるっきり勘で言いますけど、普通別にしないような気がします。
まあ勘なんでなるたけ突っ込まないで下さい。
あと細かい点ですが、実行時の視点で見るのはセクションでなくセグメントです。
ELFの場合この用語は混同しない方が良いです。
>>194
すんません、普段ELFを作れる環境を使わなかったんで……。
Sunのサイトで公開されてるSolarisのマニュアルにリンカに関する物があって、
それにELFの仕様の邦訳っぽい物も含まれてます。
所々微妙な訳もありますけど、一応メンテナンスはされてるようなんで
英語がとっつき辛い場合はそれも参考にすると良いかもしれません。
0196デフォルトの名無しさん
NGNG0197鬼塚先生
NGNG0198デフォルトの名無しさん
NGNGそれはGTO。
0199デフォルトの名無しさん
NGNGld -T boot.ls -o boot boot.o
したら
ld: PE operations on non PE file.
というエラーになって生成できません。
AMD k6-2のLinuxではちゃんとブートセクタが生成されて動作できました。
Cygwin版特有のオプション等が必要なんでしょうか?
解決方法を教えて下さい。
よろしくお願いいたします。
boot.ls
-----------------
OUTPUT_FORMAT("binary");
MEMORY
{
body : org = 0, len = 510
sign : org = 510, len = 2
}
SECTIONS
{
.text : { *(.text) } > body/* executable code */
.rodata : { *(.rodata*) } > body/* constants */
.data : { *(.data) } > body/* initialized data */
.bss : { *(.bss) } > body/* uninitialized data */
.sign : { SHORT(0xAA55) } > sign/* boot signature */
}
0200デフォルトの名無しさん
NGNGboot.oはどうやって生成した?
0201199
NGNGMakefileの内容です。
all:
gcc -Os -c -o img/boot.o boot.s
ld -T img/boot.ls -o img/boot img/boot.o
gcc -Os -c -o img/kernel.o kernel.c
ld -T img/kernel.ls -o img/kernel img/kernel.o
dd if=img/my_default.img of=img/my.img 2> /dev/null
dd if=img/boot of=img/my.img conv=notrunc 2> /dev/null
dd if=img/kernel obs=512 seek=1 of=img/my.img
0202デフォルトの名無しさん
NGNGどっちかだと思ったんだよな。
ldのメッセージは前者っぽいんだけど
gccがcygwinネイティブなら後者かなー。
今携帯からなんでPEのリファレンスがねーのよ。
0203199
NGNGばいなりエディタでboot.oを各環境とも開いてみたらLinux側は先頭に
.ELF
があって、Cygwin側の先頭は
L<
text
って感じでした。
自分ではこれが何を意味しているか分からないですが参考までに。
よろしくお願いいたします。
0204デフォルトの名無しさん
NGNGリンカスクリプトのboot.lsが元のオブジェクトファイルの中から
.textセクションとか.rodataセクションを抜きだして
(セクション構造のない)ベタなbinaryにしようとしてるわけだけど、
このセクション構造がELFにあってPEにないもので、
cygwinで作ったバイナリがPEなもんだから
ldが処理できませーんとかになってんじゃないのかなみたいな
0205デフォルトの名無しさん
NGNGして詳細メッセージ出したのをはってもらえない?
0206199
NGNG$ ld -v -T img/boot.ls -o img/boot img/boot.o
GNU ld version 2.15.91 20040725
ld: PE operations on non PE file.
0207199
NGNG$ ld -V -T boot.ls -o img/boot boot.o
GNU ld version 2.15.91 20040725
Supported emulations:
i386pe
ld: PE operations on non PE file.
となりました。
0208デフォルトの名無しさん
NGNGhttp://my.execpc.com/~geezer/embed/bugs.htm#mingbug
0209デフォルトの名無しさん
NGNG超簡単なmsvcrtの関数使うサンプルとかないですかね?
そういや市販コンパイラが作るDLL関数の呼び出しコードって
インポートテーブルから
call DWORD ptr[import_table_address]
のようなことしてるけど、別に
mov eax, procedure_addres
call eax
としてもいいよなあ。
なんで1段参照増やしてんの?
インポートテーブル分無駄じゃない?
0210デフォルトの名無しさん
NGNGなるほどねー。
0211デフォルトの名無しさん
NGNGの各DLL関数名の前に付いている、
「ヒント」の値って、何を入れるんでしょうか?
意味がまるでわからないです。
0212デフォルトの名無しさん
NGNGどうせ名前で調べるし
0213デフォルトの名無しさん
NGNGこんなのどうやって知るのでしょうか。
参照するDLLを調べろということですかね。
どっかから入手したpecoff.docによると、
>6.4.3. Hint/Name Table
>Field Hint
>Description
> Index into the Export Name Pointer Table.
> A match is attempted first with this value. If it fails,
>a binary search is performed on the DLL's Export Name Pointer Table.
ということは、わかんなかったら0とかの適当な値でよいと言う事でしょうか。
試しに全部0にしてやったらうまくいきました。
このヒントは、パフォーマンス上の理由でしかないのでしょうか?
0214デフォルトの名無しさん
NGNGそうですね。
実験してとりあえず無視して問題なかったので、
しばらく放置プレイしときます。
0215デフォルトの名無しさん
NGNGリンカであらかじめ序数を控えておいた方が良いのかな。
DLLの関数を全部列挙するなんてAPIないですよね・・・。
objdump.exeで取ってくるしかない?
0216デフォルトの名無しさん
NGNG同じことだけど PE 解析ルーチンを書けばいい。
0217デフォルトの名無しさん
NGNGそれとexe自体よりスタートアップ作るのが面倒すぎる。
Win32APIしか使わないなら話は簡単だけど、
Cランタイム使えないとあんま意味ないんだよなあ。
とりあえずmsvcrt.dllを安全に使えるレベルとか考えてたけど
無理な気がしてきた。
mingwやlccwin解析すりゃいいんだろうけどね。
すげー遠い。
素直に既成のリンカへ.obj渡す事考えた方が早いかも。
0218デフォルトの名無しさん
NGNGという連載が始まったよ。
今回は13Pで、主に用語など基礎知識の説明でした。
次回はELF形式のお話みたいなんで期待。
0219デフォルトの名無しさん
NGNGInterfaceのこの手の記事は使えそうで使えないからなあ。
ELF形式なんてGNU系の資料いっぱいあるからPEやって欲しいのだが。
PEやる予定あるのかな。
無かったら笑えるがな。
0220デフォルトの名無しさん
NGNG0221デフォルトの名無しさん
NGNG0222デフォルトの名無しさん
05/02/05 10:26:280223デフォルトの名無しさん
05/02/06 03:09:02実行ファイルを作成した場合、必ずどっちが優先されるとか
ってあるんでしょうか?
0224Rubyist!
05/02/06 03:12:030225デフォルトの名無しさん
05/02/14 14:21:01内容上重複というか同じような事書いてる部分は多いかもしれないが
読んで楽しめるとは思う
ちなみにLinker"s"
sが付く、これ重要
どうでもいいが漏れの近くの書店ではHTMLの分類の所に
隣近所はHTMLとかホームページとか
田舎の書店のアルバイトじゃ分類タイトルみただけじゃそうなるだろうなぁ
0226デフォルトの名無しさん
05/03/05 05:38:080227デフォルトの名無しさん
05/03/05 05:49:40オタ本の分類だろうし
少なすぎるというかそもそもたくさんある類いの本じゃないよね
0228226
05/03/05 06:05:41もっと美しく言うと専門書籍って言わない?(萌え本みたいな印象もあるし)
0229226
05/03/05 06:21:23みんな(出版社とか)は、わかって無いよなぁ。チャンスなのに。
0230デフォルトの名無しさん
05/03/05 06:42:57萌え本ってなんですか?
0231デフォルトの名無しさん
05/03/05 08:36:54http://www.google.co.jp/search?hl=ja&q=%E8%90%8C%E3%81%88%E6%9C%AC&btnG=Google+%E6%A4%9C%E7%B4%A2&lr=lang_ja
0232デフォルトの名無しさん
2005/05/26(木) 21:34:03×ぶっちゃけ、「Linkers & Loaders」のような本が少なすぎる。
○ぶっちゃけ、「Linkers & Loaders」のような本を読む人が少なすぎる。
■ このスレッドは過去ログ倉庫に格納されています