2

Maybe the most common bug in a beginner's program would be that it contains seg fault. But, when debugging with gdb, I cannot get what exactly the seg fault is and how exactly it happen. For example, the gdb debugger would give out thatprogram received SEGMENTATION FAULT or program receive SEGMENTATION FAULT, in main.c:13: bool flag=false. (actually I believe a program wouldn't receive seg fault because of a bool variable definition. There must be some other things) Something like that.

But that is not concrete and not informative enough. I want to know exactly which variable cause the seg fault and where its location is. For example, if I define a pointer A in a function with no initialization, and then use it afterward, mostly I would receive seg fault. I want the gdb tell me exactly that it is that variable A that cause the seg fault and its value and location is...

Any idea?

walkerlala
  • 1,599
  • 1
  • 19
  • 32

2 Answers2

1

Well, I will take a simple example as follows.

#include <stdio.h>

void main()
{
int *p=NULL;
printf("I Should be coring now");
printf("%d", *p);
}

As you can probably guess, there is problem in printf("%d", *p);, however it would not be shown clearly in gdb's output.

bash-4.1$ gdb test
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.SCLC6_4.1.R1.1.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /tmp/test...done.
(gdb) run
Starting program: /tmp/test

Program received signal SIGSEGV, Segmentation fault.
0x080483e6 in main () at test.c:7
7       printf("%d", *p);

In this trivial case, it is quite straight-forward. But for name sake, let us assume that, we need more information. So let us now try to find the pc while the SIGSEGV had occured. The pc effectively says that, while executing that particular instruction, core occured.

Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.107.SCLC6_4.5.R1.1.1.i686
(gdb) info registers
eax            0x0      0
ecx            0xbffff6f8       -1073744136
edx            0x2c5340 2904896
ebx            0x2c3ff4 2899956
esp            0xbffff710       0xbffff710
ebp            0xbffff738       0xbffff738
esi            0x0      0
edi            0x0      0
eip            0x80483e6        0x80483e6 <main+34>
eflags         0x10292  [ AF SF IF RF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51

So in our case, the pc is eip 0x80483e6 0x80483e6 <main+34>

It is now clear that, while executing the instruction that is at offset 34 from main, the core had occured. So now, the important issue is to map this instruction with highlevel language. For which use the disasm command as follows.

(gdb) disas /m main
Dump of assembler code for function main:
4       {
   0x080483c4 <+0>:     push   %ebp
   0x080483c5 <+1>:     mov    %esp,%ebp
   0x080483c7 <+3>:     and    $0xfffffff0,%esp
   0x080483ca <+6>:     sub    $0x20,%esp

5       int *p=NULL;
   0x080483cd <+9>:     movl   $0x0,0x1c(%esp)

6       printf("I Should be coring now");
   0x080483d5 <+17>:    mov    $0x80484c4,%eax
   0x080483da <+22>:    mov    %eax,(%esp)
   0x080483dd <+25>:    call   0x80482f4 <printf@plt>

7       printf("%d", *p);
   0x080483e2 <+30>:    mov    0x1c(%esp),%eax
=> 0x080483e6 <+34>:    mov    (%eax),%edx
   0x080483e8 <+36>:    mov    $0x80484db,%eax
   0x080483ed <+41>:    mov    %edx,0x4(%esp)
   0x080483f1 <+45>:    mov    %eax,(%esp)
   0x080483f4 <+48>:    call   0x80482f4 <printf@plt>

8       }
   0x080483f9 <+53>:    leave
   0x080483fa <+54>:    ret

End of assembler dump.
(gdb)

Though this might not work out of the box , it will give close to 90% accuracy, as far as I have seen from my experience.

kspviswa
  • 637
  • 3
  • 13
  • Really appreciate your answer. I have learned a lot from that. But, by the way, what is `pc` in your answer? And, what is the exact meaning of those `eip` ,`esp`,`ebp` ....when you type command `info register`?(though I know what a register is, I really don't know what they mean. – walkerlala Jun 26 '15 at 09:36
  • also, if you may, could you please answer another question about `gdb`of mine?http://stackoverflow.com/questions/30959819/want-to-watch-consistently-and-examine-occasionally-the-variable-outside-the-cur I have try the solution provided in the answer there, but, that solution(`wat -location var`) seem to cause me `seg fault` most of the time – walkerlala Jun 26 '15 at 09:39
0

Backtrace (bt) together with line of source / printout of variables is often enough to diagnose what caused the issue. For this you need to build with debug information and without most optimizations (-O0 -g3 in GCC).

Or try some different tool, like Valgrind, which makes diagnosing memory allocation issues much easier.

dbrank0
  • 9,026
  • 2
  • 37
  • 55