The code will look for any/all pointer function arguments and will insert an assert(ptr != NULL); statement. It shows looking at functions, their arguments, a function pass, declaring a function, and inserting code. Why? Eh. A few reasons that are BS, but mostly to help learn API. ## Build and Run This requires LLVM and Clang 3.8, 3.9, or 4.0 releases. You should review the Makefile to setup the LLVM path and version. ``` $ make $ make tests $ cd tests ``` If you do not specify a configuration file, the code will look for all functions and their arguments. If you specify a configuration file, it will specify the function and the argument to check. The tests/ex0*b.... files are those in which a configuration file was specified and the ex0*a are those in which none was specified.. so you should see a difference ### Example running by hand ``` $ clang -g -emit-llvm -c -o FOO.bc FOO.c $ opt -load built/libnpassert.so -null-ptr-assert -o FOO_assertall.bc < FOO.bc $ opt -load built/libnpassert.so -null-ptr-assert -npa-target-config FOO.cfg -o FOO_assertbyconfigfile.bc < FOO.bc $ clang -g -o FOO_assertall FOO_assertall.bc $ clang -g -o FOO_assertbyconfigfile FOO_assertbyconfigfile.bc ``` The last clang steps generate an runnable executable. Use llvm-dis on bitcode (.bc) files to get the human readable IR to view the differences. One may also use the -npa-use-function option which will tell the pass to create a separate function to perform the assertion in. So with the above instead of getting a crash like: ``` (gdb) r Starting program: /home/hoser/code/npassert/test/ex02 Program received signal SIGSEGV, Segmentation fault. 0x0000000000400549 in foo (s=0x0) at test/ex02.c:16 16 return s->one; (gdb) disass foo Dump of assembler code for function foo: 0x0000000000400530 <+0>: push %rbp 0x0000000000400531 <+1>: mov %rsp,%rbp 0x0000000000400534 <+4>: sub $0x10,%rsp 0x0000000000400538 <+8>: mov %rdi,-0x8(%rbp) 0x000000000040053c <+12>: callq 0x400420 0x0000000000400541 <+17>: mov %rax,-0x10(%rbp) 0x0000000000400545 <+21>: mov -0x8(%rbp),%rax => 0x0000000000400549 <+25>: mov (%rax),%eax 0x000000000040054b <+27>: add $0x10,%rsp 0x000000000040054f <+31>: pop %rbp 0x0000000000400550 <+32>: retq End of assembler dump. (gdb) ``` You would get a crash early in the function.. ``` (gdb) r Starting program: /home/hoser/code/npassert/test/ex02a Program received signal SIGSEGV, Segmentation fault. 0x0000000000400554 in foo (s=0x0) at test/ex02.c:12 12 { (gdb) disass foo Dump of assembler code for function foo: 0x0000000000400530 <+0>: push %rbp 0x0000000000400531 <+1>: mov %rsp,%rbp 0x0000000000400534 <+4>: sub $0x20,%rsp 0x0000000000400538 <+8>: cmp $0x0,%rdi 0x000000000040053c <+12>: mov %rdi,-0x8(%rbp) 0x0000000000400540 <+16>: jne 0x400558 0x0000000000400546 <+22>: xor %eax,%eax 0x0000000000400548 <+24>: mov %eax,%ecx 0x000000000040054a <+26>: mov %rsp,%rdx 0x000000000040054d <+29>: add $0xfffffffffffffff0,%rdx 0x0000000000400551 <+33>: mov %rdx,%rsp => 0x0000000000400554 <+36>: mov (%rcx),%eax 0x0000000000400556 <+38>: mov %eax,(%rdx) 0x0000000000400558 <+40>: mov %rsp,%rax 0x000000000040055b <+43>: add $0xfffffffffffffff0,%rax 0x000000000040055f <+47>: mov %rax,%rsp 0x0000000000400562 <+50>: mov %rsp,%rcx 0x0000000000400565 <+53>: add $0xfffffffffffffff0,%rcx 0x0000000000400569 <+57>: mov %rcx,%rsp 0x000000000040056c <+60>: mov -0x8(%rbp),%rdx 0x0000000000400570 <+64>: mov %rdx,(%rax) 0x0000000000400573 <+67>: mov %rax,-0x10(%rbp) 0x0000000000400577 <+71>: mov %rcx,-0x18(%rbp) 0x000000000040057b <+75>: callq 0x400420 0x0000000000400580 <+80>: mov -0x18(%rbp),%rcx 0x0000000000400584 <+84>: mov %rax,(%rcx) 0x0000000000400587 <+87>: mov -0x10(%rbp),%rax 0x000000000040058b <+91>: mov (%rax),%rdx 0x000000000040058e <+94>: mov (%rdx),%eax 0x0000000000400590 <+96>: mov %rbp,%rsp 0x0000000000400593 <+99>: pop %rbp 0x0000000000400594 <+100>: retq ``` Or if you add the -npa-use-function option ``` (gdb) r Starting program: /home/hoser/code/npassert/test/ex02c Program received signal SIGSEGV, Segmentation fault. 0x00000000004005b3 in __NPA_assert_8__ () (gdb) ``` it will fault in the assertion function.