This is the mail archive of the
cygwin@cygwin.com
mailing list for the Cygwin project.
Solved, sort of: dumper 1.10 not giving expected stack trace in gdb
- From: Robert Baruch <autophile at zoominternet dot net>
- To: cygwin at cygwin dot com
- Date: Sun, 04 Jan 2004 16:32:35 -0500
- Subject: Solved, sort of: dumper 1.10 not giving expected stack trace in gdb
- References: <3FF1F041.9010506@zoominternet.net> <Pine.GSO.4.56.0312302135360.18706@slinky.cs.nyu.edu> <3FF2414D.8060507@zoominternet.net> <20031231063511.GA2113@redhat.com> <3FF2ED39.9080003@zoominternet.net> <20031231170224.GA3881@redhat.com> <3FF356E2.5000304@zoominternet.net> <3FF43815.8050201@zoominternet.net>
Hi all,
I have a suboptimal solution for getting a good stack trace in gdb.
First, DO NOT use dumper as the error_start program. Set
CYGWIN='error_start=C:\windows-path-to-gdb\gdb.exe'.
When an abort occurs, gdb will start.
Next, do info thread to find all the threads. Chances are the aborted
thread is thread 1. Then do thread 1 to change thread context to the
right one:
(gdb) info thread
* 3 thread 3496.0xf54 0x77f75a59 in ntdll!DbgUiConnectToDbg ()
from /cygdrive/c/WINDOWS/System32/ntdll.dll
2 thread 3496.0xd6c 0x7ffe0304 in ?? ()
1 thread 3496.0xe24 0x7ffe0304 in ?? ()
(gdb) thread 1
[Switching to thread 1 (thread 3496.0xe24)]#0 0x7ffe0304 in ?? ()
(gdb) bt
#0 0x7ffe0304 in ?? ()
#1 0x77f5c534 in ntdll!ZwWaitForSingleObject ()
from /cygdrive/c/WINDOWS/System32/ntdll.dll
#2 0x77e7a62d in WaitForSingleObjectEx ()
from /cygdrive/c/WINDOWS/system32/KERNEL32.DLL
#3 0x00000778 in ?? ()
Note that the Backtrace Sucks(TM).
Next, take a look at 64 bytes of stack using x/64x $esp:
(gdb) x/64x $esp
0x22fca4: 0x77f5c534 0x77e7a62d 0x00000778 0x00000000
0x22fcb4: 0x0022fccc 0x00000778 0x0000ea60 0x0022fd30
0x22fcc4: 0x77f7d417 0x0022fccc 0xdc3cba00 0xffffffff
0x22fcd4: 0x7ffdf000 0x7ffde000 0x00000014 0x00000001
0x22fce4: 0x00000000 0x00000000 0x00000010 0x0022fcb8
0x22fcf4: 0x0022fd4c 0x0022ff28 0x77e94809 0x77e83ae0
0x22fd04: 0x00000000 0x0022fd58 0x77e7ac21 0x00000778
0x22fd14: 0x0000ea60 0x00000000 0x61073611 0x00000778
0x22fd24: 0x0000ea60 0xffffffff 0x77f59037 0x00000000
0x22fd34: 0x00240000 0x00000000 0x00244348 0x0022fe2c
0x22fd44: 0x0000c000 0x77f5c014 0x00000000 0x00000001
0x22fd54: 0x00000780 0x0022fde8 0x61071c99 0x00000780
0x22fd64: 0x00000001 0x00000000 0x00000000 0x00000000
0x22fd74: 0x0022fd90 0x0000003f 0x00401324 0x0000c000
0x22fd84: 0x0022fd90 0x0000003f 0x00000000 0x61616161
0x22fd94: 0x61416141 0x61616161 0x61126ac0 0x61616161
Also take a look at the current frame pointer via p/x $esp:
(gdb) p/x $ebp
$1 = 0x22fd08
The format of a frame in the stack is as follows:
Current function local vars
Previous frame pointer <- $ebp
Return address
Current function args
We're going to simulate a function return by changing the frame pointer
to the previous frame pointer, and the instruction pointer to the return
address. In the stack dump, look at what the stack contains at the
address of $ebp and $ebp+4:
(gdb) p/x *(int *)$ebp
$2 = 0x22fd58
(gdb) p/x *(int *)($ebp+4)
$3 = 0x77e7ac21
So to simulate a function return, we have to set $ebp to the first
value, and $eip to the second value:
(gdb) set $ebp=0x22fd58
(gdb) set $eip=0x77e7ac21
(gdb) bt
#0 0x77e7ac21 in WaitForSingleObject ()
from /cygdrive/c/WINDOWS/system32/KERNEL32.DLL
#1 0x77f5c534 in ntdll!ZwWaitForSingleObject ()
from /cygdrive/c/WINDOWS/System32/ntdll.dll
#2 0x77e7a62d in WaitForSingleObjectEx ()
from /cygdrive/c/WINDOWS/system32/KERNEL32.DLL
#3 0x00000778 in ?? ()
Still, the Backtrace Sucks(TM). So we just repeat the procedure of
simulating a function return to move up a frame:
(gdb) p/x *(int *)$ebp
$4 = 0x22fde8
(gdb) p/x *(int *)($ebp+4)
$5 = 0x61071c99
(gdb) set $ebp=0x22fde8
(gdb) set $eip=0x61071c99
(gdb) bt
#0 0x61071c99 in sigpending () from /usr/bin/cygwin1.dll
#1 0x6106f232 in sigprocmask () from /usr/bin/cygwin1.dll
#2 0x6106f3b0 in kill () from /usr/bin/cygwin1.dll
#3 0x6106f2fc in raise () from /usr/bin/cygwin1.dll
#4 0x6106f965 in cygwin1!abort () from /usr/bin/cygwin1.dll
#5 0x00401073 in main () at t.c:5
At last! A backtrace that does not suck. This is the backtrace we're
looking for.
NOTE: You cannot use dumper.exe! The reason for this is that gdb will
refuse to set registers unless it is running a process. Just looking at
a core file is not the same as running a process. Ideally, there should
be a way to change the frame without having to run a process, but I
haven't found it. That's why you have to run gdb instead of dumper, so
that gdb can attach to a running process.
I have also found that when you quit from gdb, the cygwin shell of the
original program will hang. You have to three-finger salute your way out
of the shell.
For these reasons, I'm labelling my solution as suboptimal.
--Rob
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/