最初の調査:
a.c
extern void b(void);
void a(void);
int main() {
a();
return 0;
}
void a() {
b();
}
b.S
.extern a
b:
jmp a
b.c
void a(void);
void b(void)
{
a();
}
出力
$ gcc -c a.c
$ gcc -c b.c -o b_gcc.o
$ as b.S -o b_as.o
$ gcc a.o b_gcc.o -o test_gcc
$ gcc a.o b_as.o -o test_as
a.o: In function `a':
a.c:(.text+0x15): undefined reference to `b'
collect2: error: ld returned 1 exit status
だから何ができますか?なぜGCCでは大丈夫ですか?GASでは大丈夫ですか?
$ objdump -t b_gcc.o > syms_gcc
$ objdump -t b_as.o > syms_as
$ diff syms_gcc syms_as
2c2
< b_gcc.o: file format elf64-x86-64
---
> b_as.o: file format elf64-x86-64
5d4
< 0000000000000000 l df *ABS* 0000000000000000 b.c
9,12c8
< 0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
< 0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
< 0000000000000000 l d .comment 0000000000000000 .comment
< 0000000000000000 g F .text 000000000000000b b
---
> 0000000000000000 l .text 0000000000000000 b
わかりましたので、gcc
はb
グローバルシンボルになります。
$ as b.S -o b_as2.o
$ gcc a.o b_as2.o
$
成功:b.S
で.global b
を試すことができます。したがってgcc
/ld
は、スタティックライブラリにないものに対してマルチパスシンボルの解像度を行います。しかしはグローバルシンボルを探します。最終的にはb.S
です:
.extern a
.global b
b:
jmp a
いくつか質問があります:(a)そのターゲットは何ですか? yasm、nasm、それにgasのようなものはありません。 (b) 'a.c'でvoid a()を宣言する必要があります。そうしないと、コンパイルされません。 (c) 'b()'をC関数に変更し、あなたのリンクコマンドを試してみるとうまくいきます。私が知っている限り、あなたがリンクするために話している種類の依存関係を得る唯一の時間は、静的ライブラリのリンカの振る舞いです。問題の実例を示すために質問を更新できますか? – lockcmpxchg8b
それはgnu asです。 私は大きく成長したオペレーティングシステムを書いており、このような例を作ることを考えました。 –
sry、私の問題は私の最初の調査が明白であったことでした。適切なLinuxに移動すると、あなたのサンプルをうまく組み立てることができます。以下の解決策。 TL; DR:問題は、「b」がグローバルではないということです。 – lockcmpxchg8b