* RE: Debugging GDB with GDB
@ 2002-11-15 0:51 James Sampson
0 siblings, 0 replies; 16+ messages in thread
From: James Sampson @ 2002-11-15 0:51 UTC (permalink / raw)
To: GDB Archive, Tim Combs
Thanks a lot - I didn't know the ctrl-c options, since I'm pretty new to GDB
:-D
Now I can get a bit further - More problems are sure to arise ;-)
J.S.
>The .gdbinit file uses "set prompt (top-gdb)" so you can differentiate
>between which gdb is running. This works best on
>the command line as you can readily see which gdb you are in. Things
>work the same as when you are debugging a program. When you want to
>stop use ctrl-c and you will see the top-level prompt and you can step
>through gdb source. When using the command line, I've always found it
>helpful to open the source file I'm debugging to follow along.
>
>Hope this helps
>Tim
^ permalink raw reply [flat|nested] 16+ messages in thread* Debugging GDB with GDB
@ 2006-08-31 16:17 Rajesh Warange
2006-08-31 16:34 ` Daniel Jacobowitz
2006-08-31 17:43 ` Michael Snyder
0 siblings, 2 replies; 16+ messages in thread
From: Rajesh Warange @ 2006-08-31 16:17 UTC (permalink / raw)
To: gdb
Hi all,
Thanks Jim and Michael for giving me a start to GDB.
I am trying to debug GDB with GDB. I have built a target for ARM (gdb-arm).
So I am debugging gdb-arm with gdb.
Below is a session output I had.
I have explained my problem below.
----------------------------------------------------------
<start_session>
GNU gdb Red Hat Linux (6.3.0.0-1.63rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Setting up the environment for debugging gdb.
No symbol table is loaded. Use the "file" command.
No symbol table is loaded. Use the "file" command.
.gdbinit:8: Error in sourced command file:
No breakpoint number 0.
(gdb) file gdb
Reading symbols from /home/warangr/gdb-6.5-build/gdb/gdb...done.
Using host libthread_db library "/lib64/tls/libthread_db.so.1".
(gdb) break _initialize_arm_tdep
Breakpoint 1 at 0x414b80: file ../../gdb-6.5/gdb/arm-tdep.c, line 2871.
(gdb) run
Starting program: /home/warangr/gdb-6.5-build/gdb/gdb
Breakpoint 1, _initialize_arm_tdep () at ../../gdb-6.5/gdb/arm-tdep.c:2871
2871 {
(gdb) s
During symbol reading, Incomplete CFI data; unspecified register rax
at 0x0000000000414b82.
2883 gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
(gdb) s
2871 {
(gdb) s
2881 size_t rest = sizeof (regdesc);
(gdb) s
2871 {
(gdb) s
2909 for (i = 0; i < num_disassembly_options; i++)
(gdb)
<end_session>
----------------------------------------------------------
I started with setting a breakpoint at the function
_initialize_arm_tdep (defined in arm-tdep.c - line 2871).
When doing a single-step it jumped to line 2883 to a function
gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
Now single stepping into this function would mean executing the first
line of the function gdbarch_register(bfd_....).
But it again jumps to line 2871 ... which is the start of the function
_initialize_arm_tdep.
Again after single-stepping, the debugger jumps to line 2909 executing
the "for loop".
There were some functions in between which it skipped entirely.
I 'm pretty badly foxed by this behaviour.
Could anyone please explain me this
Thanks.
--
wrr
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: Debugging GDB with GDB 2006-08-31 16:17 Rajesh Warange @ 2006-08-31 16:34 ` Daniel Jacobowitz 2006-08-31 17:43 ` Michael Snyder 1 sibling, 0 replies; 16+ messages in thread From: Daniel Jacobowitz @ 2006-08-31 16:34 UTC (permalink / raw) To: Rajesh Warange; +Cc: gdb On Thu, Aug 31, 2006 at 09:47:38PM +0530, Rajesh Warange wrote: > I 'm pretty badly foxed by this behaviour. > Could anyone please explain me this This is what always happens when you are debugging optimized code. Either ignore the jumps back and forth, or build GDB with CFLAGS=-g. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging GDB with GDB 2006-08-31 16:17 Rajesh Warange 2006-08-31 16:34 ` Daniel Jacobowitz @ 2006-08-31 17:43 ` Michael Snyder 2006-08-31 21:24 ` Andreas Schwab 1 sibling, 1 reply; 16+ messages in thread From: Michael Snyder @ 2006-08-31 17:43 UTC (permalink / raw) To: Rajesh Warange; +Cc: gdb On Thu, 2006-08-31 at 21:47 +0530, Rajesh Warange wrote: > Hi all, > Thanks Jim and Michael for giving me a start to GDB. > > I am trying to debug GDB with GDB. I have built a target for ARM (gdb-arm). > So I am debugging gdb-arm with gdb. Congratulations. You are entering a domain where few dare to go. ;-) > Below is a session output I had. > I have explained my problem below. Two suggestions will make your work much easier. 1) The "set prompt" command changes the gdb prompt. I use it so that I always know which gdb's prompt I am looking at. My personal habit is to set the "outer" gdb to "(GDB)", but this is of course a matter of preference. 2) Build your arm gdb with optimization turned off. Optimization is what is causing the "jumping around" behavior that you're experiencing. This should be as simple as: a) make clean b) make CFLAGS=-g (since by default, CFLAGS is "-g -O2", you are overriding the -O2). You aren't going to be bothered by poor performance debugging an un-optimized gdb, but you *will* be bothered by many little issues with debugging optimized code. > ---------------------------------------------------------- > <start_session> > > GNU gdb Red Hat Linux (6.3.0.0-1.63rh) > Copyright 2004 Free Software Foundation, Inc. > GDB is free software, covered by the GNU General Public License, and you are > welcome to change it and/or distribute copies of it under certain conditions. > Type "show copying" to see the conditions. > There is absolutely no warranty for GDB. Type "show warranty" for details. > This GDB was configured as "x86_64-redhat-linux-gnu". > Setting up the environment for debugging gdb. > No symbol table is loaded. Use the "file" command. > No symbol table is loaded. Use the "file" command. > .gdbinit:8: Error in sourced command file: > No breakpoint number 0. > (gdb) file gdb > Reading symbols from /home/warangr/gdb-6.5-build/gdb/gdb...done. > Using host libthread_db library "/lib64/tls/libthread_db.so.1". > (gdb) break _initialize_arm_tdep > Breakpoint 1 at 0x414b80: file ../../gdb-6.5/gdb/arm-tdep.c, line 2871. > (gdb) run > Starting program: /home/warangr/gdb-6.5-build/gdb/gdb > > Breakpoint 1, _initialize_arm_tdep () at ../../gdb-6.5/gdb/arm-tdep.c:2871 > 2871 { > (gdb) s > During symbol reading, Incomplete CFI data; unspecified register rax > at 0x0000000000414b82. > 2883 gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep); > (gdb) s > 2871 { > (gdb) s > 2881 size_t rest = sizeof (regdesc); > (gdb) s > 2871 { > (gdb) s > 2909 for (i = 0; i < num_disassembly_options; i++) > (gdb) > > <end_session> > ---------------------------------------------------------- > > I started with setting a breakpoint at the function > _initialize_arm_tdep (defined in arm-tdep.c - line 2871). > When doing a single-step it jumped to line 2883 to a function > gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep); > Now single stepping into this function would mean executing the first > line of the function gdbarch_register(bfd_....). > But it again jumps to line 2871 ... which is the start of the function > _initialize_arm_tdep. > Again after single-stepping, the debugger jumps to line 2909 executing > the "for loop". > There were some functions in between which it skipped entirely. > > I 'm pretty badly foxed by this behaviour. > Could anyone please explain me this > > Thanks. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging GDB with GDB 2006-08-31 17:43 ` Michael Snyder @ 2006-08-31 21:24 ` Andreas Schwab 2006-08-31 22:54 ` Michael Snyder 0 siblings, 1 reply; 16+ messages in thread From: Andreas Schwab @ 2006-08-31 21:24 UTC (permalink / raw) To: Michael Snyder; +Cc: Rajesh Warange, gdb Michael Snyder <Michael.Snyder@palmsource.com> writes: > 1) The "set prompt" command changes the gdb prompt. The .gdbinit in the gdb build directory does that already. Andreas. -- Andreas Schwab, SuSE Labs, schwab@suse.de SuSE Linux Products GmbH, MaxfeldstraÃe 5, 90409 Nürnberg, Germany PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging GDB with GDB 2006-08-31 21:24 ` Andreas Schwab @ 2006-08-31 22:54 ` Michael Snyder 0 siblings, 0 replies; 16+ messages in thread From: Michael Snyder @ 2006-08-31 22:54 UTC (permalink / raw) To: Andreas Schwab; +Cc: Rajesh Warange, gdb On Thu, 2006-08-31 at 23:24 +0200, Andreas Schwab wrote: > Michael Snyder <Michael.Snyder@palmsource.com> writes: > > > 1) The "set prompt" command changes the gdb prompt. > > The .gdbinit in the gdb build directory does that already. Yup. But Rajesh's log didn't show it happening, so I'm guessing he either didn't run from that directory, or used "-nx" (as I often do). ^ permalink raw reply [flat|nested] 16+ messages in thread
* Debugging GDB with GDB @ 2002-11-14 6:13 James Sampson 2002-11-14 6:58 ` Tim Combs 0 siblings, 1 reply; 16+ messages in thread From: James Sampson @ 2002-11-14 6:13 UTC (permalink / raw) To: GDB Archive Hello GDB doesn't recognize a COFF file that I have made to a certain target - In that respect I wish to see whats going on "inside" the GDB, so I'm using GDB to debug itself - Only thing is, that I don't know how this is done. I'm using GDB 5.0 to debug GDB 5.2.1, but how do I break or step the GDB when I have started the GDB being debugged? - The debugged GDB has control of the console. Is there any way I can use another console for debugging, or is there another way to do this?. Cheers, J.S. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging GDB with GDB 2002-11-14 6:13 James Sampson @ 2002-11-14 6:58 ` Tim Combs 0 siblings, 0 replies; 16+ messages in thread From: Tim Combs @ 2002-11-14 6:58 UTC (permalink / raw) To: James Sampson; +Cc: GDB Archive The .gdbinit file uses "set prompt (top-gdb)" so you can differentiate between which gdb is running. This works best on the command line as you can readily see which gdb you are in. Things work the same as when you are debugging a program. When you want to stop use ctrl-c and you will see the top-level prompt and you can step through gdb source. When using the command line, I've always found it helpful to open the source file I'm debugging to follow along. Hope this helps Tim On Thu, Nov 14, 2002 at 03:13:07PM +0100, James Sampson wrote: > Hello > > GDB doesn't recognize a COFF file that I have made to a certain target - In > that respect I wish to see whats going on "inside" the GDB, so I'm using GDB > to debug itself - Only thing is, that I don't know how this is done. > I'm using GDB 5.0 to debug GDB 5.2.1, but how do I break or step the GDB when > I have started the GDB being debugged? - The debugged GDB has control of the > console. Is there any way I can use another console for debugging, or is there > another way to do this?. > > Cheers, > > J.S. > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Debugging gdb with gdb @ 2002-02-01 8:25 Salman Khilji 2002-02-01 9:26 ` Daniel Jacobowitz 2002-02-03 12:29 ` Joel Brobecker 0 siblings, 2 replies; 16+ messages in thread From: Salman Khilji @ 2002-02-01 8:25 UTC (permalink / raw) To: gdb I am running gdb under gdb. Lets assume gdb starts mygdb. I issue the run command in (gdb) without setting any breakpoints anywhere. mygdb comes up and the prompt now says (mygdb) instead of (gdb). I want to put a break point somewhere inside the mygdb code---not the program that mygdb is going to debug. However if I issue the break command, the break point is going to be set in the program that (mygdb) is going to debug---not in mygdb itself. So the question is: How do I temporarily stop the target application in gdb---set a break point in the target---then continue? This is useful in GUI applications as well. Salman _________________________________________________________________ Send and receive Hotmail on your mobile device: http://mobile.msn.com ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging gdb with gdb 2002-02-01 8:25 Debugging gdb with gdb Salman Khilji @ 2002-02-01 9:26 ` Daniel Jacobowitz 2002-02-03 12:29 ` Joel Brobecker 1 sibling, 0 replies; 16+ messages in thread From: Daniel Jacobowitz @ 2002-02-01 9:26 UTC (permalink / raw) To: Salman Khilji; +Cc: gdb On Fri, Feb 01, 2002 at 04:25:15PM +0000, Salman Khilji wrote: > I am running gdb under gdb. > > Lets assume gdb starts mygdb. I issue the run command in (gdb) without > setting any breakpoints anywhere. mygdb comes up and the prompt now says > (mygdb) instead of (gdb). I want to put a break point somewhere inside the > mygdb code---not the program that mygdb is going to debug. However if I > issue the break command, the break point is going to be set in the program > that (mygdb) is going to debug---not in mygdb itself. > > So the question is: How do I temporarily stop the target application in > gdb---set a break point in the target---then continue? This is useful in > GUI applications as well. Hit control-C at the (mygdb) prompt, and it should stop on the parent GDB. -- Daniel Jacobowitz Carnegie Mellon University MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging gdb with gdb 2002-02-01 8:25 Debugging gdb with gdb Salman Khilji 2002-02-01 9:26 ` Daniel Jacobowitz @ 2002-02-03 12:29 ` Joel Brobecker 2002-02-04 1:32 ` Christophe PLANAT 2002-02-04 12:24 ` Piet/Pete Delaney 1 sibling, 2 replies; 16+ messages in thread From: Joel Brobecker @ 2002-02-03 12:29 UTC (permalink / raw) To: Salman Khilji; +Cc: gdb > So the question is: How do I temporarily stop the target application in > gdb---set a break point in the target---then continue? This is useful in > GUI applications as well. FWIW, I debug GDB a bit differently: I start the inferior GDB in a terminal. I then run another GDB, and attach it to the inferior. The idea behind this is that I want to avoid mixing the I/O in the inferior with the commands I'm sending to GDB. For the GUI lovers, GVD facilitates this, because it offers a File->Attach menu, which will then present you with a list of process. Click, click, click, and you're attached... -- Joel ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging gdb with gdb 2002-02-03 12:29 ` Joel Brobecker @ 2002-02-04 1:32 ` Christophe PLANAT 2002-02-04 12:24 ` Piet/Pete Delaney 1 sibling, 0 replies; 16+ messages in thread From: Christophe PLANAT @ 2002-02-04 1:32 UTC (permalink / raw) To: salmankhilji; +Cc: gdb brobecker@ACT-Europe.FR wrote: > > > So the question is: How do I temporarily stop the target application in > > gdb---set a break point in the target---then continue? This is useful in > > GUI applications as well. > > FWIW, I debug GDB a bit differently: I start the inferior GDB in a > terminal. I then run another GDB, and attach it to the inferior. > The idea behind this is that I want to avoid mixing the I/O in the > inferior with the commands I'm sending to GDB. > > For the GUI lovers, GVD facilitates this, because it offers a > File->Attach menu, which will then present you with a list of process. > Click, click, click, and you're attached... > > -- > Joel FYI, I use also an other way : In the top debugger (say GDB) I set a breakpoint on the function undef_cmd_error() calls each time the user hits a wrong GDB command. So when MYGDB is running, you hit a wrong command such as qwert and the GDB top debugger will stop in undef_cmd_error(). You can then do all what you want at the top GDB level inside MYGDB code. Christophe -- ---------------------------------------------------------------------- | Christophe PLANAT | Embedded Systems Technology | | Email : Christophe.Planat@st.com | STMicroelectronics | | Phone : +33 04 76 92 68 82 | 850, rue Jean-Monnet | | Fax : +33 04 76 92 50 94 | BP 16 - 38921 Crolles - France | ---------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging gdb with gdb 2002-02-03 12:29 ` Joel Brobecker 2002-02-04 1:32 ` Christophe PLANAT @ 2002-02-04 12:24 ` Piet/Pete Delaney 2002-02-04 14:02 ` Kevin Buettner 1 sibling, 1 reply; 16+ messages in thread From: Piet/Pete Delaney @ 2002-02-04 12:24 UTC (permalink / raw) To: Joel Brobecker; +Cc: gdb, Piet Delaney [-- Attachment #1: Type: text/plain, Size: 1863 bytes --] On Sun, Feb 03, 2002 at 04:18:45PM +0100, Joel Brobecker wrote: > > So the question is: How do I temporarily stop the target application in > > gdb---set a break point in the target---then continue? This is useful in > > GUI applications as well. > > FWIW, I debug GDB a bit differently: I start the inferior GDB in a > terminal. I then run another GDB, and attach it to the inferior. > The idea behind this is that I want to avoid mixing the I/O in the > inferior with the commands I'm sending to GDB. > > For the GUI lovers, GVD facilitates this, because it offers a > File->Attach menu, which will then present you with a list of process. > Click, click, click, and you're attached... Happen to have a trick to get the inferior GDB to wait for the attaching GDB to place breakpoints prior to the inferior setting up a remote debug session. skdb starts the inferior gdb with a named pipe (see attached), I'm thinking about adding a loop to spin till a global variable is set by the attaching gdb to indicate that the inferionr gdb can progress with setting up the remote connections and sent the 'g' packet. ------------------------------------------------------------------------------------ 3298 /* Read the remote registers into the block REGS. */ 3299 /* Currently we just read all the registers, so we don't use regno. */ 3300 3301 remote_fetch_registers_blocked = 1; <<----- 3302 3303 /* ARGSUSED */ 3304 static void 3305 remote_fetch_registers (int regno) 3306 { 3307 char *buf = alloca (PBUFSIZ); 3308 int i; 3309 char *p; 3310 char *regs = alloca (REGISTER_BYTES); 3311 3312 while(remote_fetch_registers_blocked) { <<--- 3313 sleep(1); <<--- 3314 } <<--- . . . ------------------------------------------------------------------------------------ -piet [-- Attachment #2: skdb.c --] [-- Type: text/plain, Size: 27413 bytes --] /* Some of you may remember that Keith mentioned a possibility of having source level debugging with kdb via proxy. I finally dragged myself to writing a little Readme note about it so it can be used by somebody other then myself. Here it is. Source level debugging with kdb In order to be able to use source level debugging with kdb, we need access to some information which is not stored in the running kernel. We also need to do I/O during the debugging to get the info we need from a file. All this means that 2 machines with a serial link have to be used. Once machine, which will run the kernel we're going to debug, will be called target, the other, which will run gdb and kdb proxy (I've called it skdb for Symbolic Kernel Debugger) will be called host. There is also a possibility to use remote hosts via a terminal server which supports telnet to serial mapping. To start the debugging session one starts skdb with the appropriate kernel image, i.e $ skdb ../../linux/2.4.0-pre9-with-kdb-debug/vmlinux skdb will spawn gdb and convince it that it should talk to a proxy. Proxy will translate gdb serial protocol to kdb commands and will talk via the serial link to the target. Proxy will interrupt the target and target will be in kdb mode until it is specifically told to resume execution via 'continue' or 'detach'. By default proxy assumes that serial port 1 (aka /dev/ttyS0) at 38400 bps will be used to communicate between the host and the target. This can be changed via -l command line option. -l /dev/foo:12345 will change the device to /dev/foo and set speed at 12345 bps. To use remote terminal server -l somehost:someport is used to tell skdb to connect to host 'somehost' on the port 'someport' and talk telnet to it. Note, that if the file 'somehost' exists and it a character device, skdb will try to use serial connection. There is a possibility to execute any kdb command via a 'monitor' command from gdb, i.e gdb> mon bt will execute backtrace command in kdb and print the result back. Known limitation. At the moment skdb supports only ia32 targets (it assumes a lot of stuff about registers etc). There is no support for modules but it is planned. There is no support for memory writes but it can be added provided there is interest. Sources. All sources is in one file, attached to this message. Save it, compile it and run it. max */ /***********************************************************\ * Copyright (C) 2000 SGI * Released under the terms of GNU Public License v.2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Project: GDB-KDB interface * Module: GDB remote debugging protocol * File: skdb.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * $Id: skdb.c,v 1.1 2000/11/08 23:42:49 max Exp max $ \***********************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <sys/time.h> #include <termios.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define TELOPTS #define TELCMDS #include <arpa/telnet.h> #define SKDB_MAX_REQSIZ (16384) /* Debug flags - options should match 1 << name */ char * dopt[] = {"all", "serial", "telnet", "remote", NULL}; unsigned int debug = 0; #define SKDB_DBG_SERIAL 2 #define SKDB_DBG_TELNET 4 #define SKDB_DBG_REMOTE 8 int pfork (int, char **); char * getgdbpkt (char * inqueue, char ** pkt); int putgdbpkt (int fd, char * data); char * kdb_request (int, const char *); unsigned long * breakaddrs = NULL; int breaks = 0; int telnetmode = 0; int isRunning = 1; /* This is the order in which gdb knows x86 regs. */ static const char * regnames[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "eflags", "cs", "ss", "ds", "es", "fs", "gs", NULL}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Function: getgdbpkt * Find something which looks, smells and sounds like a gdb * packet (i.e, it starts with $ and ends with #XX), check * the control sum and return the pointer to the end of * the packet to the caller. Pointer to the start of the packet * is returned via the 'pkt' parameter * Parameters: * inqueue - input buffer which may contain the packet * pkt - pointer * Returns: * pointer of the last charcter in the input buffer, which is not * in the packet to be processed, on success or NULL on error. If * packet has not been found, pkt is left unmolested. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * getgdbpkt (char * inqueue, char ** pkt) { while (*inqueue != '$' && *inqueue != '\0' ) { inqueue++; } if ( *inqueue == '\0' ) { /* No $ - no packets, skip the whole lot */ return inqueue; } else { char * start = ++inqueue; while ( *inqueue != '#' && *inqueue != '\0' ) { inqueue++; } if ( *inqueue == '\0' ) { /* We've seen the start of the packet but not the end of it */ return start; } /* Check for the obsolete sequence id and reject the packet if * there is one */ if ( (inqueue - start) > 3 && isxdigit (start[0]) && isxdigit (start[1]) && (start[2] == ':')) { return (NULL); } else { /* End of the packet - calculate checksum */ char * p = start; unsigned int chksum = 0; char s[3] = {inqueue[1], inqueue[2], '\0'}; int ctrlsum = strtol (s, NULL, 16); while ( p != inqueue ) { chksum = (chksum + *p++ ) & 0xFFU; } if ( ctrlsum != chksum ) { fprintf (stderr, "\nskdb: Bad Checksum: %d != %d\n", ctrlsum, chksum); return (NULL); } if ( pkt != NULL ) { *pkt = start; } inqueue += 3; } } return (inqueue); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Function: putgdbpkt * Form a kosher gdb packet and send it down to gdb using * file descriptor provided * Parameters: * fd - file descriptor which gdb can be reached thru * data - pointer to the content of the packet to be sent * Returns: * number of bytes send to gdb on success or -1 on error \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int putgdbpkt (int fd, char * data) { char * pkt = malloc (strlen(data)+5); if ( pkt != NULL ) { unsigned int chksum = 0; int sz = 0; pkt[sz++] = '$'; while ( *data != '\0' ) { pkt[sz++] = *data; chksum = (chksum + *data++) & 0xFFU; } sprintf (pkt+sz, "#%02X", chksum); if ( write (fd, pkt, sz+3) != sz+3 ) { extern int errno; fprintf (stderr, "putgdbpkt: write (%d, ... , %d) - %s", fd, sz+3, strerror (errno)); return (-1); } free (pkt); return (sz); } return (-1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Function: find_kdb_prompt * Telnetd will sent NULs for CR (see rfc1184 or * its successor), so we have to work around them * here. * Parameters: * reply - stuff we've got back from kdb * sz - how much have we got? * Returns: * Pointer to the start of the prompt on success or NULL * if there is no prompt. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * find_kdb_prompt (char * reply, int sz ) { char * l; for ( l = reply; l < reply + sz; l += strlen (l)+1 ) { char * prompt = strstr (l, "kdb> "); if ( prompt != NULL ) { return (prompt); } } return (NULL); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Function: kdb_request * Send kdb interrupt key, send simple request, i.e one * kdb command, wait for the result, send go and return * the result. * Parameters: * fd - file descriptor to reach kdb * req - request * Returns: * pointer to the dynamically allocated region of memory * on success or NULL on error \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * kdb_request (int fd, const char * req) { char buf[SKDB_MAX_REQSIZ]; int bc = 0, seek = 1; fd_set fds; struct timeval tv; FD_ZERO (&fds); if ( isRunning ) { write (fd, "\1", 1); /* KDB attention key */ } else { write (fd, "\n\r", 2); } /* Wait for kdb prompt */ while ( seek ) { FD_SET (fd, &fds); tv.tv_sec = 15; tv.tv_usec = 0; if ( select (fd+1, &fds, NULL, NULL, &tv) > 0 ) { int nb = read (fd, buf+bc, SKDB_MAX_REQSIZ-bc-1); if ( nb > 0 && ((bc + nb) < SKDB_MAX_REQSIZ)) { bc += nb; buf[bc+1] = '\0'; if ( find_kdb_prompt (buf, bc) != NULL ) { seek = 0; bc = 0; isRunning = 0; } } else { fputs ("\nskdb: Request is too big\n", stderr); fflush (stderr); return (NULL); } } else { fputs ("\nskdb: Timed out while trying to get kdb attention\n", stderr); fflush (stderr); return (NULL); } } /* Check if we have smth to request or if it was just an interrupt */ if ( req[0] ) { /* Send request */ write (fd, req, strlen (req)); write (fd, "\n\r", 2); /* Read reply until we find a second prompt, unless it's a 'go' - * in this case we just return */ if ( strncmp (req, "go", 2) ) { seek = 1; while ( seek ) { FD_SET (fd, &fds); tv.tv_sec = 5; tv.tv_usec = 0; if ( select (fd+1, &fds, NULL, NULL, &tv) > 0 ) { int nb = read (fd, buf+bc, SKDB_MAX_REQSIZ-bc-1); if ( nb > 0 && ((bc + nb) < SKDB_MAX_REQSIZ) ) { char * pstart; bc += nb; buf[bc+1] = '\0'; if ( (pstart = find_kdb_prompt(buf, bc)) != NULL ) { char * nl; if ( telnetmode ) { char * nul; while ((nul=memchr (buf, '\0', bc)) != NULL) { memmove (nul, nul+1, buf+bc-nul-1); bc--; } } *pstart = '\0'; if ( (nl = strrchr (buf, '\n')) != NULL ) { seek = 0; *pstart = 'k'; bc = nl - buf; *nl = '\0'; } } } else { return (NULL); } } else { return (NULL); } } } else { isRunning = 1; return (strdup ("")); } } else { return (strdup ("")); } return (strdup (buf)); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Function: gdb_process * Process one gdb packet. One gdb packet my result to zero, * one or no requests to kdb. * Parameters: * pm - file descriptor to talk to gdb * kdb - file descriptor to talk to kdb * pkt - gdb packet sense control sum \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void gdb_process (int pm, int kdb, char * pkt) { char * start = NULL, *end; if ( ((end = getgdbpkt (pkt, &start)) != NULL) && (start != NULL) ) { unsigned long bpaddr; int i; char reply[SKDB_MAX_REQSIZ] = ""; char * sep; write (pm, "+", 1); /* ACK the packet */ switch ( *start ) { case 'c': /* Continue - do nothing, just ACK the packet. The rest * will come from the kdb */ free (kdb_request (kdb, "go")); break; case 'D': /* GDB doesn't want to play no more but it still * wants a reply regardless of what is said in the * manual */ free (kdb_request (kdb, "go")); putgdbpkt (pm, "OK"); break; case 's': free (kdb_request (kdb, "ss")); putgdbpkt (pm, "S00"); break; case 'H': putgdbpkt (pm, "OK"); break; case 'm': /* Memory read */ if ( (sep = strchr (start+1, ',')) == NULL ) { strcpy (reply, "E01"); } else { char * aend; unsigned long addr = strtoul (start+1, &aend, 16); if ( aend != sep ) { strcpy (reply, "E01"); } else { int sz = atoi (sep+1); char * res; sprintf (reply, "mdr 0x%x %d", addr, sz); if ( (res = kdb_request (kdb, reply)) == NULL ) { putgdbpkt (pm, "E02"); } else { char * nl = strrchr (res, '\n'); if ( nl == NULL ) { putgdbpkt (pm, "E02"); } else { int i; for (i = strlen (nl)-1; i>0; i-- ) { if ( ! isxdigit (nl[i]) ) { break; } } if ( i ) { /* Wrong address */ putgdbpkt (pm, "E03"); } else { putgdbpkt (pm, nl+1); } } free (res); } } } break; case 'P': /* Set register */ if ( (sep = strchr (start+1, '=')) == NULL ) { strcpy (reply, "E01"); } else { char * aend; unsigned long rn = strtoul (start+1, &aend, 16); if ( aend != sep ) { strcpy (reply, "E01"); } else if ( rn > sizeof (regnames) / sizeof (regnames[0]) ) { strcpy (reply, "E04"); } else { int i; char * res; unsigned long rv = strtoul (sep+1, NULL, 16); sprintf (reply, "rm %%%s ", regnames[rn]); for ( i=0; i < sizeof (int); i++ ) { char x2[3]; sprintf (x2, "%02x", rv & 0xFFU); rv >>= 8; strcat (reply, x2); } if ( (res = kdb_request (kdb, reply)) == NULL ) { putgdbpkt (pm, "E02"); } else { if ( strstr (res, "diag:") != 0 ) { /* We don't expect anything back, so it's * an error */ putgdbpkt (pm, "E03"); } else { putgdbpkt (pm, "OK"); } free (res); } } } break; case 'g': if ( start[1] != '#' ) { putgdbpkt (pm, "E01"); } else { char * res = kdb_request (kdb, "rd"); if ( res == NULL ) { putgdbpkt (pm, "E02"); } else { int r; for ( r=0; regnames[r] != NULL; r++ ) { char * p = strstr (res, regnames[r]); if ( p != NULL && isspace (p[-1])){ int b = strlen(regnames[r])+2; unsigned long rv = strtoul (p+b, NULL, 0); for ( b=0; b < sizeof (int); b++ ) { char x2[3]; sprintf (x2, "%02x", (rv & 0xFFU)); strcat (reply, x2); rv >>= 8; } } else { strcat (reply, "xxxxxxxx"); } } putgdbpkt (pm, reply); free (res); } } break; case 'q': /* Query packet - needs further processing */ switch ( start[1] ) { case 'C': putgdbpkt (pm, "QC0"); break; case 'O': /* We don't use any special offsets, so whatever * is in the elf, should be fine. */ putgdbpkt (pm, "Text=00000000;Data=00000000;Bss=00000000;"); break; case 'R': /* Remote Command */ if ( (sep = strchr (start, ',')) == NULL ) { putgdbpkt (pm, "E01"); } else { int i; for ( i=0,sep++; sep[0] != '#' && sep < end; sep+=2,i++ ) { if ( isxdigit (sep[0]) && isxdigit (sep[1]) ) { char x2[3] = {sep[0], sep[1], '\0'}; unsigned long ch = strtoul (x2, NULL, 16); reply[i] = (ch & 0xFFU); } else { i = -1; break; } } if ( i < 0 ) { putgdbpkt (pm, "E02"); } else { const char * xchars = "0123456789ABCDEF"; char * res = kdb_request (kdb, reply); if ( res != NULL ) { for (i=0; res[i] && (i*2 < SKDB_MAX_REQSIZ); i++) { reply[i*2] = xchars[(res[i] >> 4) & 0xFU]; reply[i*2+1] = xchars[(res[i] & 0xFU)]; } reply[i*2] = '\0'; strcat (reply, "0A0D"); i += 2; if ( i*2 > 256 ) { /* Have to break the reply as gdb * cannot cope with the big packets */ char part[256]; int j; for ( j=0; j < (i*2)-254; j += 254 ) { part[0] = 'O'; memcpy (part+1, reply + j, 254); part[255] = '\0'; putgdbpkt (pm, part); } putgdbpkt (pm, reply+j); } else { putgdbpkt (pm, reply); } free (res); } else { putgdbpkt (pm, "E02"); } } } break; default: putgdbpkt (pm, "E33"); break; } break; case 'z': /* Clear a break/watch point */ bpaddr = strtoul (start+3, NULL, 16); for ( i=0; i < breaks; i++ ) { if ( breakaddrs[i] == bpaddr ) { char * res; sprintf (reply, "bc %d", i); if ( (res = kdb_request (kdb, reply)) != NULL ) { bpaddr = 0; putgdbpkt (pm, "OK"); free (res); } else { putgdbpkt (pm, "E05"); } break; } } if ( i >= breaks ) { putgdbpkt (pm, "E06"); } break; case 'Z': /* Breakpoint/watchpoint - Z<type>,<addr>,<length> */ bpaddr = strtoul (start+3, NULL, 16); switch ( start[1] ) { case '0': /* Software breakpoint */ for ( i=0; i < breaks; i++ ) { if ( breakaddrs[i] == bpaddr ) { putgdbpkt (pm, "OK"); break; } } if ( i >= breaks ) { char * res; sprintf (reply, "bp 0x%x", bpaddr); if ( (res = kdb_request (kdb, reply)) != NULL ) { char * bpnum; if ( (bpnum = strstr (res, "BP #")) == NULL ) { putgdbpkt (pm, "E03"); } else { int bp = strtol (bpnum+4, NULL, 0); if ( breaks <= bp) { unsigned long * nb; if ( (nb = realloc (breakaddrs, sizeof (int)*(bp+1))) != NULL ) { breakaddrs = nb; for ( i=breaks+1; i < bp; i++ ) { breakaddrs[i] = 0; } breaks = bp+1; breakaddrs[bp] = bpaddr; putgdbpkt (pm, "OK"); } else { putgdbpkt (pm, "E05"); } } free (res); } } else { putgdbpkt (pm, "E02"); } } break; case '1': /* Hardware breakpoint */ sprintf (reply, "bph 0x%8.8s", start+3); if ( kdb_request (kdb, reply) != NULL ) { putgdbpkt (pm, "OK"); } else { putgdbpkt (pm, "E02"); } break; default: putgdbpkt (pm, "E34"); break; } break; case '?': putgdbpkt (pm, "S05"); break; default: putgdbpkt (pm, "E35"); break; } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Function: pfork * Create a master/slave pty pair, fork and exec gdb with * -x fudged to point it to the slave pty in the parent * process space. Child will do the real work. * Parameters: * argc - number of gdb command line parameters * args - gdb's command line parameters * Returns: * file descriptor for master PTY on success or -1 on error \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int pfork (int argc, char ** args) { int pt; if ( (pt = open ("/dev/ptmx", O_RDWR)) >= 0 ) { if ( grantpt (pt) != -1 ) { if ( unlockpt (pt) != -1 ) { FILE * tf; char * tname = strdup (tmpnam (NULL)); pid_t child; if ( tname == NULL ) { puts ("Oops!"); return -1; } else if ( (tf = fopen (tname, "w")) == NULL ) { perror (tname); free (tname); return -1; } fprintf (tf, "shell rm %s\n" "set remotedebug %d\n" "set serialdebug %d\n" "target remote %s\n" "define lsmod\n" "set $mod = (struct module*)module_list\n" "while $mod != &kernel_module\n" "printf \"%%p\t%%s\\n\", (long)$mod, ($mod)->name\n" "set $mod = $mod->next\n" "end\nend\n", tname, ((debug & SKDB_DBG_REMOTE) != 0), ((debug & SKDB_DBG_SERIAL) != 0), ptsname(pt)); fflush (tf); if ( (child = fork ()) > 0 ) { int i; char **gargs = calloc (argc+5, sizeof (char *)); if ( gargs == NULL ) { kill (child, SIGTERM); exit (1); } else { gargs[0] = "gdb"; gargs[1] = "-q"; gargs[2] = "-x"; gargs[3] = tname; close (pt); for ( i=0; i < argc ; i++ ) { gargs[i+4] = args[i]; } gargs[i+4] = NULL; execvp ("gdb", gargs); kill (child, SIGTERM); exit (1); } /*NOTREACHED*/ } else if ( child < 0 ) { perror ("fork"); close (pt); pt = -1; } fclose (tf); free (tname); return (pt); } else { perror ("unlockpt"); } } else { perror ("grantpt"); } close (pt); } return (-1); } static void usage (char * pname) { printf ("USAGE: %s [-Dall,serial,telnet] [-k] [-l tty] -- [gdb-args]\n", pname); puts ("Options:"); puts ("-k target is already in kdb, don't break in"); puts ("-l tty tty:speed or host:port to get access to"); puts (" a target"); } int main (int argc, char * argv[]) { int c, pm, kdb; char * line = "/dev/ttyS0"; int speed = B38400; char * delim; struct stat st; if ( argc == 2 && argv[1][0] == '-' && argv[1][1] == '?' ) { usage (argv[0]); exit (0); } while ( (c = getopt (argc, argv, "D:kl:")) > 0 ) { switch ( c ) { case 'k': isRunning = 0; break; case 'l': line = optarg; break; case 'D': delim = optarg; do { char * nextcomma; int i; if ( (nextcomma = strchr (delim, ',')) == NULL ) { nextcomma = delim + strlen (delim); } for ( i=0; dopt[i] != NULL; i++ ) { if ( ! strncmp (delim, dopt[i], nextcomma-delim)) { if ( i ) { debug |= 1 << i; } else { debug = 0xffffffffUL; } break; } } if ( dopt[i] == NULL ) { fprintf (stderr, "Unknown debug option: %s\n", delim); exit (1); } delim = nextcomma+1; } while ( (delim - optarg) < strlen (optarg) ); break; default: usage (argv[0]); exit (1); } } if ( (delim = strchr (line, ':')) != NULL ) { *delim++ = '\0'; } /* Try to guess if we're dealing with real line or with a host name */ if ( (stat (line, &st) >= 0) && S_ISCHR (st.st_mode) ) { if ( (kdb = open (line, O_RDWR)) < 0 ) { perror (line); exit (1); } else { struct termios tio; if ( tcgetattr (kdb, & tio) < 0 ) { perror ("tcgetattr"); return (1); } else { tio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); tio.c_cflag &= ~(CBAUD | CSIZE | PARENB | CSTOPB | CRTSCTS ); tio.c_cflag |= B38400 | CS8 | CREAD | HUPCL; tio.c_iflag &= ~(BRKINT | ICRNL |INPCK | ISTRIP); tio.c_iflag |= IXON |IXOFF; tio.c_oflag &= ~OPOST; cfsetispeed (& tio, B38400); cfsetospeed (& tio, B38400); tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; if ( tcsetattr (kdb, TCSANOW, & tio) < 0 ) { perror ("tcsetattr"); exit (1); } } } } else { /* Must be a host name - try to resolve it. Note, that host must * have a port number - defaulting to a telnet port isn't going to do * us much good here */ if ( delim == NULL ) { fputs ("Host specification requires a port number\n", stderr); exit (1); } else { static struct sockaddr_in sa; struct servent * sp; struct hostent * he; char **p; memset ( & sa, 0, sizeof (sa)); sa.sin_family = AF_INET; if ( (sp = getservbyname (delim, "tcp")) != NULL ) { sa.sin_port = htons (sp->s_port); } else { /* Lookup fails. Check if it's a number */ char * err = NULL; sa.sin_port = htons ((short int)strtol (delim, & err, 0)); if ( (err == NULL) || (*err != '\0') ) { fprintf (stderr, "Cannot find port number for port %s\n", delim); exit (1); } } if ( (he = gethostbyname (line)) == NULL ) { fprintf (stderr,"No address information for %s\n", line); exit (1); } else { memcpy (& sa.sin_addr.s_addr, * he->h_addr_list, sizeof (sa.sin_addr.s_addr)); } if ( (kdb = socket (AF_INET, SOCK_STREAM, 0)) < 0 ) { perror ("socket"); exit (1); } else { if ( connect (kdb, (struct sockaddr *)&sa, sizeof (sa)) < 0 ) { fprintf (stderr, "Cannot connect to %s - %s\n", line, strerror (errno)); exit (1); } else { /* Assume telnetd connection and try to negotiate: * reply WONT to any DOs, reply DONT to any WILL * except WILL ECHO. First non-escaped charachter stops * negotiation */ int negotiate = 1; int echo = 0; telnetmode = 1; while ( negotiate ) { fd_set fds; struct timeval tv; unsigned char negbuf[512]; int bc = 0; FD_ZERO (&fds); FD_SET (kdb, &fds); tv.tv_sec = 1; tv.tv_usec = 0; if ( select (kdb+1, &fds, NULL, NULL, &tv) > 0 ) { int nb = read (kdb, negbuf+bc, 511-bc); unsigned char rep[512], * prep = rep; int i; if ( nb > 0 && ((bc + nb) < 512)) { bc += nb; for (i=0; i < bc-2; i+= 3 ) { if ( negbuf[i] == IAC ) { switch ( negbuf[i+1] ) { case DO: if ( debug & SKDB_DBG_TELNET ) { printf ("RECV DO %s\n", telopts[negbuf[i+2]]); } prep[0] = IAC; prep[1] = WONT; prep[2] = negbuf[i+2]; prep += 3; break; case WILL: if ( debug & SKDB_DBG_TELNET ) { printf ("RECV WILL %s\n", telopts[negbuf[i+2]]); } prep[0] = IAC; prep[2] = negbuf[i+2]; if ( negbuf[i+2] != TELOPT_ECHO ) { prep[1] = DONT; } else { if ( echo ) { prep -= 3; } else { echo = 1; prep[1] = DO; } } prep += 3; break; } } else { negotiate = 0; break; } } if ( ! echo ) { prep[0] = IAC; prep[1] = DO; prep[2] = TELOPT_ECHO; prep += 3; echo = 1; } if ( debug & SKDB_DBG_TELNET ) { for ( i=0; i < prep - rep; i += 3 ) { printf ("SEND %s %s\n", TELCMD((rep[i+1])), TELOPT(rep[i+2])); } } write (kdb, rep, prep - rep); } else { fputs ("Connection closed by remote host\n", stderr); exit (1); } } else { /* Timeout - other end doesn't want * to negotiate no more */ negotiate = 0; } } } } } } if ( (pm = pfork (argc-optind, argv+optind)) >= 0 ) { int maxfd = (pm > kdb) ? pm : kdb; int bc = 0; char kdbpkt[SKDB_MAX_REQSIZ]; signal (SIGINT, SIG_IGN); while ( 1 ) { fd_set fds; FD_SET(pm, &fds); FD_SET(kdb, &fds); if (select (maxfd+1, &fds, NULL, NULL, NULL) < 0 ) { close (pm); break; } else { int i, sz; if ( FD_ISSET (pm, &fds) ) { char pkt[SKDB_MAX_REQSIZ]; if ( (sz = read (pm, pkt, SKDB_MAX_REQSIZ)) <= 0 ) { break; } pkt[sz] = '\0'; /* Sometimes gdb doesn't play by the rules and * doesn't sent packets but sends Ctrl-C instead, * which is naughty but it does it, so we check * for this case before we start processing good * packets */ if ( pkt[0] == '\3' ) { /* GDB sent us an interrupt */ kdb_request (kdb, ""); putgdbpkt (pm, "S02"); } else { gdb_process (pm, kdb, pkt); } } if ( FD_ISSET (kdb, &fds) ) { if ( (sz = read (kdb, kdbpkt+bc, SKDB_MAX_REQSIZ - bc)) >= 0 ) { char * prompt; bc += sz; kdbpkt[bc] = '\0'; if ( telnetmode ) { char * nul; while ((nul=memchr (kdbpkt, '\0', bc)) != NULL) { memmove (nul, nul+1, kdbpkt+bc-nul-1); bc--; } } if ( (prompt = strstr (kdbpkt, "kdb> ")) != NULL ) { isRunning = 0; if ( strstr (kdbpkt, "due to Keyboard Entry") != NULL ) putgdbpkt (pm, "S02"); else if ( strstr (kdbpkt, "due to Breakpoint") != NULL ) putgdbpkt (pm, "S05"); else putgdbpkt (pm, "S00"); bc -= prompt+5 - kdbpkt; memmove (kdbpkt, prompt+5, bc); } else { if ( (SKDB_MAX_REQSIZ - bc) < 5 ) { memmove (kdbpkt, kdbpkt+bc-5, 5); bc = 5; } } } } } } } close (pm); close (kdb); return (0); } ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging gdb with gdb 2002-02-04 12:24 ` Piet/Pete Delaney @ 2002-02-04 14:02 ` Kevin Buettner 2002-02-04 15:00 ` Piet/Pete Delaney 0 siblings, 1 reply; 16+ messages in thread From: Kevin Buettner @ 2002-02-04 14:02 UTC (permalink / raw) To: Piet/Pete Delaney; +Cc: gdb On Feb 4, 12:23pm, Piet/Pete Delaney wrote: > Happen to have a trick to get the inferior GDB to wait for the attaching GDB > to place breakpoints prior to the inferior setting up a remote debug session. > skdb starts the inferior gdb with a named pipe (see attached), I'm thinking > about adding a loop to spin till a global variable is set by the attaching > gdb to indicate that the inferionr gdb can progress with setting up the > remote connections and sent the 'g' packet. I don't understand why you need to do this. Why not just start up the inferior gdb first and attach to it with another gdb while it's at the prompt? Once you're attached, you can set breakpoints wherever you like. After your breakpoints are set, do a ``continue'' and then start entering your target connection commands in the inferior gdb. Assuming you've placed a breakpoint somewhere along the execution path that the inferior gdb will take when/after it connects, you'll be stopped... Kevin ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging gdb with gdb 2002-02-04 14:02 ` Kevin Buettner @ 2002-02-04 15:00 ` Piet/Pete Delaney 2002-02-04 15:13 ` Piet/Pete Delaney 0 siblings, 1 reply; 16+ messages in thread From: Piet/Pete Delaney @ 2002-02-04 15:00 UTC (permalink / raw) To: Kevin Buettner; +Cc: Piet Delaney, gdb On Mon, Feb 04, 2002 at 03:01:27PM -0700, Kevin Buettner wrote: > On Feb 4, 12:23pm, Piet/Pete Delaney wrote: > > > Happen to have a trick to get the inferior GDB to wait for the attaching GDB > > to place breakpoints prior to the inferior setting up a remote debug session. > > skdb starts the inferior gdb with a named pipe (see attached), I'm thinking > > about adding a loop to spin till a global variable is set by the attaching > > gdb to indicate that the inferionr gdb can progress with setting up the > > remote connections and sent the 'g' packet. > > I don't understand why you need to do this. Why not just start up the > inferior gdb first and attach to it with another gdb while it's at the > prompt? Once you're attached, you can set breakpoints wherever you > like. After your breakpoints are set, do a ``continue'' and then > start entering your target connection commands in the inferior gdb. > Assuming you've placed a breakpoint somewhere along the execution path > that the inferior gdb will take when/after it connects, you'll be > stopped... skdb starts gdb with the -x option so that gdb will get cmds from a tmp file. The cmds targets the remote to a pty. I suppose I could disable the startup code. Adding a hang in gdb seems easier. Likely I'll add an option to the inferior gdb and enable the switch to hang before sending the 'g' packet and pass the new option via the execvp() args to gdb. The new option might come in handy for other bugs. ---------------------------------------------------------------------------------------------------- stdin/stdout | | | ^ / \ / \ / \ / \ / \ / \ (ignored) +---------------+ pty +---------------+ telet +---------------+ + gdb + <---> + skdb + <---------> + kdb + + + + + + + +---------------+ +---------------+ +---------------+ | | \ / \ / \ / /tmp/tmpnam: ---------------------------------------------------------------------------------------------------- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Function: pfork * Create a master/slave pty pair, fork and exec gdb with * -x fudged to point it to the slave pty in the parent * process space. Child will do the real work. * Parameters: * argc - number of gdb command line parameters * args - gdb's command line parameters * Returns: * file descriptor for master PTY on success or -1 on error \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int pfork (int argc, char ** args) { int pt; if ( (pt = open ("/dev/ptmx", O_RDWR)) >= 0 ) { if ( grantpt (pt) != -1 ) { if ( unlockpt (pt) != -1 ) { FILE * tf; char * tname = strdup (tmpnam (NULL)); pid_t child; if ( tname == NULL ) { puts ("Oops!"); return -1; } else if ( (tf = fopen (tname, "w")) == NULL ) { perror (tname); free (tname); return -1; } fprintf (tf, "shell rm %s\n" "set remotedebug %d\n" "set serialdebug %d\n" "target remote %s\n" "define lsmod\n" "set $mod = (struct module*)module_list\n" "while $mod != &kernel_module\n" "printf \"%%p\t%%s\\n\", (long)$mod, ($mod)->name\n" "set $mod = $mod->next\n" "end\nend\n", tname, ((debug & SKDB_DBG_REMOTE) != 0), ((debug & SKDB_DBG_SERIAL) != 0), ptsname(pt)); fflush (tf); if ( (child = fork ()) > 0 ) { int i; char **gargs = calloc (argc+5, sizeof (char *)); if ( gargs == NULL ) { kill (child, SIGTERM); exit (1); } else { gargs[0] = "gdb"; gargs[1] = "-q"; gargs[2] = "-x"; gargs[3] = tname; close (pt); for ( i=0; i < argc ; i++ ) { gargs[i+4] = args[i]; } gargs[i+4] = NULL; execvp ("gdb", gargs); kill (child, SIGTERM); exit (1); } /*NOTREACHED*/ } else if ( child < 0 ) { perror ("fork"); close (pt); pt = -1; } fclose (tf); free (tname); return (pt); } else { perror ("unlockpt"); } } else { perror ("grantpt"); } close (pt); } return (-1); } ----------------------------------------------------------------------------------------------------- -piet ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Debugging gdb with gdb 2002-02-04 15:00 ` Piet/Pete Delaney @ 2002-02-04 15:13 ` Piet/Pete Delaney 0 siblings, 0 replies; 16+ messages in thread From: Piet/Pete Delaney @ 2002-02-04 15:13 UTC (permalink / raw) To: Kevin Buettner; +Cc: Piet Delaney, gdb On Mon, Feb 04, 2002 at 03:00:44PM -0800, Piet/Pete Delaney wrote: > On Mon, Feb 04, 2002 at 03:01:27PM -0700, Kevin Buettner wrote: > > On Feb 4, 12:23pm, Piet/Pete Delaney wrote: I think I could likely remove the target cmd from the cmds in the tmp file, print the name of the pty, and then target it myself from gdb prompt. I suppose that's what you may have been suggeting. -piet > > > > > Happen to have a trick to get the inferior GDB to wait for the attaching GDB > > > to place breakpoints prior to the inferior setting up a remote debug session. > > > skdb starts the inferior gdb with a named pipe (see attached), I'm thinking > > > about adding a loop to spin till a global variable is set by the attaching > > > gdb to indicate that the inferionr gdb can progress with setting up the > > > remote connections and sent the 'g' packet. > > > > I don't understand why you need to do this. Why not just start up the > > inferior gdb first and attach to it with another gdb while it's at the > > prompt? Once you're attached, you can set breakpoints wherever you > > like. After your breakpoints are set, do a ``continue'' and then > > start entering your target connection commands in the inferior gdb. > > Assuming you've placed a breakpoint somewhere along the execution path > > that the inferior gdb will take when/after it connects, you'll be > > stopped... > > skdb starts gdb with the -x option so that gdb will get cmds from a tmp file. The cmds > targets the remote to a pty. I suppose I could disable the startup code. Adding a hang > in gdb seems easier. Likely I'll add an option to the inferior gdb and enable the switch > to hang before sending the 'g' packet and pass the new option via the execvp() args to gdb. > The new option might come in handy for other bugs. > ---------------------------------------------------------------------------------------------------- > > stdin/stdout > | > | > | > ^ > / \ > / \ > / \ > / \ > / \ > / \ (ignored) > +---------------+ pty +---------------+ telet +---------------+ > + gdb + <---> + skdb + <---------> + kdb + > + + + + + + > +---------------+ +---------------+ +---------------+ > | | > \ / > \ / > \ / > /tmp/tmpnam: > > > > ---------------------------------------------------------------------------------------------------- > /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ > * Function: pfork > * Create a master/slave pty pair, fork and exec gdb with > * -x fudged to point it to the slave pty in the parent > * process space. Child will do the real work. > * Parameters: > * argc - number of gdb command line parameters > * args - gdb's command line parameters > * Returns: > * file descriptor for master PTY on success or -1 on error > \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ > int > pfork (int argc, char ** args) > { > int pt; > > if ( (pt = open ("/dev/ptmx", O_RDWR)) >= 0 ) { > if ( grantpt (pt) != -1 ) { > if ( unlockpt (pt) != -1 ) { > FILE * tf; > char * tname = strdup (tmpnam (NULL)); > pid_t child; > > if ( tname == NULL ) { > puts ("Oops!"); > return -1; > } else if ( (tf = fopen (tname, "w")) == NULL ) { > perror (tname); > free (tname); > return -1; > } > > fprintf (tf, > "shell rm %s\n" > "set remotedebug %d\n" > "set serialdebug %d\n" > "target remote %s\n" > "define lsmod\n" > "set $mod = (struct module*)module_list\n" > "while $mod != &kernel_module\n" > "printf \"%%p\t%%s\\n\", (long)$mod, ($mod)->name\n" > "set $mod = $mod->next\n" > "end\nend\n", > tname, > ((debug & SKDB_DBG_REMOTE) != 0), > ((debug & SKDB_DBG_SERIAL) != 0), > ptsname(pt)); > fflush (tf); > > if ( (child = fork ()) > 0 ) { > int i; > char **gargs = calloc (argc+5, sizeof (char *)); > if ( gargs == NULL ) { > kill (child, SIGTERM); > exit (1); > } else { > gargs[0] = "gdb"; > gargs[1] = "-q"; > gargs[2] = "-x"; > gargs[3] = tname; > > close (pt); > > for ( i=0; i < argc ; i++ ) { > gargs[i+4] = args[i]; > } > > gargs[i+4] = NULL; > > execvp ("gdb", gargs); > kill (child, SIGTERM); > exit (1); > } > /*NOTREACHED*/ > } else if ( child < 0 ) { > perror ("fork"); > close (pt); > pt = -1; > } > > fclose (tf); > > free (tname); > return (pt); > } else { > perror ("unlockpt"); > } > } else { > perror ("grantpt"); > } > close (pt); > } > > return (-1); > } > ----------------------------------------------------------------------------------------------------- > > -piet ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2006-08-31 22:54 UTC | newest] Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-11-15 0:51 Debugging GDB with GDB James Sampson -- strict thread matches above, loose matches on Subject: below -- 2006-08-31 16:17 Rajesh Warange 2006-08-31 16:34 ` Daniel Jacobowitz 2006-08-31 17:43 ` Michael Snyder 2006-08-31 21:24 ` Andreas Schwab 2006-08-31 22:54 ` Michael Snyder 2002-11-14 6:13 James Sampson 2002-11-14 6:58 ` Tim Combs 2002-02-01 8:25 Debugging gdb with gdb Salman Khilji 2002-02-01 9:26 ` Daniel Jacobowitz 2002-02-03 12:29 ` Joel Brobecker 2002-02-04 1:32 ` Christophe PLANAT 2002-02-04 12:24 ` Piet/Pete Delaney 2002-02-04 14:02 ` Kevin Buettner 2002-02-04 15:00 ` Piet/Pete Delaney 2002-02-04 15:13 ` Piet/Pete Delaney
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox