Related articles |
---|
stack trace generation spuler@cs.jcu.edu.au (David Spuler) (1993-12-09) |
Re: stack trace generation spuler@coral.cs.jcu.edu.au (1993-12-11) |
Newsgroups: | comp.compilers |
From: | David Spuler <spuler@cs.jcu.edu.au> |
Keywords: | debug |
Organization: | Compilers Central |
Date: | Thu, 9 Dec 1993 14:14:13 GMT |
In response to my Summary about using BFD for stack traces, I received a
few interesting messages. One suggested the horrible-seeming but actually
quite useful hack of forking a process that dumps core and then running a
debugger like gdb or dbx on it. I think it's a neat idea, and so I coded
it up: included below. Let me know if there's portability problems getting
it to work on other UNIX platforms.
Comments anyone? I'm still seeking useful information about how
to portably produce stack traces within a C/C++ program.
-David Spuler
/*-----------------------------------------------------------------------*/
/* StackDump.c: written by David Spuler */
/*-----------------------------------------------------------------------*/
/*
Very useful hack for UNIX stack traces suggested by Castor Fu:
fork off a process which core dumps then run a debugger on it.
*/
/*-----------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/wait.h>
/*-----------------------------------------------------------------------*/
#define DEBUGGER "gdb"
#define TEMPORARY_FILENAME "input.tmp"
#define DEBUGGER_COMMAND "where\nquit\n"
#define EXECUTABLE_NAME "a.out" /* argv[0] better, if we had argv */
#define CORE_NAME "core"
/*-----------------------------------------------------------------------*/
/* StackDump(): print out a stack trace */
/*-----------------------------------------------------------------------*/
/* Procedure:
1. Fork off a child process that dumps core; creates the "core" file
2. Fork off a 2nd child process which:
2a. Creates a temporary file of input commands for the debugger
2b. Redirects stdin from this temporary file
2c. Executes the debugger using the redirected input commands
*/
/*-----------------------------------------------------------------------*/
void StackDump(void)
{
int pid;
/* Fork a child to dump core */
pid = fork();
if(pid == 0) { /* child */
abort(); /* dump core */
exit(0);
}
else if (pid == -1) {
fprintf(stderr, "StackDump ERROR: could not fork process 1 to dump core\n");
exit(1);
}
/* Parent continues */
/* Fork a 2nd child! (Runs gdb or dbx) */
pid = fork();
if(pid == 0) { /* child */
FILE *fp;
int fd;
/* Open a temporary file for the input: the "where" command */
fp = fopen(TEMPORARY_FILENAME, "w");
fprintf(fp, DEBUGGER_COMMAND);
fclose(fp);
fd = open(TEMPORARY_FILENAME, O_RDONLY, 0);
if (fd < 0) {
fprintf(stderr, "StackDump ERROR: open failed on temporary file\n");
exit(1);
}
/* Redirect stdin from the temporary file */
close(0); /* close stdin */
dup(fd); /* replace file descriptor 0 with reference to temp file */
close(fd); /* close the other reference to temporary file */
fprintf(stderr, "-------------------------------------------\n");
fprintf(stderr, "StackDump: --- now running the debugger ---\n");
fprintf(stderr, "-------------------------------------------\n");
execlp(DEBUGGER, DEBUGGER, EXECUTABLE_NAME, CORE_NAME, NULL);
/* dbx a.out core or gdb a.out core */
fprintf(stderr, "StackDump ERROR: execlp failed for debugger\n");
exit(1);
}
else if (pid == -1) {
fprintf(stderr, "StackDump ERROR: could not fork process 2 to run debugger\n");
exit(1);
}
/* Parent continues */
/* Wait for these children to complete before returning */
while (wait(NULL) > 0)
{ } /* empty loop */
remove(TEMPORARY_FILENAME); /* clean up the temporary file */
fprintf(stderr, "-------------------------------------------\n");
}
--
Return to the
comp.compilers page.
Search the
comp.compilers archives again.