Monday, March 9, 2009

Crash'em all

NOTE:- This is a high end technical post.... if you are really not into it, I really don't care of the total hits :)

It's been a long time since I've been working on a new library. I wont be opening the flood gates by letting all information flow... but still show you some glimpses of how technology has changed in this all so complex Open Source business.

What generally happens when your program crashes... well most of you think it in terms of "Hanging of the binary" and it's consequential termination by the Kernel.
The kernel does so when it sees that the binary is either trying to occupy some domain not in it's program stack space or when it tries to access pointer to some restricted space.

Now it's an interesting fact that most of you might not know.... whenever a program is executing, the processor takes one instruction at a time( for the time being the instruction can be thought of as a line in the program ). It's interesting to note that, what all happens is that the program counters, it's activations records and other state variables move from one state to other. Changing the configuration continuously. And yes... you can capture each configuration seperately. Have a look at this C file:

#include
#include

void bug();

int main(int argc, char *argv[])
{
int a=0,b=1,c=2;
printf("till here everthing is fine %d %d %d",a,b,c);
bug(); //wooo... crash
printf("dont hope to reach here :P");
return 0;
}

void bug(){

int i,a[10];

for(i=0;i<1000;i++) style="color: rgb(51, 51, 255);">sanket@sanket-laptop:~$ gdb ./a.out

GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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 "i486-linux-gnu"...
(gdb) b main
Breakpoint 1 at 0x8048385: file bug_c.c, line 8.
(gdb) r
Starting program: /home/sanket/a.out

Breakpoint 1, main () at bug_c.c:8
8 int a=0,b=1,c=2;
(gdb) s
9 printf("till here everthing is fine %d %d %d",a,b,c);
(gdb) s
10 bug(); //wooo... crash
(gdb) s
bug () at bug_c.c:17
17 int *a=NULL;
(gdb) s
20 a=10; //my classic was to trigger bug.. unless kernel is too generous :D
(gdb) s
21 printf("%d",*a);
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x080483f1 in bug () at bug_c.c:21
21 printf("%d",*a);
(gdb) bt full
#0 0x080483f1 in bug () at bug_c.c:21
a = (int *) 0xa
#1 0x080483c0 in main () at bug_c.c:10
a = 0
b = 1
c = 2

The interesting thing here is the command bt full, which displays the position of the function while it crashed. Clearly, we had a crash in bug() followed by that in main() and the backtrace has two function calls as it is evident.

This information is extremely essential when debuggers/programmers set out to solve a bug. This trace has a lot more to it then it'll look at first... just for instance look at this trace( it's a crash of a proprietry software ;) )

(gdb) core-file core
(no debugging symbols found)
Core was generated by `/media/disk/iViz/project/avgscan avg_poc.exe'.
Program terminated with signal 11, Segmentation fault.
[New process 31608]
#0 0xb7d1b4e7 in ?? ()
(gdb) bt full
#0 0xb7d1b4e7 in ?? ()
No symbol table info available.
#1 0x080809c4 in ?? ()
No symbol table info available.
#2 0x080826f2 in ?? ()
No symbol table info available.
#3 0x08052651 in ?? ()
No symbol table info available.
#4 0x08053753 in ?? ()
No symbol table info available.
#5 0x08053a82 in ?? ()
No symbol table info available.
#6 0x0806bf7f in ?? ()
No symbol table info available.
#7 0x081685b2 in ?? ()
No symbol table info available.
#8 0x08168b19 in ?? ()
No symbol table info available.
#9 0x0816976b in ?? ()
No symbol table info available.
#10 0x0818898e in ?? ()
No symbol table info available.
#11 0x081894f9 in ?? ()
---Type to continue, or q to quit---
No symbol table info available.
#12 0x0818b331 in ?? ()
No symbol table info available.
#13 0x0817c20f in ?? ()
No symbol table info available.
#14 0x0817d51f in ?? ()
No symbol table info available.
#15 0x08192df5 in ?? ()
No symbol table info available.
#16 0x08193348 in ?? ()
No symbol table info available.
#17 0x0818c1a7 in ?? ()
No symbol table info available.
#18 0x0818d18f in ?? ()
No symbol table info available.
#19 0x08158429 in ?? ()
No symbol table info available.
#20 0x08151006 in ?? ()
No symbol table info available.
#21 0x08151d40 in ?? ()
No symbol table info available.
#22 0x0815301d in ?? ()
No symbol table info available.
---Type to continue, or q to quit---
#23 0xb7cbe450 in ?? ()
No symbol table info available.
#24 0x0804e4f1 in ?? ()
No symbol table info available.
(gdb)

some more information that can be useful:

(gdb) info all-registers
eax 0x0 0
ecx 0x35427516 893547798
edx 0x0 0
ebx 0xd50bd000 -720646144
esp 0xbfffdee8 0xbfffdee8
ebp 0xbfffdf28 0xbfffdf28
esi 0xd50bd000 -720646144
edi 0x834b000 137670656
eip 0xb7d1b4e7 0xb7d1b4e7
eflags 0x10246 [ PF ZF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
st0 0 (raw 0x00000000000000000000)
st1 0 (raw 0x00000000000000000000)
st2 0 (raw 0x00000000000000000000)
st3 0 (raw 0x00000000000000000000)
st4 0 (raw 0x00000000000000000000)
st5 0 (raw 0x00000000000000000000)
st6 39855 (raw 0x400e9baf000000000000)
---Type to continue, or q to quit---
st7 39855.5 (raw 0x400e9baf800000000000)
fctrl 0x37f 895
fstat 0x4020 16416
ftag 0xffff 65535
fiseg 0x73 115
fioff 0x81fe18a 136307082
foseg 0x7b 123
fooff 0xbfffe960 -1073747616
fop 0x59d 1437
xmm0 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
xmm1 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
xmm2 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
xmm3 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
---Type to continue, or q to quit---
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
xmm4 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
xmm5 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
xmm6 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
xmm7 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0},
v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0},
uint128 = 0x00000000000000000000000000000000}
mxcsr 0x1f80 [ IM DM ZM OM UM PM ]
mm0 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0,
0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm1 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0,
0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
---Type to continue, or q to quit---
mm2 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0,
0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm3 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0,
0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm4 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0,
0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm5 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0,
0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm6 {uint64 = 0x9baf000000000000, v2_int32 = {0x0, 0x9baf0000},
v4_int16 = {0x0, 0x0, 0x0, 0x9baf}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xaf, 0x9b}}
mm7 {uint64 = 0x9baf800000000000, v2_int32 = {0x0, 0x9baf8000},
v4_int16 = {0x0, 0x0, 0x8000, 0x9baf}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0,
0x80, 0xaf, 0x9b}}
(gdb)

Newayz the registers are really important though you may not even get a sniff from the above depiction. Another interesting output I want you to see... just refer to the first program:

sanket@sanket-laptop:~$ gdb ./a.out
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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 "i486-linux-gnu"...
(gdb) breakpoint main
Breakpoint 1 at 0x8048385: file bug_c.c, line 8.
(gdb) run
Starting program: /home/sanket/a.out

Breakpoint 1, main () at bug_c.c:8
8 int a=0,b=1,c=2;
(gdb) s
9 printf("till here everthing is fine %d %d %d",a,b,c);
(gdb) bt full
#0 main () at bug_c.c:9
a = 0
b = 1
c = 2
(gdb) info sharedlibrary
From To Syms Read Shared Object Library
0xb7fe47f0 0xb7ff979f Yes /lib/ld-linux.so.2
0xb7e90230 0xb7f90d84 Yes /lib/tls/i686/cmov/libc.so.6
(gdb) info locals
a = 0
b = 1
c = 2
(gdb)

What I've done is... stopped the program flow at a certain point( by use of breakpoints ) stepped through a few lines and shown you the state of the program... wow!! You can get what the program is doing at any damn stage of execution :P. You might want to play with it.... and debug and do whatever you want to :D:D


All that I've shown you is the importance of a Backtrace... what exactly it implies and what it has in store of interested parties!!



No comments:

Post a Comment