Search code examples
c++cllvmllvm-clangllvm-ir

How can I set a breakpoint in LLVM's LowerTypeTests Pass?


I am trying to set a breakpoint in the LLVM code that generates jump tables in response to the -fsanitize=cfi-icall flag.

I have tried running indirect.c below through clang -flto -fsanitize=cfi-icall indirect.c -o indirect, and the resulting object file clearly contains jump tables in x86. Furthermore, the intermediate bitcode files emitted contain the string "CFI Canonical Jump Tables," which is only present in llvm/lib/Transforms/IPO/LowerTypeTests.cpp and llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp. However, I've built clang and opt from source with debugging symbols, and have not been able to hit the relevant code in either file in GDB or LLDB. The code is much more likely to be in LowerTypeTests.cpp since that's where jump table construction code occurs. Here's the code I'm using:

indirect.c:

int foo (int a) {
        return 2 * a;
};

int bar (int a) {
        return 3 * a;
}

int main(int argc, char* argv[]) {
        int (*func)(int) = foo;
        int (*func2)(int) = bar;
        int c = func(2);
}

And the jump tables in the x86:

0000000000400510 <__typeid__ZTSFiiE_global_addr>:
  400510:   e9 6b ff ff ff          jmpq   400480 <foo.cfi>
  400515:   cc                      int3   
  400516:   cc                      int3   
  400517:   cc                      int3   

0000000000400518 <bar>:
  400518:   e9 73 ff ff ff          jmpq   400490 <bar.cfi>
  40051d:   cc                      int3   
  40051e:   cc                      int3   
  40051f:   cc                      int3

The relevant code in LowerTypeTests.cpp:

bool lowertypetests::isJumpTableCanonical(Function *F) {
  if (F->isDeclarationForLinker())
    return false;
  auto *CI = mdconst::extract_or_null<ConstantInt>(
      F->getParent()->getModuleFlag("CFI Canonical Jump Tables"));
  if (!CI || CI->getZExtValue() != 0)
    return true;
  return F->hasFnAttribute("cfi-canonical-jump-table");
}

and in CodeGenModule.cpp:

if (LangOpts.Sanitize.has(SanitizerKind::CFIICall)) {
    getModule().addModuleFlag(llvm::Module::Override,
                              "CFI Canonical Jump Tables",
                              CodeGenOpts.SanitizeCfiCanonicalJumpTables);
  }

I'd appreciate if anyone could help me trigger this code in GDB or LLDB!


Solution

  • If you are setting a breakpoint in clang, first run your command with -v flag. It would give you proper incantation for -cc1:

    "/usr/bin/clang" -cc1 -triple x86_64-unknown-freebsd12.0 ... <very long command line>
    

    Pass this line to GDB and break wherever you like.