Looking for "undump" for SysV

joost helberg joost at nixvia.UUCP
Sat Jan 28 00:06:18 AEST 1989


UNDUMP for coff-files:

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	scanargs.c
#	undump.c
#	undump.1
# This archive created: Fri Jan 27 14:31:58 1989
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#/*
# *      @(#)Makefile	1.2     88/05/27     eg4
# */
BINDIR=/usr/local

all undump: undump.o scanargs.o
	cc -O -o undump undump.o scanargs.o

clean:
	rm *.o undump

install: undump
	cp undump $(BINDIR)
SHAR_EOF
fi # end of overwriting check
if test -f 'scanargs.c'
then
	echo shar: will not over-write existing file "'scanargs.c'"
else
cat << \SHAR_EOF > 'scanargs.c'
/*
		Version 7 compatible
	Argument scanner, scans argv style argument list.

	Some stuff is a kludge because sscanf screws up

	Gary Newman - 10/4/1979 - Ampex Corp.

	Modified by Spencer W. Thomas, Univ. of Utah, 5/81 to
	add args introduced by 	a flag, add qscanargs call,
	allow empty flags.

	Compiling with QUICK defined generates 'qscanargs' ==
	scanargs w/o floating point support; avoids huge size
	of scanf.

	If you make improvements we'd like to get them too.
	Jay Lepreau	lepreau at utah-20, decvax!{harpo,randvax}!utah-cs!lepreau
	Spencer Thomas	thomas at utah-20, decvax!{harpo,randvax}!utah-cs!thomas

	(There seems to be a bug here in that if the last option you have
	is a flag, and the user enters args incorrectly, sometimes the usage
	message printed will miss the null and go flying off thru core...)
							--jay for spencer
*/
#include <stdio.h>
#include <ctype.h>

#define YES 1
#define NO 0
#define ERROR(msg)  {fprintf(stderr, "msg\n"); goto error; }

char	*prformat();

#ifndef	QUICK
scanargs (argc, argv, format, arglist)
#else
qscanargs (argc, argv, format, arglist)
#endif
int     argc;
char  **argv;
char   *format;
int     arglist[];
{
#ifndef	QUICK
    _scanargs (argc, argv, format, &arglist);
#else
    _qscanargs (argc, argv, format, &arglist);
#endif
}

#ifndef	QUICK
_scanargs (argc, argv, format, arglist)
#else
_qscanargs (argc, argv, format, arglist)
#endif
int     argc;
char  **argv;
char   *format;
int    *arglist[];
{
    register    check;			/* check counter to be sure all argvs
					   are processed */
    register char  *cp;
    register    cnt;
    char    tmpflg;			/* temp flag */
    char    c;
    char    numnum;			/* number of numbers already processed
					   */
    char    numstr;			/* count # of strings already
					   processed */
    char    tmpcnt;			/* temp count of # things already
					   processed */
    char    required;
    char    exflag;			/* when set, one of a set of exclusive
					   flags is set */
    char    excnt;			/* count of which exclusive flag is
					   being processed */
    char   *ncp;			/* remember cp during flag scanning */
#ifndef	QUICK
    char   *cntrl;			/* control string for scanf's */
    char    junk[2];			/* junk buffer for scanf's */

    cntrl = "% %1s";			/* control string initialization for
					   scanf's */
#endif
    check = numnum = numstr = 0;
    cp = format;
    while (*cp)
    {
	required = NO;
	switch (*(cp++))
	{
	    default: 			/* all other chars */
		break;
	    case '!': 			/* required argument */
		required = YES;
	    case '%': 			/* not required argument */
		switch (tmpflg = *(cp++))
		{
		    case '-': 		/* argument is flag */
		    /* go back to label */
			ncp = cp-1;	/* remember */
			cp -= 3;
			for (excnt = exflag = 0
				; *cp != ' ' && !(*cp=='-' &&(cp[-1]=='!'||cp[-1]=='%'));
				(--cp, excnt++))
			{
			    for (cnt = 1; cnt < argc; cnt++)
			    {
			    /* flags all start with - */
				if (*argv[cnt] == '-' && !isdigit(argv[cnt][1]))
				    if (*(argv[cnt] + 1) == *cp)
				    {
					if (*(argv[cnt] + 2) != 0)
					    ERROR (extra flags ignored);
					if (exflag)
					    ERROR (more than one exclusive flag chosen);
					exflag++;
					required = NO;
					check += cnt;
					**arglist |=
					    (1 << excnt);
					break;
				    }
			    }
			}
			if (required)
			    ERROR (flag argument missing);
			cp = ncp;
			if (!exflag)	/* if no flags scanned, skip */
			{
			    while (*++cp != ' ' && *cp)
				if (*cp == '!' || *cp == '%')
				    arglist++;
			}
			else
			    cp++;	/* skip over - */
			while (*cp == ' ')
			    cp++;
			arglist++;
			break;
		    case 's': 		/* char string */
		    case 'd': 		/* decimal # */
		    case 'o': 		/* octal # */
		    case 'x': 		/* hexadecimal # */
#ifndef	QUICK
		    case 'f': 		/* floating # */
#endif
		    case 'D': 		/* long decimal # */
		    case 'O': 		/* long octal # */
		    case 'X': 		/* long hexadecimal # */
#ifndef	QUICK
		    case 'F': 		/* double precision floating # */
#endif
			tmpcnt = tmpflg == 's' ? numstr : numnum;
			for (cnt = 1; cnt < argc; cnt++)
			{
			    if (tmpflg == 's')/* string */
			    {
				if ((c = *argv[cnt]) == '-')
				    continue;
				if (c >= '0' && c <= '9')
				    continue;
				if (tmpcnt-- != 0)
				    continue;
				**arglist = (int) argv[cnt];
				check += cnt;
				numstr++;
				required = NO;
				break;
			    }
			    if (*argv[cnt] == '-')
			    {
				if(!isdigit (*(argv[cnt] + 1)))
				    continue;
			    }
			    else if (!isdigit(*argv[cnt]))
				continue;
			    if (tmpcnt-- != 0)/* skip to new one */
				continue;
#ifndef	QUICK
			/* kludge for sscanf */
			    if ((tmpflg == 'o' || tmpflg == 'O')
				    && *argv[cnt] > '7')
				ERROR (Bad numeric argument);
			    cntrl[1] = tmpflg;/* put in conversion */
			    if (sscanf (argv[cnt], cntrl, *arglist
					,junk) != 1)
#else
			    if (numcvt(argv[cnt], tmpflg, *arglist) != 1)
#endif
				ERROR (Bad numeric argument);
			    check += cnt;
			    numnum++;
			    required = NO;
			    break;
			}
			if (required)
			    switch (tmpflg)
			    {
				case 'x':
				case 'X':
				    ERROR (missing hexadecimal argument);
				case 's':
				    ERROR (missing string argument);
				case 'o':
				case 'O':
				    ERROR (missing octal argument);
				case 'd':
				case 'D':
				    ERROR (missing decimal argument);
				case 'f':
				case 'F':
				    ERROR (missing floating argument);
			    }
			arglist++;
			while (*cp == ' ')
			    cp++;
			break;
		    default: 		/* error */
			fprintf (stderr, "error in call to scanargs\n");
			return (0);
		}
	}
    }
/*  Count up empty flags */
    for (cnt=1; cnt<argc; cnt++)
	if (argv[cnt][0] == '-' && argv[cnt][1] == 0)
	    check += cnt;
 /* sum from 1 to N = n*(n+1)/2 used to count up checks */
    if (check != (((argc - 1) * argc) / 2))
	ERROR (extra arguments not processed);
	    return (1);

error:
    fprintf (stderr, "usage : ");
    if (*(cp = format) != ' ')
	while (putc (*cp++, stderr) != ' ');
    else
	fprintf (stderr, "?? ");
    while (*cp == ' ')
	cp++;
    prformat (cp, NO);
    return 0;
}

char *
prformat (format, recurse)
char   *format;
{
    register char  *cp;
    char    required;

    cp = format;
    if (recurse)
	putc (' ', stderr);
    required = NO;
    while (*cp)
    {
	if (recurse && *cp == ' ')
	    break;
	switch (*cp)
	{
	    default:
		cp++;
		break;
	    case '!':
		required = YES;
	    case '%':
		switch (*++cp)
		{
		    case '-': 		/* flags */
			if (!required)
			{
			    putc ('[', stderr);
			    putc ('-', stderr);
			}
			else
			{
			    putc ('-', stderr);
			    putc ('{', stderr);
			}
			cp = format;
			while (*cp != '%' && *cp != '!')
			    putc (*cp++, stderr);
			if (required)
			    putc ('}', stderr);
			cp += 2;	/* skip !- or %- */
			if (*cp != ' ')
			    cp = prformat (cp, YES);
					/* this is a recursive call */
			if (!required)
			    putc (']', stderr);
			break;
		    case 's': 		/* char string */
		    case 'd': 		/* decimal # */
		    case 'o': 		/* octal # */
		    case 'x': 		/* hexadecimal # */
		    case 'f': 		/* floating # */
		    case 'D': 		/* long decimal # */
		    case 'O': 		/* long octal # */
		    case 'X': 		/* long hexadecimal # */
		    case 'F': 		/* double precision floating # */
			if (!required)
			    putc ('[', stderr);
			for (; format < cp - 1; format++)
			    putc (*format, stderr);
			if (!required)
			    putc (']', stderr);
			break;
		    default:
			break;
		}
		required = NO;
		format = ++cp;
		putc (' ', stderr);
	}
    }
    if (!recurse)
	putc ('\n', stderr);
    return (cp);
}

#ifdef	QUICK
numcvt(str, conv, val)
register char *str;
char conv;
int *val;
{
    int base, neg = 0;
    register unsigned int d;
    long retval = 0;
    register char *digits;
    extern char *index();
    if (conv == 'o' || conv == 'O')
	base = 8;
    else if (conv == 'd' || conv == 'D')
	base = 10;
    else if (conv == 'x' || conv == 'X')
	base = 16;
    else
	return 0;

    if (*str == '-')
    {
	neg = 1;
	str++;
    }
    while (*str)
    {
	if (*str >= '0' && *str < '0'+base)
	    d = *str - '0';
	else if (base == 16 && *str >= 'a' && *str <= 'f')
	    d = 10 + *str - 'a';
	else if (base == 16 && *str >= 'A' && *str <= 'F')
	    d = 10 + *str - 'A';
	else
	    return 0;
	retval = retval*base + d;
	str++;
    }
    if (neg)
	retval = -retval;
    if (conv == 'D' || conv == 'O' || conv == 'X')
	*(long *) val = retval;
    else
	*val = (int) retval;
    return 1;
}
#endif	QUICK

SHAR_EOF
fi # end of overwriting check
if test -f 'undump.c'
then
	echo shar: will not over-write existing file "'undump.c'"
else
cat << \SHAR_EOF > 'undump.c'
/*
 *      %W%     %E%     %Q%
 */

/*
 * This program was advertised on unix-wizards.  I have had such a large
 * response I'm sending it out to the world.
 * 
 * Here is the source.  It works fine under 4.1bsd, I see no fundamental
 * reason why it shouldn't work on an 11. (Except possibly small format
 * changes in exec header or user structure.)  No documentation yet.
 * Usage is
 *        undump new-a.out-file [old-a.out-file] [core-file]
 * where old-a.out-file and core-file default to "a.out" and "core",
 * respectively.  Probably should have an option to not require
 * old-a.out-file if the core came from a 407 file.
 * 
 * It doesn't preserve open files, and the program is re-entered at main
 * when you run it.  It's used locally to dump a lisp and restart it.
 * 
 * It requires a local subroutine called scanargs, somewhat similar to
 * getopt (I think).  You should be able to easily get around this, though.
 * =Spencer
 *
 * Changed for COFF format by Piet van Oostrum (piet at ruuinfvax.uucp)
 * 18-Aug-1987
 *
 */


/*
 * undump.c - Convert a core file to an a.out.
 *
 * Author:	Spencer W. Thomas
 * 		Computer Science Dept.
 * 		University of Utah
 * Date:	Wed Feb 17 1982
 * Copyright (c) 1982 Spencer W. Thomas
 *
 * Usage:
 * undump new-a.out [a.out] [core]
 */

#include <sys/types.h>
#include <signal.h>
#include <sys/dir.h>
#include <sys/sysmacros.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/user.h>
#include <sys/stat.h>
#include <a.out.h>
#include <core.h>

#define UPAGES		2 /*  size of u-structure in clicks */
#define OMAGIC 0150
#define PSIZE	    2048 /* click-size */

struct user u;
static struct filehdr f_hdr;
static struct aouthdr f_ohdr;
static struct scnhdr thdr, dhdr, bhdr;
long	OldSym;

main(argc, argv)
char **argv;
{
    char *new_name, *a_out_name = "a.out", *core_name = "core";
    int new, a_out, core;

    if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s",
	    &new_name, &a_out_name, &core_name)
		    != 1)
	exit(1);

    if ((a_out = open(a_out_name, 0)) <0)
    {
	perror(a_out_name);
	exit(1);
    }
    if ((core = open(core_name, 0)) <0)
    {
	perror(core_name);
	exit(1);
    }
    if ((new = creat(new_name, 0666)) <0)
    {
	perror(new_name);
	exit(1);
    }

    read_u(core);
    make_hdr(new, a_out);
    copy_text(new, a_out);
    copy_data(new, core);
    copy_sym(new, a_out);
    close(new);
    close(core);
    close(a_out);
    mark_x(new_name);
}

/*
 * read the u structure from the core file.
 */
read_u(core)
int core;
{
    if (read (core, &u, sizeof u) != sizeof u )
    {
	perror("Couldn't read user structure from core file");
	exit(1);
    }
}

/*
 * Make the header in the new a.out from the header in the old one
 * modified by the new data size.
 */
make_hdr(new, a_out)
     int new, a_out;
{
  auto struct scnhdr scntemp;		/* Temporary section header */
  register int scns;
  
  if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)
      || f_hdr.f_opthdr == 0
      || read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
    {
      perror("Couldn't read header from a.out file");
      exit(1);
    }
  
  /*
  if BADMAG(f_ohdr)
    {
      fprintf(stderr, "a.out file doesn't have legal magic number\n");
      exit(1);
    }
	*/ /* not done for a while JAH */
  /*
  if (f_ohdr.magic != u.u_exdata.ux_mag ||
      f_ohdr.tsize != u.u_exdata.ux_tsize ||
      f_ohdr.dsize != u.u_exdata.ux_dsize ||
      f_ohdr.entry != u.u_exdata.ux_entloc)
    {
      fprintf(stderr, "Core file didn't come from this a.out\n");
      exit(1);
    }
	 *//* not done for a while */
  f_hdr.f_timdat = time(0);
  printf("Data segment size was %u", f_ohdr.dsize);
  f_ohdr.dsize = ctob(u.u_dsize);
  f_ohdr.bsize = 0;			/* all data is inited now! */
  printf(" now is %u\n", f_ohdr.dsize);
  
  /* Loop through section headers, copying them in */
  for (scns = f_hdr.f_nscns; scns > 0; scns--) {
    if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
      {
	perror ("Couldn't read section header from a.out file");
	exit(1);
      }
    if (scntemp.s_scnptr > 0L)
      {
      }
    if (strcmp (scntemp.s_name, ".text") == 0)
      {
	thdr = scntemp;
      }
    else if (strcmp (scntemp.s_name, ".data") == 0)
      {
	dhdr = scntemp;
      }
    else if (strcmp (scntemp.s_name, ".bss") == 0)
      {
	bhdr = scntemp;
      }
  }	    
  
  dhdr.s_size = f_ohdr.dsize;
  bhdr.s_size = 0L;
  bhdr.s_scnptr = 0L;
  
  OldSym = f_hdr.f_symptr;

  if (f_hdr.f_symptr > 0L)
    {
      f_hdr.f_symptr = dhdr.s_scnptr + dhdr.s_size;
    }
  
  if (thdr.s_lnnoptr > 0L) 
    {
      thdr.s_lnnoptr += 0;  /* ihave no soultion (i.e time) for that! JAH */
    }
  
  if (write(new, &f_hdr, sizeof f_hdr) != sizeof f_hdr
      || write(new, &f_ohdr, sizeof f_ohdr) != sizeof f_ohdr
      || write (new, &thdr, sizeof (thdr)) != sizeof (thdr)
      || write (new, &dhdr, sizeof (dhdr)) != sizeof (dhdr)
      || write (new, &bhdr, sizeof (bhdr)) != sizeof (bhdr))
    {
      perror("Couldn't write header to new a.out file");
      exit(1);
    }
  
  return (0);
}

/*
 * Copy the text from the a.out to the new a.out
 */
copy_text(new, a_out)
     int new, a_out;
{
  char page[PSIZE];
  int txtcnt = f_ohdr.tsize;
  
  lseek (new, thdr.s_scnptr, 0);
  lseek(a_out, thdr.s_scnptr, 0);
  if (f_ohdr.magic == OMAGIC)
    {
      printf("a.out file is not shared text, getting text from core file\n");
      return;
    }
  while (txtcnt >= PSIZE)
    {
      if (read(a_out, page, PSIZE) != PSIZE)
	{
	  perror("Read failure on a.out text");
	  exit(1);
	}
      if (write(new, page, PSIZE) != PSIZE)
	{
	  perror("Write failure in text segment");
	  exit(1);
	}
      txtcnt -= PSIZE;
    }
  if (txtcnt)
    {
      if (read(a_out, page, txtcnt) != txtcnt)
	{
	  perror("Read failure on a.out text");
	  exit(1);
	}
      if (write(new, page, txtcnt) != txtcnt)
	{
	  perror("Write failure in text segment");
	  exit(1);
	}
    }
}

/*
 * copy the data from the core file to the new a.out
 */
copy_data(new, core)
     int new, core;
{
  char page[PSIZE];
  int datacnt = f_ohdr.dsize;
  lseek (new, dhdr.s_scnptr, 0);
  
  if (f_ohdr.magic == OMAGIC)
    datacnt += f_ohdr.tsize;
  lseek(core, ctob(UPAGES), 0);
  while (datacnt >= PSIZE)
    {
      if (read(core, page, PSIZE) != PSIZE)
	{
	  perror("Read failure on core data");
	  exit(1);
	}
      if (write(new, page, PSIZE) != PSIZE)
	{
	  perror("Write failure in data segment");
	  exit(1);
	}
      datacnt -= PSIZE;
    }
  if (datacnt)
    {
      if (read(core, page, datacnt) != datacnt)
	{
	  perror("Read failure on core data");
	  exit(1);
	}
      if (write(new, page, datacnt) != datacnt)
	{
	  perror("Write failure in data segment");
	  exit(1);
	}
    }
}

/*
 * Copy the relocation information and symbol table from the a.out to the new
 */
copy_sym(new, a_out)
     int new, a_out;
{
  char page[PSIZE];
  int n;
  
  lseek(a_out, OldSym, 0);	/* skip over data segment */
  while ((n = read(a_out, page, PSIZE)) > 0)
    {
      if (write(new, page, n) != n)
	{
	  perror("Error writing symbol table to new a.out");
	  fprintf(stderr, "new a.out should be ok otherwise\n");
	  return;
	}
    }
  if (n < 0)
    {
      perror("Error reading symbol table from a.out");
      fprintf(stderr, "new a.out should be ok otherwise\n");
    }
}

/*
 * After succesfully building the new a.out, mark it executable
 */
mark_x(name)
char *name;
{
    struct stat sbuf;
    int um;

    um = umask(777);
    umask(um);
    if (stat(name, &sbuf) == -1)
    {
	perror ("Can't stat new a.out");
	fprintf(stderr, "Setting protection to %o\n", 0777 & ~um);
	sbuf.st_mode = 0777;
    }
    sbuf.st_mode |= 0111 & ~um;
    if (chmod(name, sbuf.st_mode) == -1)
	perror("Couldn't change mode of new a.out to executable");

}
SHAR_EOF
fi # end of overwriting check
if test -f 'undump.1'
then
	echo shar: will not over-write existing file "'undump.1'"
else
cat << \SHAR_EOF > 'undump.1'
.TH UNDUMP 1 "University of Utah"
.SH NAME
undump \- convert a core dump to an executable a.out file
.SH SYNOPSIS
undump new-a.out-file [old-a.out-file] [core-file]
.SH DESCRIPTION
Undump takes a core dump file and the executable "a.out" file which
caused it and produces a new executable file with all static
variables initialised to the values they held at the time of the
core dump.  It is primarily useful for programs which take a long time
to initialise themselves, e.g. Emacs.  The idea is to go through all of
the initialisations and then create a core dump (e.g. with the abort()
call).  One then uses undump to make a new executable file with all of it
done.  This usually implies the use of a global flag variable which says
whether or not initialisation has been done.
.PP
Undump's arguments, old-a.out-file and core-file, default to "a.out" and
"core", respectively.
.PP
A few things to keep in mind about undump:
.IP
It doesn't preserve open files.
.IP
The program will be re-entered at the beginning of main(), not at the point
where the core dump occurred.
.SH BUGS
Probably should have an option to not require
old-a.out-file if the core came from a 407 file.
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0




   |
   |   _   _   _  |
   |  / ) / ) / ) --
 __) (_/ (_/   /  (__

Tel: +3473 75154
Adr: nixdorf computer bv
	 mijlweg 9
	 4124 pj vianen
	 the netherlands
uucp:  ....mcvax!unido!nixpbe!helberg.via



More information about the Comp.unix.wizards mailing list