実現したいこと
最終的に実現したいことは前者の記事の内容で、そのためにllvmバックエンドを書き換える必要があるのですがその方法が記述されているのが後者の記事になります。
RISCVFrameLowering::emitPrologue を正しく書き換えたいです。正しいなら、記事でいうあとは、プロセスを終了させる stack_failure 関数が定義されたオブジェクトファイルを用意し、リンクさせれば完了です。
をどのように行えばいいのか知りたいです。
前提
筆者さんの使用したllvmなどのバージョンが異なり、llvmバックエンドを記事の通りに書き換えたあとにclang経由で実行するとエラーが出ます。
記事ではRISCVFrameLowering::emitPrologueにsspushという独自命令をRISCVFrameLowering::emitEpilogueにsspop, bneの処理を追加することでclangを実行すると関数の頭にsspush, 終わりにsspopとリターンアドレスが書き換えられていないかの確かめが行われ一致していない場合は処理を停止するという仕組みを実装しています。
記事で紹介されていたプログラムの通りsspush, sspop命令を定義しclangに-Sを付けて実行すると自動的に挿入されていることが確認できるのです(以下に載せました)が、bneの追加でエラーが発生します。
発生するエラーコードが139ということで調べるとsegmentation faultのようですので、おそらくllvmが実行される中でbneでジャンプ先のオブジェクト(処理をすべて停止させる関数)のアドレスがわからないよ(リンクされていないから)というエラーだと思います。しかしこのオブジェクトをどのように用意してどのようにリンクすればいいのかがわからず詰まってしまいました。
llvm自体がC++で書かれているようだったのでstack_failure
オブジェクトのソースはC++で書くべきだと思うのでsspushなどが自動挿入されない素のllvmを利用して作成しましたオブジェクトをどうにかリンクさせてあげたいです。
llvmはcmake --build .
でビルドするのですが用意したオブジェクトをllvmに認識させてあげる方法を知りたいです。
エラーメッセージは長いので一番下にしました。
記事では"スタックフレームを破棄した後で"とあるので以下のようにRISCVFrameLowering::emitPrologue の最後らへんでDeallocate stackのコメントがある場所に紹介されていたプログラムを追加しました。
該当のソースコード
cpp
1 // Deallocate stack 2 if (StackSize != 0) { 3 RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize), 4 MachineInstr::FrameDestroy, getStackAlign()); 5 // 今回の追加部分 (スタックフレームを破棄した後で sspop x5, x0, x0 命令の追加) 6 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(RISCV::SSPOP), RISCV::X5).addReg(RISCV::X0).addReg(RISCV::X0); 7 // 今回の追加部分 (リターンアドレスと Shadow Stack からポップした内容の比較処理を追加 命令としては、bne x1, x5, stack_failure を追加している) 8 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(RISCV::BNE)) 9 .addReg(RISCV::X1) 10 .addReg(RISCV::X5) 11 .addExternalSymbol("stack_failure") 12 .setMIFlag(MachineInstr::FrameSetup); // stack_failure 13 }
sspush, sspopは無事挿入できています。
assembly
1 sspush zero, ra, zero 2 addi sp, sp, -32 3(省略) 4 ld s0, 16(sp) # 8-byte Folded Reload 5 addi sp, sp, 32 6 sspop t0, zero, zero 7
試したこと
- 当該ファイル内で他に2箇所でaddExternalSymbol()が以下のように実行されており、そのどちらも続いてsetMIFlagという関数を実行していました。なのでbneの追加部分でも続けて
.setMIFlag(MachineInstr::FrameSetup);
を書いてみましたが変わらずエラーがでました。
cpp
1 BuildMI(MBB, MI, DL, TII.get(RISCV::PseudoCALLReg), RISCV::X5) 2 .addExternalSymbol(SpillLibCall, RISCVII::MO_CALL) 3 .setMIFlag(MachineInstr::FrameSetup);
発生している問題・エラーメッセージ
Stack dump: 0. Program arguments: ./llvm-project/build/bin/clang --target=riscv64 -c --sysroot=./sysroot/usr/ test.c -march=rv64gc -mabi=lp64d -S 1. <eof> parser at end of file 2. Code generation 3. Running pass 'Function Pass Manager' on module 'test.c'. 4. Running pass 'Branch relaxation pass' on function '@func' #0 0x00007f5434dcd3a0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/nohara/riscv/llvm-project/build/bin/../lib/libLLVMSupport.so.18git+0x1cd3a0) #1 0x00007f5434dcb274 llvm::sys::CleanupOnSignal(unsigned long) (/home/nohara/riscv/llvm-project/build/bin/../lib/libLLVMSupport.so.18git+0x1cb274) #2 0x00007f5434ccf198 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0 #3 0x00007f5434442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520) #4 0x00007f5437d4ab19 (anonymous namespace)::BranchRelaxation::runOnMachineFunction(llvm::MachineFunction&) BranchRelaxation.cpp:0:0 #5 0x00007f5437f3edd4 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0 #6 0x00007f5435a7570a llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/nohara/riscv/llvm-project/build/bin/../lib/libLLVMCore.so.18git+0x27570a) #7 0x00007f5435a75894 llvm::FPPassManager::runOnModule(llvm::Module&) (/home/nohara/riscv/llvm-project/build/bin/../lib/libLLVMCore.so.18git+0x275894) #8 0x00007f5435a76294 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/nohara/riscv/llvm-project/build/bin/../lib/libLLVMCore.so.18git+0x276294) #9 0x00007f54384f8482 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>) (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangCodeGen.so.18git+0xf8482) #10 0x00007f543897ac0c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangCodeGen.so.18git+0x57ac0c) #11 0x00007f5432f40cf9 clang::ParseAST(clang::Sema&, bool, bool) (/home/nohara/riscv/llvm-project/build/bin/../lib/../lib/libclangParse.so.18git+0x39cf9) #12 0x00007f543757ef59 clang::FrontendAction::Execute() (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangFrontend.so.18git+0x114f59) #13 0x00007f54374f47e9 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangFrontend.so.18git+0x8a7e9) #14 0x00007f543946b023 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangFrontendTool.so.18git+0x5023) #15 0x00005566c1d020ef cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (./llvm-project/build/bin/clang+0x140ef) #16 0x00005566c1cfab4d ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0 #17 0x00007f54370c1c2d void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0 #18 0x00007f5434ccf5e7 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/nohara/riscv/llvm-project/build/bin/../lib/libLLVMSupport.so.18git+0xcf5e7) #19 0x00007f54370c1fc7 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0 #20 0x00007f5437088041 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangDriver.so.18git+0x88041) #21 0x00007f5437088afd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangDriver.so.18git+0x88afd) #22 0x00007f543709c01c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/nohara/riscv/llvm-project/build/bin/../lib/libclangDriver.so.18git+0x9c01c) #23 0x00005566c1cff699 clang_main(int, char**, llvm::ToolContext const&) (./llvm-project/build/bin/clang+0x11699) #24 0x00005566c1cf9f83 main (./llvm-project/build/bin/clang+0xbf83) #25 0x00007f5434429d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #26 0x00007f5434429e40 call_init ./csu/../csu/libc-start.c:128:20 #27 0x00007f5434429e40 __libc_start_main ./csu/../csu/libc-start.c:379:5 #28 0x00005566c1cf9fc5 _start (./llvm-project/build/bin/clang+0xbfc5) clang: error: clang frontend command failed with exit code 139 (use -v to see invocation)
補足情報(FW/ツールのバージョンなど)
- llvmは記事で紹介されている通りの手順でエラーなくビルドできました
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/09/28 03:48