MultiCanaryメモ

  • Canaryを増やしてみる
    • 関数の終わりでチェック→バッファごとに追加
    • バッファ操作が終わってから全てのcanaryをチェックするかそのファのすぐ隣にあるものだけチェックするか
    • 隣だけでよさそう(canary値が漏れない限り遠くのスタックだけを書き換えることはできない…はず?)
    • きめ細かく検知できる
  • 検知すると何がうれしい?
    • どこで落ちたかソースコードの行レベルでわかる
    • ログに取っておくとインシデントとかの対応に役立つ
  • デバッグするために自動でブレークポイント貼るみたいに、デバッグするために変なモードでコンパイルさせる
    • するとなんかラクになるかも
  • 「コンパイラでできるのになんか変なレイヤで頑張ってる」→ブレークポイントもその例になりそう
  • バグ検出, warningの改善
  • 実行時に初めてわかることって何?
  • ソースコードなどを組み合わせなきゃダメ
  • ローダでソースコードを使う…?
  • シンボル情報
    • まあ入れることもできるのでローダで読ませてもよい
  • でも普通のデバッガでもソースコードとメモリを対応付けたりできるような
  • Heap canary
  • リターンアドレス/PCを守るというよりかは、データそのものを守れないかなーという
  • パフォーマンス
    • 2, 4, n個だけ置いてみるとか
  • HeapSentry
  • ProPolice
    • StackGuardの進化版
    • オーバーフローしそうなバッファをcanary直下に配置したり
  • ValueGuard
  • エミュレータでしていることhypervisorでできないか?

LLVMを改造する

  • LLVM: lib/CodeGen/StackProtector.cpp (「コンパイラを読む」参照)
  • CreatePrologue()とかが作れなくなるので…
  • アセンブラのイメージとして…

これを

 int main() {
   char a[16];
   char b[8];
   gets(a);
   gets(b);
   printf("a: %s\n", a);
   printf("b: %s\n", b);
   
   return 0;
 }
 sei0o@sei0o-opensuse ~/D/S/multicanary> ./poc
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
 d
 a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
 b: d
 fish: “./poc” terminated by signal SIGSEGV (Address boundary error)
 
 sei0o@sei0o-opensuse ~/D/S/multicanary> ./poc
 AA
 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
 a: bbbbbbbbbbbbbbbbbb
 b: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
  • [LLVM Pass]が使えそう
    • http://llvm.org/docs/WritingAnLLVMPass.html
  • IR(中間言語)のallocaのあとにもう一個QWORDを確保するallocaを追加してあげればよいのでは
  • 改めて見てみるとStackProtectorもFunctionPassだった
    • これを継承して書くのがいいかも’
  • https://stackoverflow.com/questions/4995899/difference-between-pointer-and-reference-in-c
  • どうでもいいけど、BranchInst::Createなのかnew BranchInstなのかIRBuilderを使うのかはっきりしてほしい

  • 実装してoptを使って書き換えるのはうまくできたが、落ちる
     sei0o@sei0oarch ~/D/llvm-experiment> ../llvm-build/bin/lli hello_opt.bc
     ...
     #5 0x000056196fa4da46 llvm::Value::getType() const /home/sei0o/Devs/llvm-6.0.1.src/include/llvm/IR/Value.h:245:34
     #6 0x0000561970541796 llvm::SelectionDAGBuilder::getValue(llvm::Value const*) /home/sei0o/Devs/llvm-6.0.1.src/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:1135:60
     #7 0x00005619705487a0 llvm::SelectionDAGBuilder::visitSPDescriptorParent(llvm::SelectionDAGBuilder::StackProtectorDescriptor&, llvm::MachineBasicBlock*) /home/sei0o/Devs/llvm-6.0.1.src/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:2194:40
     #8 0x00005619704059fd llvm::SelectionDAGISel::FinishBasicBlock() /home/sei0o/Devs/llvm-6.0.1.src/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1788:5
     #9 0x0000561970405176 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) /home/sei0o/Devs/llvm-6.0.1.src/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1634:5
     #10 0x00005619703fe12d llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) /home/sei0o/Devs/llvm-6.0.1.src/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:467:7
     #11 0x000056197081df17 (anonymous namespace)::X86DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) /home/sei0o/Devs/llvm-6.0.1.src/lib/Target/X86/X86ISelDAGToDAG.cpp:176:14
     ...
     Stack dump:
     0.	Program arguments: ../llvm-build/bin/lli hello_opt.bc 
     1.	Running pass 'Function Pass Manager' on module 'hello_opt.bc'.
     2.	Running pass 'X86 DAG->DAG Instruction Selection' on function '@main'
     fish: “../llvm-build/bin/lli hello_opt…” terminated by signal SIGSEGV (Address boundary error)
    
  • 普通のIRを見てみるとstackprotectorが入ってない hello.ll
  • でもllcでコンパイルして逆アセンブルみるとちゃっかり__stack_chk_failがいる
  • 上のメッセージではSelectionDAGが関係している→StackProtectorは関係なかった?
  • MultiCanaryを動かすにはSelectionDAGでのCanary挿入を無効化すればよいのでは
  • Intrinsicのstackprotectorの役割を勘違いしていたかもしれない
  • アセンブラを直接見てみる
    • code:hello.s
      • .LBB0_5: # %CallStackCheckFailBlk
        • callq __stack_chk_fail
    • code:bash
      • $ rg CallStackCheckFailBlk
      • lib/CodeGen/StackProtector.cpp
      • 448: // br i1 %3, label %SP_return, label %CallStackCheckFailBlk
      • 453: // CallStackCheckFailBlk:
      • 503: BasicBlock *FailBB = BasicBlock::Create(Context, “CallStackCheckFailBlk”, F);
  • やっぱりStackProtector使われてたわ
  • llcはbitcodeをアセンブラにするだけではなくて内部で最適化・セキュリティ強化をしているということか
  • Function Attributeのsspstrongが悪さをしていそう

  • ../llvm-build/bin/llc hello_noguard_opt.bc -o hello_noguard_opt.s -print-after-all -debug-pass=Structure -O0 > hello_noguard_opt_llc.txt 2>&1のようにしてすべてのPassのIRを出力する
  • X86 DAG->DAG Instruction Selectionで落ちているので…
  • X86ISelDAGToDAG.cppを参照する
  • code:X86IselDAGTODAG.cpp - //--------------------------------------------------------------------// - /// ISel - X86-specific code to select X86 machine instructions for - /// SelectionDAG operations. - ///
  • SelectionDAGBuilder.cpp:2194 GuardPtr = getValue(IRGuard)で落ちてる
    • code:SelectionDAGBuilder.cpp - // If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD. - // Otherwise, emit a volatile load to retrieve the stack guard value. - SDValue Chain = DAG.getEntryNode(); - if (TLI.useLoadStackGuardNode()) { - Guard = getLoadStackGuard(DAG, dl, Chain); - } else { - const Value *IRGuard = TLI.getSDagStackGuard(M); - SDValue GuardPtr = getValue(IRGuard);

          - Guard =
                  - DAG.getLoad(PtrTy, dl, Chain, GuardPtr, MachinePointerInfo(IRGuard, 0),
                                          - Align, MachineMemOperand::MOVolatile);
      - }
      
  • TLI->getSDagStackGuard()TargetLoweringBase::getSDagStackGuard()__stack_chk_guardというグローバル変数を取ってくる
  • で、これが定義されていないから落ちたと
  • これはTargetLoweringBase::insertSSPDeclarations()でセットされている
    • code:TargetLowering.h - /// Inserts necessary declarations for SSP (stack protection) purpose. - /// Should be used only when getIRStackGuard returns nullptr. ←おいおい - virtual void insertSSPDeclarations(Module &M) const;
  • getIRStackGuardは普通に使えるので、これがよくなさそう
  • SDAGBuidler; StackProtectorDescripto

  • stackprotectorもIntrinsicに頼らず自前で実装することにした
  • Intrinsic読んだけど何してるかよくわからなかったのでとりあえず愚直にStoreをつけてみたら検知できるようになった
  • と思って別の検知プログラムを書いてみたら検知できなかった
  • アセンブラを見て見ると、バッファとバッファの間に挟んだはずのCanaryがまとめて端っこに追いやられている
  • $ llc twobuf_opt.bc -o twobuf_opt.s –print-after-all -debug-pass=Structure > twobuf_opt_llc.txt 2>&1
  • DAGが原因っぽい ぐぬぬ…
  • code:twobuf_opt_llc.txt
    • ** IR Dump After X86 DAG->DAG Instruction Selection **:

    • Machine code for function main: IsSSA, TracksLiveness

    • Frame Objects:
      • fi#0: size=8, align=8, at location SP+8
      • fi#1: size=8, align=8, at location SP+8
      • fi#2: size=4, align=4, at location SP+8
      • fi#3: size=8, align=8, at location SP+8
      • fi#4: size=4, align=4, at location SP+8
      • fi#5: size=8, align=8, at location SP+8
      • fi#6: size=8, align=8, at location SP+8
      • fi#7: size=8, align=8, at location SP+8
      • fi#8: size=30, align=16, at location SP+8 // バッファ?
      • fi#9: size=8, align=8, at location SP+8
      • fi#10: size=30, align=16, at location SP+8 // バッファ?
    • Function Live Ins: %edi in %0, %rsi in %2

    • %bb.0: derived from LLVM BB %2 - Live Ins: %edi %rsi
      • %2:gr64 = COPY %rsi; GR64:%2
      • %0:gr32 = COPY %edi; GR32:%0
      • %1:gr32 = COPY killed %0; GR32:%1,%0
      • %3:gr64 = COPY killed %2; GR64:%3,%2
      • %22:gr64 = MOV64ri @.str; GR64:%22
        • // StackGuardSlotになにかを代入している(おそらくCanary値)
        • // @llvm.stackprotector(組み込み関数)が消えたのでLoweringが完了したとみてよさそう
      • %25:gr64 = MOV64rm %noreg, 1, %noreg, 40, %fs; mem:Volatile LD8inttoptr (i32 40 to i8* addrspace(257)*)(addrspace=257) GR64:%25
      • MOV64mr %stack.0.StackGuardSlot, 1, %noreg, 0, %noreg, killed %25; mem:Volatile ST8FixedStack0 GR64:%25
      • %26:gr64 = MOV64rm %noreg, 1, %noreg, 40, %fs; mem:Volatile LD8inttoptr (i32 40 to i8* addrspace(257)*)(addrspace=257) GR64:%26
        • // (Multi)Canary領域の確保・代入
      • MOV64mr %stack.1.CanarySlot, 1, %noreg, 0, %noreg, killed %26; mem:ST8%CanarySlot GR64:%26
      • %27:gr64 = MOV64rm %noreg, 1, %noreg, 40, %fs; mem:Volatile LD8inttoptr (i32 40 to i8* addrspace(257)*)(addrspace=257) GR64:%27
      • MOV64mr %stack.3.CanarySlot1, 1, %noreg, 0, %noreg, killed %27; mem:ST8%CanarySlot1 GR64:%27
      • %28:gr64 = MOV64rm %noreg, 1, %noreg, 40, %fs; mem:Volatile LD8inttoptr (i32 40 to i8* addrspace(257)*)(addrspace=257) GR64:%28
      • MOV64mr %stack.5.CanarySlot3, 1, %noreg, 0, %noreg, killed %28; mem:ST8%CanarySlot3 GR64:%28
      • %29:gr64 = MOV64rm %noreg, 1, %noreg, 40, %fs; mem:Volatile LD8inttoptr (i32 40 to i8* addrspace(257)*)(addrspace=257) GR64:%29
      • MOV64mr %stack.7.CanarySlot5, 1, %noreg, 0, %noreg, killed %29; mem:ST8%CanarySlot5 GR64:%29
      • %24:gr64 = MOV64rm %noreg, 1, %noreg, 40, %fs; mem:Volatile LD8inttoptr (i32 40 to i8* addrspace(257)*)(addrspace=257) GR64:%24
      • MOV64mr %stack.9.CanarySlot7, 1, %noreg, 0, %noreg, killed %24; mem:ST8%CanarySlot7 GR64:%24
      • MOV32mi %stack.2, 1, %noreg, 0, %noreg, 0; mem:ST4%3
      • MOV32mr %stack.4, 1, %noreg, 0, %noreg, %1; mem:ST4%4 GR32:%1
      • MOV64mr %stack.6, 1, %noreg, 0, %noreg, %3; mem:ST8%5 GR64:%3
      • ADJCALLSTACKDOWN64 0, 0, 0, implicit-def %rsp, implicit-def %eflags, implicit-def %ssp, implicit %rsp, implicit %ssp
      • %rdi = COPY %22; GR64:%22
      • %al = MOV8ri 0
      • CALL64pcrel32 @printf, <regmask %bh %bl %bp %bpl %bx %ebp %ebx %rbp %rbx %r12 %r13 %r14 %r15 %r12b %r13b %r14b %r15b %r12d %r13d %r14d %r15d %r12w %r13w %r14w %r15w>, implicit %rsp, implicit %ssp, implicit %al, implicit %rdi, implicit-def %eax
      • ADJCALLSTACKUP64 0, 0, implicit-def %rsp, implicit-def %eflags, implicit-def %ssp, implicit %rsp, implicit %ssp
      • %23:gr32 = COPY %eax; GR32:%23
      • %18:gr64 = MOV64ri @.str.1; GR64:%18
      • %21:gr64 = LEA64r %stack.8, 1, %noreg, 0, %noreg; GR64:%21 // ここで初めて確保している
      • ADJCALLSTACKDOWN64 0, 0, 0, implicit-def %rsp, implicit-def %eflags, implicit-def %ssp, implicit %rsp, implicit %ssp
      • %rdi = COPY %18; GR64:%18
      • %rsi = COPY %21; GR64:%21
      • %al = MOV8ri 0
      • CALL64pcrel32 @__isoc99_scanf, <regmask %bh %bl %bp %bpl %bx %ebp %ebx %rbp %rbx %r12 %r13 %r14 %r15 %r12b %r13b %r14b %r15b %r12d %r13d %r14d %r15d %r12w %r13w %r14w %r15w>, implicit %rsp, implicit %ssp, implicit %al, implicit %rdi, implicit %rsi, implicit-def %eax
      • ADJCALLSTACKUP64 0, 0, implicit
  • やはりstackprotectorを使うしかないのか…とほほ…
  • IRBuilder::CreateCall?→IRTranslator::translateCallIRTranslator::translateKnownIntrinsicIRTranslator::getStackGuard
    • ここから結局getSDagStackGuardが呼ばれているが、__stack_chk_guardはセットされていないのでnullptrが返る
  • IRBuilder::CreateCall?→SelectionDAGBuilder::visitCallSelectionDAGBuilder::visitIntrinsicCall
  • SelectionDAGISel:: SelectAllBasicBlocksFinishBasicBlock
  • ここにくるまでにParentMBB=nullptrにしたい
  • SelectionDAGISel:1607でshouldEmitSDCheckがtrueを吐いてしまって, 保持されていただけのSPDescriptorがinitializeされてしまった
  • HasIRCheckがfalseになっているとSelectionDAG側で検証コードを置いてしまうということか
  • →結局修正したけどうまくいかなかった
  • code:StackProtector.cpp
    • RequiresStackProtector() {
      • for (const BasicBlock &BB : *F)
        • for (const Instruction &I : BB)
          • if (const CallInst *CI = dyn_cast(&I))
            • if (CI->getCalledFunction() == - Intrinsic::getDeclaration(F->getParent(), - Intrinsic::stackprotector))
              • HasPrologue = true
  • これがじゃましてPrologueを生成しない=生成されるはずのAllocaInstもない→落ちる
  • llcに–enable-selectiondag-sp=falseをつけても落ちる
  • RequiresStackProtectorを読めばsspが適用される条件がわかるけれど、単純にllvm.stackprotectorという名前を使わないのがシンプル

  • 名前だけllvm.multicanaryにして、処理内容はそのままで実行してみる
  • やはり隅っこに追いやられる
  • function prologue/epilogue挿入時にstackのレイアウト(stack frame)は決定されるらしい
  • そこでstack frame indexというIDが使われる
    • MachineFrameInfo.h
  • 逆に、その時点までスタックの順番は決まっていない
  • getStackProtectorIndex()でgrepしてみると以下が出てきた
  • code:CodeGen/PrologEpilogInserter.cpp - // Make sure that the stack protector comes before the local variables on the - // stack. - SmallSet<int, 16> ProtectedObjs; - if (MFI.getStackProtectorIndex() >= 0) {

  • DAGを命令の配列にするときに(Lowering)うまいこと優先度を調整できればよいのだけれど
    • ScheduleDAGRRList
  • でもその解決のしかたはおかしいようにも思える
  • AllocaInstを拡張する以外にも、いくつか方法を見つけた
    • intrinsicを作る方法
    • DAGに順序関係を追加して並び替えられなくする方法
    • pseudo instructionを作る方法
      • この2つの方法ではclangを改造しなきゃいけない
      • でもFunctionPassでallocaを消してpseudo instructionに差し替えればいいのでは?
    • bundle
  • https://stackoverflow.com/questions/33005061/what-are-glue-and-chain-dependencies-in-an-llvm-dag
    • (If you’re implementing your own backend that requires two instructions to be adjacent to each other, you really want to be using a pseudoinstruction instead, and expand that after scheduling happens.)

  • http://lists.llvm.org/pipermail/llvm-dev/2014-June/074048.html
    • It “mostly” worked, but we kept

    • running into a long series of subtle issues. I strongly suggest you

    • use the pseudo op approach. That has worked fairly well for us.

  • http://lists.llvm.org/pipermail/llvm-dev/2016-April/098366.html
    • Maybe I don’t follow exactly what you’re trying to do but it seems like

    • something you can solve with an intrinsic that you can put in an SDAG

    • pattern and create a builtin for clang to emit this intrinsic. https://eli.thegreenplace.net/2012/11/24/life-of-an-instruction-in-llvm https://www.slideshare.net/chimerawang/llvm-register-allocation-2nd-version http://lists.llvm.org/pipermail/llvm-dev/2016-November/107130.html

  • llvmのチュートリアルにあるような内容はstackoverflowにあるけれど、ちょっと変わったことしようとするとMLばっかりになる

  • それか「余分のallocaする」方法
  • Intrinsicを作ってMultiCanaryでallocaをそれに置き換える
  • struct type?
  • なぜllvm.stackprotectorの第二引数はllvm_ptrptrなのだろうか
    • そもそも、%StackGuardSlotはなぜalloca i8*なのだろうか
  • Intrinsicを処理する3つの部分
    • IRTranslator::translateKnownIntrinsic→
    • SelectionDAGBuilder::visitIntrinsicCall→
    • この2つの役割分担がよくわからないのでgdbで見てみる
      • 下のfastLowerIntrinsicCallしか呼ばれなかった
    • X86FastISel::fastLowerIntrinsicCall→別にいらなさそう コメントにもFIXME: Handle more intrinsicsって書いてる
      • ここにreturn falseを入れたらSelectionDAGBuilderのほうが呼ばれた
  • allocaInstをvolatileにしたい
    • あとにstoreInst volatileを置くことでなんとかしてみたがstackprotectorで落ちた(getValueでのnullptr dereference)
  • pseudo-instruction == pseudo-op?
  • code:bash
    • $ cat hello_noguard_opt_llc.txt | rg -e ‘sched|pseudo’ -i - Expand ISel Pseudo-instructions - Machine Instruction Scheduler - Post-RA pseudo instruction expansion pass - X86 pseudo instruction expansion pass - Post RA top-down list latency scheduler
  • Expand ISel Pseudo-instructions
    • X86TargetLowering::EmitInstrWithCustomInserterで処理される
    • たとえばretpoline, tcreturn
    • retpolineどこかで聞いたことあるなと思ったらspectreの対処方だった https://reviews.llvm.org/D41723
    • Machine Instruction Schedulerの前だから多分ここに入れても意味ないんだよな
  • Post-RA pseudo instruction expansion pass
    • X86InstrInfo::expandPostRAPseudoで処理される
    • RA = register allocation なので、reorderingも終わっているはず
    • たとえばX86::V_SETALLONES わからん
  • Agg->getType PointerTy
  • Val->getType PointerTy
  • AllocaInstで確保した領域そのものは存在しない(?)のでinsertvalueではなくgetelementptr + storeで対応しているということか?
    • getTypeしても30 x i8ではなく30 x i8*が返ってしまうのでArrayTypeと認識されない
  • できた
  • ビルドしてみる
  • code:bash
    • sei0o@sei0oarch ~/D/l/twobuf> gcc –verbose twobuf_opt.s
    • gcc version 8.2.1 20180831 (GCC)
    • COLLECT_GCC_OPTIONS=’-v’ ‘-mtune=generic’ ‘-march=x86-64’
      • as -v –64 -o /tmp/ccQc8zBQ.o twobuf_opt.s
    • /usr/bin/ld: /tmp/ccQc8zBQ.o: relocation R_X86_64_32 against `.rodata.str1.1’ can not be used when making a PIE object; recompile with -fPIC
    • /usr/bin/ld: final link failed: nonrepresentable section on output
    • collect2: error: ld returned 1 exit status
  • えー
  • MultiCanaryなしの普通のバージョンですらコンパイルできない←!?
  • clang/gccを直接呼び出せばもちろんコンパイルできる
  • どんどん怪しいところをC言語のソースから削っていった結果、これでもダメなことがわかった
    • code:two.c
      • #include
      • int main() {
        • int a;
        • scanf(“%d”, &a);
        • return 0;
      • }
  • でもhello.cは通るから、何が違うんだろうといろいろ試してみるとif文の有無だった
    • code:これはOK.c
      • #include
        • int main() {
          • int a;
          • scanf(“%d”, &a);
          • return 0;
        • }
  • ifがあるとBasicBlockが分かれる→

  • 結局愛媛回では「余分にalloca」でデモ
  • twobuf/twobuf_opt.llを参照

  • Canaryについての勘違い
    • code:twobuf.S - 0x0000117e 488945f8 mov qword rbp - 8, rax - 0x00001182 64488b042528. mov rax, qword fs:0x28 - 0x0000118b 8a00 mov rax, qword rax // なんでこんなの入れちゃったんだろう
  • Value, LoadInstあたりの対応がよくわからない
  • stack_chk_failに飛ばすのがもったいないなあ
  • Loweringとは結局LLVM IRをMIRのレベルに落とし込むということだろうか

  • https://llvm.org/docs/Contributing.html beginnerとかあるのか やってみたい
  • https://www.slideshare.net/KuanHsuChenZakk/instruction-scheduling-algo-and-implementation-in-llvm むずい
  • https://jonathan2251.github.io/lbd/llvmstructure.html

  • この差はなんだろう
  • code:bash
    • sei0o@sei0oarch ~/D/llvm-experiment> ../llvm-build/bin/lli hello_noguard_opt.ll -o a
    • 3 9999999999999999999999999999999999999999999999999999999999999999999999999999999999
    • Hello, world! 960051513 ←ここと
    • x isn’t 3
    • ** stack smashing detected **: terminated
    • fish: “../llvm-build/bin/lli hello_nog…” terminated by signal SIGSEGV (Address boundary error)

    • sei0o@sei0oarch ~/D/llvm-experiment> ./hello
    • 3 9999999999999999999999999999999999999999999999999999999999999999999999999999999999
    • Hello, world! 3 ←ここ
    • x is 3
    • ** stack smashing detected **: terminated
    • fish: “./hello” terminated by signal SIGABRT (Abort)
  • llcでコンパイルしてから動かすと同じ挙動になったのでJIT領域とかそういう違いかな

  • gdbでスタック見てみようと思ったらなんか出た
 gdb-peda$ c
 Continuing.
 [Attaching after Thread 0x7ffff77fa740 (LWP 8077) vfork to child process 8081]
 [New inferior 2 (process 8081)]
 [Thread debugging using libthread_db enabled]
 Using host libthread_db library "/usr/lib/libthread_db.so.1".
 [Detaching vfork parent process 8077 after child exec]
 [Inferior 1 (process 8077) detached]
 process 8081 is executing new program: /home/sei0o/Devs/llvm-build/bin/llvm-symbolizer
 breakpoint.c:13157: internal-error: void delete_breakpoint(breakpoint*): Assertion `bpt != NULL' failed.
 A problem internal to GDB has been detected,
 further debugging may prove unreliable.
 
 This is a bug, please report it.  For instructions, see:
 <http://www.gnu.org/software/gdb/bugs/>.
 
 fish: “gdb -q ../llvm-build/bin/lli” terminated by signal SIGABRT (Abort)
 /home/sei0o/Devs/llvm-build/bin/lli(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x33)[0x555556e7ded5]
 /home/sei0o/Devs/llvm-build/bin/lli(+0x1929f68)[0x555556e7df68]
 /home/sei0o/Devs/llvm-build/bin/lli(_ZN4llvm3sys17RunSignalHandlersEv+0x99)[0x555556e7c137]
 /home/sei0o/Devs/llvm-build/bin/lli(+0x1929743)[0x555556e7d743]
 /usr/lib/libpthread.so.0(+0x123c0)[0x7ffff7f9a3c0]
 /usr/lib/libc.so.6(gsignal+0x10f)[0x7ffff7836d7f]
 /usr/lib/libc.so.6(abort+0x125)[0x7ffff7821672]
 /usr/lib/libc.so.6(+0x7a878)[0x7ffff7879878]
 /usr/lib/libc.so.6(+0x10d415)[0x7ffff790c415]
 /usr/lib/libc.so.6(+0x10d3c6)[0x7ffff790c3c6]
 [0x7ffff7fcd0d3]
 /home/sei0o/Devs/llvm-build/bin/lli(_ZN4llvm5MCJIT11runFunctionEPNS_8FunctionENS_8ArrayRefINS_12GenericValueEEE+0x766)[0x5555569e732a]
 /home/sei0o/Devs/llvm-build/bin/lli(_ZN4llvm15ExecutionEngine17runFunctionAsMainEPNS_8FunctionERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EEPKPKc+0x4a6)[0x5555569468fc]
 /home/sei0o/Devs/llvm-build/bin/lli(main+0x1a98)[0x5555561a22f3]
 /usr/lib/libc.so.6(__libc_start_main+0xf3)[0x7ffff7823223]
 /home/sei0o/Devs/llvm-build/bin/lli(_start+0x2e)[0x55555619f1ae]
 Stack dump:
 0.	Program arguments: /home/sei0o/Devs/llvm-build/bin/lli hello_noguard_opt.ll 

Backlinks