Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-ID: <3FF88673.7050002@zoominternet.net> Date: Sun, 04 Jan 2004 16:32:35 -0500 From: Robert Baruch User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6b) Gecko/20031205 Thunderbird/0.4 MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: Solved, sort of: dumper 1.10 not giving expected stack trace in gdb References: <3FF1F041 DOT 9010506 AT zoominternet DOT net> <3FF2414D DOT 8060507 AT zoominternet DOT net> <20031231063511 DOT GA2113 AT redhat DOT com> <3FF2ED39 DOT 9080003 AT zoominternet DOT net> <20031231170224 DOT GA3881 AT redhat DOT com> <3FF356E2 DOT 5000304 AT zoominternet DOT net> <3FF43815 DOT 8050201 AT zoominternet DOT net> In-Reply-To: <3FF43815.8050201@zoominternet.net> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-IsSubscribed: yes 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/