In this short article I will show you how to create an executable file as well as produce debug information but in a completely separate file. There has been a number of times when I wanted to understand what went wrong with a program but debug information was not available. Without debug information it is nearly impossible to make sense of what happened. This holds true especially for larger programs. Today we will work with something super simple: { (n== ) { ; } { n * factorial(n ); } } { x = factorial( ); (x) { : ; : ; } ; } int factorial ( n) int if 1 return 1 else return -1 int main ( argc, **argv) int char int 5 switch case 120 return 0 default return -1 return -1 Save this into a file called . main.c We can now use c compiler to produce an executable: gcc -o fact main.c This gives us a binary file, but unfortunatelly there's no debug information in it. If we run a program like this in production and for whatever reason need to debug this program to understand what's wrong we're out of luck. I understand that some of you may say - "hey, you should never debug programs in production" but there will be situations where that's the only way. Ideally, programs should be so good by the time they go to production that they don't fail. In a future post, I'll talk more about how to do understand failures in production. For now, you will need to trust me that to truly understand failure of a system you will need to inspect that system. Now let's compile this program with debug info: gcc -g -Og -o fact-debug main Now we can use (or ) to look at section headers in two binaries . With a bit of and wizardry you will notice that debug version of the binary has a few more sections: , , , and . eu-readelf readelf sed readelf debug_aranges debug_info debug_abbrev debug_line debug_str If you try using to step through binary (one that doesn't include debug info) you will notice that there's no source code that you can use to step through. You can step through the program and understand what's happening from disassembly but it will be hard to make sense. On the other hand, if you use gdb to run fact-debug binary (one that includes debug information) you will notice that you can see source code while stepping through. gdb fact Now let's extract debug information from fact-debug binary and put it in another file. That can be done using and command: obj-copy eu-strip objcopy --only-keep-debug fact-debug fact-debug-info eu-strip -g fact-debug Now you have the best of both worlds - an executable file that does not include debug information as well as access to debug information if the need arises. As a teaser to my next article, I encourage you to check out associated with the executable. It can be retrieved using . build-id eu-readelf -n fact-debug I'll show you how to put it to good use using the latest . gdb