gnu ld, binutils についての質問です。
watatsu というものです。
始めての投稿です。
gnu ld を使ってリンクをしたときに疑問に思い、投稿しました。
リンカスクリプトで、以下のようにリンクしたときに、スタック・デー
タ各セグメントを別々の領域として使うことは出来るのでしょうか。ど
なたかご教授をお願いします。
以下に例を示します。
OUTPUT_FORMAT("binary")
OUTPUT_ARCH(i386)
SECTIONS
{
_align = 4K;
OVERLAY 0 : AT(0)
{
.text { *(.text)
_etext = ALIGN(_align);
. = _etext; }
.data { *(.data .rodata)
*(.bss)
_edata = ALIGN(_align);
. = _edata; }
}
}
として、GDT に、コードセグメント用としてロードしたアドレスを
起点として _etext だけ、コードセグメントに、そこから_e
dataだけデータセグメントに割り当て、それ以降をエキスパンドダ
ウン型のスタック領域として割り当てて、例えば以下のようなコードを
bochs 上で実行するとエラーになります。(便宜上重要な部分だ
け抜きだします。)
file1.S:
.org 0
.code32
// ds, es, fs, gs はデータセグメント
// cs は現在のコードセグメント
// ss はスタックセグメント
xorl %esp, %esp
decl %esp
jmp start
file2.c:
int bogus_func(int* bar)
{
// この代入で例外が発生します…
*bar = 0;
}
extern void start(void)
__asm__ ("start")
__attribute__((noreturn));
void start(void)
{
int foo;
bogus_func(&foo);
cont:
goto cont;
}
逆アセンブルした結果から推測すると、宣言した変数が全てスタック上
でやりとりされ、bogus_funcにポインタを渡すと、スタック
へのポインタが渡され、メモリの実体を指してないようです。
つまり、fooがスタック上にあるにもかかわらず、barへの代入の
時点でデータセグメントに対して変更を加えようとするのです。
どなたかご教授願よろしくお願いします。
gcc 3.2.3
コンフィグオプション: ./configure
GNU ld 2.13
; cltack
; cltack@xug.biglobe.ne.jp
Fnews-brouse 1.9(20180406) -- by Mizuno, MWE <mwe@ccsf.jp>
GnuPG Key ID = ECC8A735
GnuPG Key fingerprint = 9BE6 B9E9 55A5 A499 CD51 946E 9BDC 7870 ECC8 A735