I'm trying to use -ftrap-function flag from clang manual to catch CFI (call frame information) errors in a custom handler.
Here is a basic example generating a CFI error:
#include <stdio.h>
#include <stdlib.h>
__attribute__((used)) extern "C" void CatchCfi() {
printf("catched\n");
}
struct Foo {
Foo(const char* s) : command(s) {}
virtual ~Foo() {}
void fooStuff() { printf("fooStuff\n"); }
const char* command;
};
struct Bar {
Bar(const char* s) : name(s) {}
virtual ~Bar() {}
void barStuff() { printf("barStuff\n"); }
const char* name;
};
enum class WhichObject { FooObject, BarObject };
static void* allocator(WhichObject w, const char* arg) {
switch (w) {
case WhichObject::FooObject:
return new Foo(arg);
case WhichObject::BarObject:
return new Bar(arg);
}
}
int main(int argc, const char* argv[]) {
void* ptr = nullptr;
(void)(argc);
(void)(argv);
ptr = allocator(WhichObject::BarObject, "system(\"/bin/sh\")");
Foo* fooptr = static_cast<Foo*>(ptr);
fooptr->fooStuff();
printf("not printed when compiled with -O2\n");
return 0;
}
I build it with these CFI related clang options:
-ftrap-function=CatchCfi -fsanitize=cfi-vcall -fvisibility=hidden -fsanitize=cfi-derived-cast -fsanitize=cfi-unrelated-cast -flto=thin
When this example is built without optimization it works as I want. Output:
catched
fooStuff
not printed when compiled with -O2
The problem appear when I build it with -O2 option:
catched
Trace/breakpoint trap (core dumped)
GDB shows that the program is receiving SIGTRAP just after CatchCfi returns:
(gdb) r
Starting program: /home/romex/browser/src/out/debug/hello_cfi
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
catched
Program received signal SIGTRAP, Trace/breakpoint trap.
0x000000000020118a in ?? ()
(gdb) bt
#0 0x000000000020118a in ?? ()
#1 0x00000000002010f0 in frame_dummy ()
#2 0x00007ffff748e830 in __libc_start_main (main=0x201180 <main(int, char const**)>, argc=1, argv=0x7fffffffde18, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffde08) at ../csu/libc-start.c:291
#3 0x0000000000201029 in _start ()
Warning: the current language does not match this frame.
(gdb)
How to fix that? I'm wondering if somebody has a success story dealing with ftrap-function flag? May be there is some specific optimization flag fixing this error? Thanks.