macOSでLLVMを使って言語を作った際、オブジェクトファイルを吐いてリンクしようとすると、以下のエラーが発生した。
"_Unwind_Resume", referenced from:
f in foo.o
g in foo.o
"__gcc_personality_v0", referenced from:
f in foo.o
g in foo.o
Dwarf Exception Unwind Info (__eh_frame) in foo.o
どうやら_Unwind_Resume
と__gcc_personality_v0
が未定義らしい。しかし、LLVMのライブラリから二つのシンボルを探してみると、存在していた。/usr/local/opt/llvm/lib
内でnm libunwind.dylib | grep _Unwind_Resume
を実行すると、以下のように、__Unwind_Resume
が存在していることがわかる。
000000000000be7f S $ld$hide$os10.4$__Unwind_Resume
000000000000be8f S $ld$hide$os10.4$__Unwind_Resume_or_Rethrow
000000000000be80 S $ld$hide$os10.5$__Unwind_Resume
000000000000be90 S $ld$hide$os10.5$__Unwind_Resume_or_Rethrow
0000000000008780 T __Unwind_Resume
0000000000008e70 T __Unwind_Resume_or_Rethrow
しかし、よくみると、アンダースコアが一つ多いことがわかる。これはどういうことか。
実は、LLVMを使ってオブジェクトファイルを出力する際、接頭辞のアンダースコアをつけていなかった(接頭辞のアンダースコアをleading underscoreと言う)。このため、ライブラリの方はアンダースコアがついているが、オブジェクトファイルの方はそうでない、という状況になっていた。
LLVMで接頭辞のアンダースコアをつけるには、オブジェクトファイルを出力する際に以下の処理をする必要がある。
TargetMachine *target_machine =
target->createTargetMachine(target_triple, cpu, features, opt, rm);
module->setDataLayout(target_machine->createDataLayout());
重要なのは、module->setDataLayout
の部分だ。ここでmodule
はstd::unique_ptr<llvm::Module>
の型を持っている。こうすることによって、LLVMが全てのシンボルにleading underscoreをつけるようになる。