diff options
Diffstat (limited to 'obsolete/support/undump/Encore/undump.c')
-rw-r--r-- | obsolete/support/undump/Encore/undump.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/obsolete/support/undump/Encore/undump.c b/obsolete/support/undump/Encore/undump.c new file mode 100644 index 0000000000..02d8b1d582 --- /dev/null +++ b/obsolete/support/undump/Encore/undump.c @@ -0,0 +1,374 @@ +/* + * 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 + */ + + +/* + * 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 <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/stat.h> +#include <aouthdr.h> +#include <filehdr.h> +#include <scnhdr.h> +#include <linenum.h> +#include <sys/ptrace.h> + +#define PSIZE 10240 +#define MAXSCNS 8 + +struct ptrace_user u; +AOUTHDR ahdr, oahdr; +struct filehdr fhdr, ofhdr; +struct scnhdr scns[MAXSCNS]; +int nscns; +long cur_pos, sym_top; + + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *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 = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + 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); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + 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) +FILE *new, *a_out; +{ + + int i; + +/* sym_top points to the beginning of the line#/sym/str data */ + +/* + * read file header from a.out + */ + + if (fread(&fhdr, sizeof fhdr, 1, a_out) != 1) + { + perror("Couldn't read file header from a.out file"); + exit(1); + } + +/* + * read system header from a.out COFF format + */ + + if (fhdr.f_opthdr > 0) + { + if (fread(&ahdr, sizeof ahdr, 1, a_out) != 1) + { + perror("Couldn't read system file header from a.out file"); + exit(1); + } + +/* + * read section headers from a.out COFF format + */ + + nscns = fhdr.f_nscns; + for(i=0;(i != nscns);i++) { + if (fread(&scns[i], sizeof(struct scnhdr), 1, a_out) != 1) { + perror("Couldn't read section headers from a.out file"); + exit(1); + } + } + } + + +/* if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } */ + + + + if (ahdr.magic != u.pt_aouthdr.magic || + ahdr.tsize != u.pt_aouthdr.tsize || + ahdr.dsize != u.pt_aouthdr.dsize || + ahdr.entry != u.pt_aouthdr.entry) + { + fprintf(stderr, "Core file didn't come from this a.out\n"); + exit(1); + } + + printf("Data segment size was %u", ahdr.dsize); + ahdr.dsize = u.pt_dsize; + ahdr.bsize = 0; /* all data is inited now! */ + printf(" now is %u\n", ahdr.dsize); + + +/* + * point to top of old line#/symbol/string info if there is any so + * we can find it later... + */ + + sym_top = 0; + if (scns[0].s_nlnno != 0) + sym_top = scns[0].s_lnnoptr; + else if (fhdr.f_nsyms != 0) + sym_top = fhdr.f_symptr; + + scns[1].s_size = u.pt_dsize; + scns[2].s_size = 0; + scns[2].s_vaddr = 0; + scns[2].s_paddr = 0; + + cur_pos = scns[1].s_scnptr + scns[1].s_size; + + if (scns[0].s_nlnno != 0) { + scns[0].s_lnnoptr = cur_pos; + cur_pos += scns[0].s_nlnno * sizeof(struct lineno); + } + if (fhdr.f_nsyms != 0) { + fhdr.f_symptr = cur_pos; + } + + + + + if (fwrite(&fhdr, sizeof fhdr, 1, new) != 1) + { + perror("Couldn't write file header to new a.out file"); + exit(1); + } + if (fhdr.f_opthdr > 0) + { + if (fwrite(&ahdr, sizeof ahdr, 1, new) != 1) + { + perror("Couldn't write system file header to new a.out file"); + exit(1); + } + for(i=0;(i != nscns);i++) { + if (fwrite(&scns[i], sizeof(struct scnhdr), 1, new) != 1) { + perror("Couldn't write section headers to new a.out file"); + exit(1); + } + } + } + +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt; + + txtcnt = ahdr.tsize; + + fseek(new, scns[0].s_scnptr, 0); + fseek(a_out, scns[0].s_scnptr, 0); + +/* if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); * skip over text * + return; + } */ + + + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; + int datacnt; + + + datacnt = u.pt_dsize; + +/* if (hdr.a_magic == OMAGIC) + datacnt += u.u_tsize; */ + fseek(core,(long) sizeof(struct ptrace_user), 0); + fseek(new, scns[1].s_scnptr, 0); + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + 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) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + + fseek(a_out, sym_top, 0); /* skip over data segment */ + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != 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"); + +} + |