How To Add Debug Info To Autogenerated C Code


I just recently learned about the #line directive in C/C++. This is not a very well known feature (that is, I've never heard about it until now), but is very useful for people writing compilers that export C code.


Why Would You Need This?


Suppose you have the following programming language:


print("Hello world!")

You might chose to use C as your compilation target, which means anyone with a C compiler can compile and run your programming language! Given the above example, your compiler might output the following C code:


#include <stdio.h>

int main(void) {
  puts("Hello world!");
}

All you need to do compile and run it is:


$ cc file.c -g
$ ./a.out
Hello world!

The -g flag is what adds the debug info

Great! But what happens when you try debugging this?


$ gdb a.out -q
Reading symbols from a.out...
(gdb) b main
Breakpoint 1 at 0x113d: file file.c, line 4.
(gdb) r
Starting program: a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Breakpoint 1, main () at file.c:4
4         puts("Hello world!");
(gdb)

The issue is that the debugger is using the line numbers of our C program, not our original program. This also means that the user will be debugging the generated C code, which probably isn't what we want.


The Solution


To fix this, include a #line directive for every line that you want to have different line numbers on:


#include <stdio.h>

#line 1 "file.dsl"
int main(void) {
  #line 1 "file.dsl"
  puts("Hello world!");
}

Here file.dsl is the source file for our custom DSL (Domain Specific Language).


Now, when we recompile and debug we get the following:


$ gdb a.out -q
Reading symbols from a.out...
(gdb) b main
Breakpoint 1 at 0x113d: file file.dsl, line 1.
(gdb) r
Starting program: a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Breakpoint 1, main () at file.dsl:1
1       print("Hello world!")
(gdb)

Ta da! Now the debugger shows the correct source line and line number for our code!