DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T g

⟦a87011dcf⟧ TextFile

    Length: 20149 (0x4eb5)
    Types: TextFile
    Names: »gdb.c«

Derivation

└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
    └─⟦e10a7c8ba⟧ »./UNRELEASED/xgdb.tar.Z« 
        └─⟦ae30648b5⟧ 
            └─⟦this⟧ »./gdb.c« 

TextFile

\f


#ifndef lint
static char rcsid[] = "$Header: gdb.c,v 1.1 89/07/05 15:36:02 hubbard Exp $";
#endif

/*
 *
 *                     Copyright 1988, 1989
 *                  PCS Computer Systeme, GmbH
 *                     Munich, West Germany
 *
 *  All rights reserved.
 * 
 *  This is unsupported software and is subject to change without notice.
 *  PCS makes no representations about the suitability of this software
 *  for any purpose. It is supplied "as is" without express or implied
 *  warranty.
 * 
 *  Permission to use, copy, modify, and distribute this software and its
 *  documentation for any purpose and without fee is hereby granted, provided
 *  that the above copyright notice appear in all copies and that both that
 *  copyright notice and this permission notice appear in supporting
 *  documentation, and that the name of PCS Computer Systeme not be used in
 *  advertising or publicity pertaining to distribution of the software
 *  without specific, written prior permission.
 *
 */

/*
 * Author:	Jordan K. Hubbard
 * For:		PCS Computer Systems, GmbH.
 * When:	February 10th, 1989.
 *
 * $Log:	gdb.c,v $
 * Revision 1.1  89/07/05  15:36:02  hubbard
 * Initial revision
 * 
 * 
 */

#include "xgdb.h"
#include <errno.h>

/*
 * Debugger-dependent stuff for the GNU debugger (gdb).
 */

String debuggerPrintOutput(), debuggerParseErrors(), debuggerParseInfo();

/*
 * Foreward declarations for the "input region" commands. These are not
 * much different from the command functions, the only reason for
 * seperating them being that they make more sense when presented next
 * to the input region itself.
 */

void quitp(), clear(), restart();

/*
 * These arrays mate command names to their function callbacks.
 */
SimpleField DebuggerCommands[] = {
     { "Run",		debuggerRun },
     { "Continue",	debuggerContinue },
     { "Kill",		debuggerKill },
     { "Step",		debuggerStep },
     { "StepT",		debuggerStepThrough },
     { "StepU",		debuggerStepUntil },
     { "StepF",		debuggerStepFinish },
     { "StepI",		debuggerStepI },
     { "StepIT",	debuggerStepIThrough },
     { "Search>",	debuggerSearchForward },
     { "Search<",	debuggerSearchBackward },
     { "Up",		debuggerUp },
     { "Down",		debuggerDown },
     { "Break",		debuggerAddBkpt },
     { "Delete",	debuggerDeleteBkpt },
     { "Clear",		debuggerClearBkpt },
     { "Enable",	debuggerEnableBkpt },
     { "Disable",	debuggerDisableBkpt },
     { "exec",		debuggerExecFile },
     { "symbol",	debuggerSymbolFile },
     { "core",		debuggerCoreFile },
     { "cd",		debuggerChangeDirectory },
     { "dir",		debuggerSetDirectory },
     { "tty",		debuggerSetTTY },
     { NULL,		NULL }
};

SimpleField InputRegionCommands[] = {
     { "Quit",		quitp },
     { "Restart",	restart }, 
     { NULL,		NULL }
};

SimpleField Options[] = {
     { ASSEMBLY_N,	assemblyCreateView },
     { AUTOEXEC_N,	autoExecCreateView },
     { BREAKPOINTS_N,	breakCreateView },
     { SOURCE_N,	sourceCreateView },
     { STACK_N,		stackCreateView },
     { STATUS_N,	statusCreateView },
     { NULL,		NULL }
};

/*
 * First the utility routines.
 */

/*
 * Largest chunk of data we reasonably expect to receive. This can
 * be too small, as the buffer will just grow in HandleOutput(),
 * but for efficiency reasons it should be as large as the largest
 * chunk of output expected from gdb.
 */
#define MAX_TRANS	4096

void processDebuggerOutput(client_data, src, id)
caddr_t client_data;
int *src;
XtInputId *id;
{
     char buffer[MAX_TRANS];
     Cardinal i;

     Entry("processDebuggerOutput");

     if ((i = read(DebuggerProcess->in_channel, buffer, MAX_TRANS)) < 1) {
	  Leave_void;
     }
     else {
	  viewChangeCursor(DebuggerProcess->view,
			   app_resources.cursors.busy, TRUE);

	  /* Use the generic handler */
	  handleOutput(DebuggerProcess, buffer, i);
     }
     Leave_void;
}

/*
 * What to do when the debugger snuffs it.
 */
void handleDebuggerTermination(pd, wait_stat)
Process *pd;
int wait_stat;
{
     int status;

     Entry("handleDebuggerTermination");

     disableProcessHandling();
     status = wait_stat & 0xffff;
     if ((status & 0xff00) == 0x7f00)
	  puke_and_die("Couldn't execute debugger '%s'",
		       app_resources.debugger);
     else {
	  displayTerminationStatus(pd, wait_stat);
	  flushPendingOutput(pd); /* Get rid of all the output */
	  if (pd->in_id)
	       XtRemoveInput(pd->in_id);
	  if (pd->out_id)
	       XtRemoveInput(pd->out_id);
	  close(pd->in_channel);
	  close(pd->out_channel);
     }
     enableProcessHandling();
     Leave_void;
}

/*
 * gdb-specific preliminary setup work. 
 */
void setInitialDebuggerState(pd)
Process *pd;
{
     Entry("setInitialDebuggerState");

     /*
      * What's the debugger's prompt look like?
      */
     DebuggerPrompt = "(gdb) ";

     /*
      * What are all the different prompts gdb might print?
      */
     DebuggerPromptRegexp = "(gdb) \\|(y or n) ";

     /*
      * Declare a generic handler to catch any output not handled by
      * by anyone else.
      */
     Generic = installParser(debuggerPrintOutput);

     /*
      * Install the error message parser.
      */
     installParser(debuggerParseErrors);

     /*
      * Install the main parser.
      */
     installParser(debuggerParseInfo);
     Leave_void;
}

/*
 * Create the argument list.
 */
void setDebuggerArgs(name)
String name;
{
     static String program_args[9];
     Cardinal i, n;

     Entry("setDebuggerArgs");

     /*
      * Construct gdb's args based on what we were passsed.
      */
     i = 0;

     program_args[i++] = name;
     program_args[i++] = "-fullname";
     for (n = 1; n < Global_ac; n++)
	  program_args[i++] = Global_av[n];
     program_args[i] = NULL;
     DebuggerArgs = program_args;
     Leave_void;
}

/*
 * The command functions.
 */

void debuggerRun(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;
     static SimpleParser run[] = {
	  { "StE1", T_ARG, { SO(S_exec_file) } },
	  { NULL,	0, { NULL } },
     };

     Entry("debuggerRun");

     tmp = getInputAsString("run ", '\n');
     queueDebuggerTrans(tmp, run, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerContinue(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;
     static SimpleParser except[] = {
	  { "NORN", T_PROC,{ (caddr_t)popupErrorMessage } },
	  { "CONT", T_NOP, { NULL } },
	  { NULL,	0, { NULL } },
     };

     Entry("debuggerContinue");

     tmp = getInputAsString("cont ", '\n');
     queueDebuggerTrans(tmp, except, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerKill(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     Entry("debuggerKill");

     queueDebuggerTrans("kill\n", NULL, NULL);
     Leave_void;
}

/*
 * Step one source line.
 */
void debuggerStep(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerStep");

     tmp = getInputAsString("step ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

/*
 * Step one source line, moving "through" function calls (that is, over
 * them).
 */
void debuggerStepThrough(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerStepThrough");

     tmp = getInputAsString("next ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

/*
 * Step one instruction.
 */
void debuggerStepI(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerStepI");

     tmp = getInputAsString("stepi ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

/*
 * Step one instruction, passing over subroutine calls.
 */
void debuggerStepIThrough(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerStepIThrough");

     tmp = getInputAsString("nexti ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

/*
 * Step until the end of the current function is reached.
 */
void debuggerStepFinish(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;
     static SimpleParser fin[] = {
	  { "FINI", T_NOP, { NULL } },
	  { "FINV", T_NOP, { NULL } },
	  { NULL,	0, { NULL } },
     };
     Entry("debuggerStepFinish");

     tmp = getInputAsString("finish ", '\n');
     queueDebuggerTrans(tmp, fin, NULL);
     XtFree(tmp);
     Leave_void;
}

/*
 * Step until a source line > than the current is reached,
 * or until a given line is reached (arg) OR at the end of
 * the current function.
 */
void debuggerStepUntil(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerStepUntil");

     tmp = getInputAsString("until ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerUp(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;
     static SimpleParser except[] = {
	  { "NOUP", T_PROC0, { (caddr_t)feep } },
	  { NULL,	0,   { NULL } },
     };
     Entry("debuggerUp");

     tmp = getInputAsString("up ", '\n');
     queueDebuggerTrans(tmp, except, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerDown(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;
     static SimpleParser except[] = {
	  { "NODN", T_PROC0, { (caddr_t)feep } },
	  { NULL,	0,   { NULL } },
     };

     Entry("debuggerDown");

     tmp = getInputAsString("down ", '\n');
     queueDebuggerTrans(tmp, except, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerSetFrame(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     Entry("debuggerSetFrame");

     if (w == (Widget)NULL) {
	  char buf[30];

	  sprintf(buf, "frame %d\n", (int)data);
	  queueDebuggerTrans(buf, NULL, NULL);
     }
     Leave_void;
}

void debuggerAddBkpt(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;
     static void handleMultipleBkpts();
     static SimpleParser except[] = {
	  { "BPMU", T_PROC,  { (caddr_t)handleMultipleBkpts } },
	  { "BPBD", T_PROC0, { (caddr_t)feep } },
	  { NULL,	0,   { NULL } },
     };

     Entry("debuggerAddBkpt");

     /*
      * If NULL, We were invoked from some other part of the program,
      * not a button.
      */
     if (w == (Widget)NULL) {
	  char buf[30];

	  switch ((int)client_data) {
	  case T_LINE: /* Line number */
	       sprintf(buf, "break %d\n", (int)data);
	       queueDebuggerTrans(buf, except, NULL);
	       break;

	  case T_ADDRESS: /* Hex address */
	       sprintf(buf, "break *0x%x\n", (long)data);
	       queueDebuggerTrans(buf, except, NULL);
	       break;

	  default:
	       puke("%p: Don't know break type for #%d", (int)client_data);
	       break;
	  }
     }
     else {
	  tmp = getInputAsString("break ", '\n');
	  queueDebuggerTrans(tmp, except, NULL);
	  XtFree(tmp);
     }
     Leave_void;
}

void debuggerClearBkpt(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerClearBkpt");

     if (w == (Widget)NULL) { /* called non-interactivly */
	  char buf[30];

	  sprintf(buf, "clear %d\n", (int)data);
	  queueDebuggerTrans(buf, NULL, NULL);
     }
     else {
	  tmp = getInputAsString("clear ", '\n');
	  queueDebuggerTrans(tmp, NULL, NULL);
	  XtFree(tmp);
     }
     Leave_void;
}

void debuggerDeleteBkpt(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerDeleteBkpt");

     if (w == (Widget)NULL) { /* called non-interactivly */
	  char buf[30];

	  sprintf(buf, "delete %d\n", (int)data);
	  queueDebuggerTrans(buf, NULL, NULL);
     }
     else {
	  tmp = getInputAsString("delete ", '\n');
	  queueDebuggerTrans(tmp, NULL, NULL);
	  XtFree(tmp);
     }
     Leave_void;
}

void debuggerDisableBkpt(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerDisableBkpt");

     if (w == (Widget)NULL) { /* called non-interactivly */
	  char buf[40];

	  sprintf(buf, "disable breakpoint %d\n", (int)data);
	  queueDebuggerTrans(buf, NULL, NULL);
     }
     else {
	  tmp = getInputAsString("disable breakpoint ", '\n');
	  queueDebuggerTrans(tmp, NULL, NULL);
	  XtFree(tmp);
     }
     Leave_void;
}

void debuggerEnableBkpt(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerEnableBkpt");

     if (w == (Widget)NULL) { /* called non-interactivly */
	  char buf[40];

	  sprintf(buf, "enable breakpoint %d\n", (int)data);
	  queueDebuggerTrans(buf, NULL, NULL);
     }
     else {
	  tmp = getInputAsString("enable breakpoint ", '\n');
	  queueDebuggerTrans(tmp, NULL, NULL);
	  XtFree(tmp);
     }
     Leave_void;
}

void debuggerSearchForward(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     static void searchSucceeded();
     String tmp;
     static SimpleParser except[] = {
	  { "SE1", T_PROC0,{ (caddr_t)feep } },
	  { "SE2", T_PROC, { (caddr_t)popupErrorMessage } },
	  { "SE3", T_PROC, { (caddr_t)popupErrorMessage } },
	  { "SE4", T_PROC, { (caddr_t)searchSucceeded } },
	  { NULL,  0,	   { NULL } },
     };

     Entry("debuggerSearchForward");

     tmp = getInputAsString("forward-search ", '\n');
     queueDebuggerTrans(tmp, except, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerSearchBackward(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     static void searchSucceeded();
     String tmp;
     static SimpleParser except[] = {
	  { "SE1", T_PROC0, { (caddr_t)feep } },
	  { "SE2", T_PROC,  { (caddr_t)popupErrorMessage } },
	  { "SE3", T_PROC,  { (caddr_t)popupErrorMessage } },
	  { "SE4", T_PROC,  { (caddr_t)searchSucceeded } },
	  { NULL,	0,  { NULL } },
     };

     Entry("debuggerSearchBackward");

     tmp = getInputAsString("reverse-search ", '\n');
     queueDebuggerTrans(tmp, except, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerExecFile(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerExecFile");

     tmp = getInputAsString("exec-file ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerSymbolFile(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerSymbolFile");

     tmp = getInputAsString("symbol-file ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerCoreFile(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerCoreFile");

     tmp = getInputAsString("core-file ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerChangeDirectory(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerChangeDirectory");

     tmp = getInputAsString("cd ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

void debuggerSetDirectory(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerSetDirectory");

     tmp = getInputAsString("dir ", '\n');
     queueDebuggerTrans(tmp, NULL, NULL);
     XtFree(tmp);
     Leave_void;
}

/*
 * Set the debugged process's output to the selected tty/file. If no
 * file is selected, or it cannot be opened, do nothing.
 */
void debuggerSetTTY(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     String tmp;

     Entry("debuggerSetTTY");

     tmp = getInputAsString(NULL, '\0');

     if (tmp && strlen(tmp)) {
	  char buf[MAXPATHLEN + 19];

	  if (!access(buf, 0x06)) {
	       sprintf(buf, "tty %s\n", tmp);
	       queueDebuggerTrans(buf, NULL, NULL);
	  }
	  else {
	       sprintf(buf, "Can't open file '%s'", tmp);
	       popupErrorMessage(NULL, buf, strlen(buf));
	  }
     }
     else {
	  /* Redirect to, or create slave xterm */
     }
     Leave_void;
}

/*
 * Debugger query functions. A query function either sets state so that
 * one of the update functions catches the change sometime later, or it
 * calls one of the view public procedures directly from a parser.
 */

/* Get status information, usually for status view */
void debuggerQueryStatus()
{
     static SimpleParser dirs[] = {
	  { "StPa", T_ARG, { SO(S_file_path) } },
	  { NULL,	0, { NULL } },
     };
     static SimpleParser pwd[] = {
	  { "StD1", T_ARG, { SO(S_dir) } },
	  { "StD2", T_ARG, { SO(S_dir) } },
	  { NULL,	0, { NULL } },
     };
     static SimpleParser files[] = {
	  { "STQ1", T_NOP, { NULL } },
	  { "STQ2", T_NOP, { NULL } },
	  { "STQ3", T_NOP, { NULL } },
	  { "STQ4", T_NOP, { NULL } },
	  { "StS1", T_ARG, { SO(S_symbol_file) } },
	  { "StS2", T_ARG, { SO(S_symbol_file) } },
	  { "StE1", T_ARG, { SO(S_exec_file) } },
	  { "StE2", T_ARG, { SO(S_exec_file) } },
	  { "StC1", T_ARG, { SO(S_core_file) } },
	  { "StT1", T_ARG, { SO(S_text_segment) } },
	  { "Std1", T_ARG, { SO(S_data_segment) } },
	  { "Std2", T_ARG, { SO(S_data_segment) } },
	  { "Sts1", T_ARG, { SO(S_stack_segment) } },
	  { NULL,	0, { NULL } },
     };

     Entry("debuggerQueryStatus");

     queueDebuggerTrans("info files\n", files, NULL);
     queueDebuggerTrans("info directories\n", dirs, NULL);
     queueDebuggerTrans("pwd\n", pwd, NULL);
     Leave_void;
}

/* Find out which breakpoints are set */
void debuggerQueryBreakpoints()
{
     static SimpleParser bkpts[] = {
	  { "BPP1", T_PROCS, { (caddr_t)breakAddBreakpoint } },
	  { "BPP2", T_PROCS, { (caddr_t)breakAddBreakpoint } },
	  { "BPP3", T_NOP,   { NULL } },
	  { "BPP4", T_NOP,   { NULL } },
	  { NULL,	0,   { NULL } },
     };

     Entry("debuggerQueryBreakpoints");

     queueDebuggerTrans("info breakpoints\n", bkpts, NULL);
     Leave_void;
}

/* Find out which source file to start with */
void debuggerQueryInitialSource()
{
     static SimpleParser src[] = {
	  { "SLQ1", T_ARG,   { SO(S_file) } },
	  { "SLQ2", T_NOP,   { NULL } },
	  { NULL,	0,   { NULL } },
     };

     Entry("debuggerQueryInitialSource");

     /* KLUUUUUUUUDGE */
     queueDebuggerTrans("info line 0\n", src, NULL);
     Leave_void;
}

/*
 * Look at the current stack.
 */
void debuggerQueryStack()
{
     Entry("debuggerQueryStack");

     queueDebuggerTrans("where\n", NULL, NULL);
     Leave_void;
}

/*
 * Get the disassembled code for the current function.
 */

void debuggerQueryFunction()
{
     static SimpleParser func[] = {
	  { "ASDX", T_NOP, { NULL } },
	  { NULL,	0, { NULL } },
     };

     Entry("debuggerQueryFunction");

     if (assemblyMapped()) {
	  toggleOutputThreshold();
	  queueDebuggerTrans("asdump\n", func, assemblyDisplayFunction);
     }
     Leave_void;
}

/*
 * various parser service routines.
 */

/*
 * Deal with more than one breakpoint at a location.
 */
static void handleMultipleBkpts(T_PROC_ARGS)
T_PROC_DECL;
{
     Entry("handleMultipleBkpts");
printf("Multiple breakpoint..\n");
     Leave_void;
}

/*
 * Parse out line number information from a successful search.
 */
static void searchSucceeded(T_PROC_ARGS)
T_PROC_DECL;
{
     int line = 0;
     char *np;
     void searchRequestFile();

     Entry("searchSucceeded");

     /*
      * Yes, we go from ascii->integer->ascii here, but it's necessary
      * for error checking. Since searches aren't done all *that* often,
      * the expense is negligible.
      */
     line = atoi(s);
     if (!line)
	  puke("%p: bad line number returned by search!");
     else {
	  /* No file selected in the source window? */
	  if (!strcmp(dbg_state.S_file, INITIAL)) {
	       static SimpleParser except[] = {
		    { "SS", T_ARGS, { SO(S_line), SO(S_file) } },
		    { NULL,	0,  { NULL } },
	       };
	       queueDebuggerTrans("info line\n", except, NULL);
	  }
	  else {
	       np = (String)itoa(line);
	       STASH(dbg_state.S_line, np);
	  }
     }
     Leave_void;
}