/* * 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 #include #include #include #include #include #include #include #include #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"); }