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!
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.