Introduction

As long as the gcc tells you whats wrong (including the -Wall Flag) you can at least barely locate the source of the error. What about Segmentation Faults which are hard to detect during compilation time? The GNU Debugger may give you a clue!

The GNU Debugger (short: gdb) is a command line tool which allows to debug a compiled binary. Especially when the binary was compiled with Debug Information, the debugger can tell us a bit more about its behaviour.

Starting over with SegFault

For example look at the following code which provocates a SegFault by writing to unallocated memory.

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 
 
void getLyrics(char* lyricBuffer){ 
 
 char *segFaultLyrics = "SegFault, SegFault! Whatcha gonna do? Whatcha gonna do when I come for you?";
 memcpy(lyricBuffer, segFaultLyrics, strlen(segFaultLyrics)); 
} 
 
int main() 
{ 
 char* lyrics = NULL; 
 getLyrics(lyrics); 
 printf("%s\n",lyrics);                                                                                   
}

Let’s compile it with gcc and see what happens on execute.

$ gcc -Wall debugme1.c -o debugme1
$ ./debugme1
Segmentation fault (core dumped)

Gcc didn’t complain anything, even with the -Wall Flag.

In order to start over with the gdb, we have to compile our program with debug information. This can be acheived by adding the -g Flag to the gcc parameter list.

$gcc -Wall debugme1.c -g -o debugme1
$gdb debugme1
Reading symbols from debugme1...done.
(gdb) r
Starting program: ~/debugme/debugme1

Program received signal SIGSEGV, Segmentation fault.
__memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:100
100     ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S: No such file or directory.

As you can see, the gdb tells you which library-function causes the error. What we can’t see is the location of this faulty library-function call in our source code.  The No such file or directory error can be ignored with the assumption that our call of this function is wrong and not the original source[1].
This can be accomplished with the gdb command bt (back-trace).

(gdb) bt
#0 __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:100
#1 0x000000000040060c in getLyrics (lyricBuffer=0x0) at debugme1.c:8
#2 0x000000000040062b in main () at debugme1.c:14

The back trace will print the last call stack where the faulty function is on the top. In our example we have to look at the function getLyrics in line 8 which will be the memcpy call.

 Division by zero

Imagine you worked out a fancy formula which solve a certain problem. Especially when you use fractions you have to take care of the range of the input values.
The following code will implement a formula which doesn’t care about the input value. The compiler doesn’t either.

#include <stdio.h>            
#include <stdlib.h>           
                              
int magicFormula(int a, int b)
{                             
    return a/b;               
}                             
                              
int main()                    
{                             
    int n = magicFormula(1,0);
    printf("%d\n",n);         
}

This will cause a Floating Point Exception. This isn’t directly a Divison-By-Zero Bug. If you would change the datatype from intto float , this operation would be result inf for infinity. But a float  with the value inf can’t be casted into an integer. However, we will ask the gdb if he can help us out again.

$gdb debugme2
Reading symbols from debugme2...done.
(gdb) r
Starting program: ~/debugme/debugme2

Program received signal SIGFPE, Arithmetic exception.
0x0000000000400534 in magicFormula (a=1, b=0) at debugme2.c:6
6           return a/b;

In order to see more than the faulty line, we can use the gdb-command l  to list. This will maybe give us the context and a hint why the method magicFormula failed with a=1  and b=0

(gdb) l
1       #include <stdio.h>
2       #include <stdlib.h>
3
4       int magicFormula(int a, int b)
5       {
6           return a/b;
7       }
8
9       int main()
10      {

Tips ‘n’ Tricks

  • Your Application foo needs arguments bar and bbar? Try this: gdb –args foo bar bbar
  • More Debug Information with the gcc-Flag -g3 (My very short examples hadn’t had more information..)
  • There is a console-based gui included in gdb which can be opened with gdb -tui
  • The bash command strip <your binary>  will remove all debug information which the gcc has included into your binary
  • The gcc can generate gdb-friendly debug information with -ggdb (https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html)

[1] If you think the memcpy is wrong and want to debug it, take a look at this SO Post.

Hits: 1183