Re: Debugging gdb with gdb

Piet/Pete Delaney
2002-02-04T23:00:51Z

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