Xref: utzoo comp.sys.att:5359 comp.unix.wizards:14388 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!nrl-cmf!ames!amdcad!sun!pitstop!sundc!seismo!uunet!mcvax!hp4nl!targon!nixvia!joost From: joost@nixvia.UUCP (joost helberg) Newsgroups: comp.sys.att,comp.unix.wizards Subject: Re: Looking for "undump" for SysV Summary: I got one undump.c for coff-files, the only thing it won't do is copying the line-number info when comiled with -g. Keywords: undump memory core TeX Message-ID: <101@nixvia.UUCP> Date: 27 Jan 89 14:06:18 GMT References: <404@cwjcc.CWRU.Edu> Organization: Nixdorf Computer bv., EG4, Vianen, The Netherlands Lines: 815 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@utah-20, decvax!{harpo,randvax}!utah-cs!lepreau Spencer Thomas thomas@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 #include #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= '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@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 #include #include #include #include #include #include #include #include #include #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