/* * undump - resurrect a core file into a running program. * * for UNIX System V on a 3Bx * that uses the Common Object File Format * * Author: * Lou Salkind * New York University * Tue Mar 3 13:18:25 EST 1987 * * Adapted from: * Spencer Thomas's undump and the file unexec.c in GNU emacs */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define PAGE_SIZE NBPC struct filehdr fh; AOUTHDR aout; struct scnhdr tsc; struct scnhdr dsc; struct scnhdr bsc; long bias; long lnnoptr; long text_scnptr; long data_scnptr; long symlocptr; main(argc, argv) char **argv; { FILE *afp, *cfp, *nfp; struct user u; long off; long size; struct scnhdr sc; int i, n; char *a_out_name = "a.out"; char *core_name = "core"; char *new_name; if (argc < 2 || argc > 4) { fprintf(stderr, "usage: %s new [a.out [core]]\n", argv[0]); exit(1); } new_name = argv[1]; if (argc > 2) a_out_name = argv[2]; if (argc > 3) core_name = argv[3]; afp = fopen(a_out_name, "r"); if (afp == 0) Perror(a_out_name); cfp = fopen(core_name, "r"); if (cfp == 0) Perror(core_name); nfp = fopen(new_name, "w"); if (nfp == 0) Perror(new_name); if (fread(&fh, sizeof fh, 1, afp) != 1) Perror("fh read"); if (fread(&aout, sizeof aout, 1, afp) != 1) Perror("aout read"); for (i = 0; i < fh.f_nscns; i++) { if (fread(&sc, sizeof(sc), 1, afp) != 1) Perror("read"); if (strcmp(sc.s_name, ".text") == 0) { tsc = sc; } else if (strcmp(sc.s_name, ".data") == 0) { dsc = sc; } else if (strcmp(sc.s_name, ".bss") == 0) { bsc = sc; } } if (fread(&u, sizeof u, 1, cfp) != 1) Perror("core read"); if (u.u_exdata.ux_tsize != aout.tsize || u.u_exdata.ux_dsize != aout.dsize || u.u_exdata.ux_bsize != aout.bsize) { fprintf("mismatch between %s and %s sizes\n", a_out_name, core_name); exit(1); } off = USIZE*PAGE_SIZE; size = u.u_dsize *PAGE_SIZE; fh.f_flags |= F_RELFLG | F_EXEC; aout.dsize = size; aout.bsize = 0; tsc.s_size = aout.tsize; tsc.s_scnptr = sizeof(fh) + sizeof(aout); tsc.s_scnptr += fh.f_nscns * sizeof (struct scnhdr); text_scnptr = tsc.s_scnptr; lnnoptr = tsc.s_lnnoptr; symlocptr = fh.f_symptr; dsc.s_paddr = dsc.s_vaddr = aout.data_start; dsc.s_size = aout.dsize; dsc.s_scnptr = tsc.s_scnptr + tsc.s_size; data_scnptr = dsc.s_scnptr; bsc.s_paddr = bsc.s_vaddr = aout.data_start + aout.dsize; bsc.s_size = aout.bsize; bsc.s_scnptr = 0L; bias = dsc.s_scnptr + dsc.s_size - lnnoptr; if (fh.f_symptr > 0L) fh.f_symptr += bias; if (tsc.s_lnnoptr > 0L) tsc.s_lnnoptr += bias; if (fwrite(&fh, sizeof(fh), 1, nfp) != 1) Perror("fh write"); if (fwrite(&aout, sizeof(aout), 1, nfp) != 1) Perror("aout write"); if (fwrite(&tsc, sizeof(tsc), 1, nfp) != 1) Perror("ts write"); if (fwrite(&dsc, sizeof(dsc), 1, nfp) != 1) Perror("ds write"); if (fwrite(&bsc, sizeof(bsc), 1, nfp) != 1) Perror("bs write"); fseek(nfp, (long)text_scnptr, 0); copy(afp, nfp, aout.tsize); fseek(cfp, off, 0); fseek(nfp, (long)data_scnptr, 0); copy(cfp, nfp, size); copy_syms(afp, nfp); fclose(nfp); fclose(afp); fclose(cfp); mark_x(new_name); exit(0); } copy_syms(afp, nfp) register FILE *afp, *nfp; { char page[BUFSIZ]; register int n; register int nsyms; struct syment symentry; AUXENT auxentry; /* if there are line numbers, copy them */ if (lnnoptr) { if (fseek(afp, lnnoptr, 0) == -1L) Perror("ln fseek"); copy(afp, nfp, symlocptr - lnnoptr); } /* now write the symbol table */ if (fseek(nfp, fh.f_symptr, 0) == -1L) Perror("fh fseek"); for (nsyms = 0; nsyms < fh.f_nsyms; nsyms++) { if (fread(&symentry, SYMESZ, 1, afp) != 1) Perror("sym fread"); if (fwrite(&symentry, SYMESZ, 1, nfp) != 1) Perror("sym fwrite"); /* * adjust relative offsets of line numbers for * function definitions */ if (symentry.n_numaux) { if (fread(&auxentry, AUXESZ, 1, afp) != 1) Perror("aux fread"); nsyms++; if (ISFCN (symentry.n_type)) auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; if (fwrite(&auxentry, AUXESZ, 1, nfp) != 1) Perror("aux fwrite"); } } /* finally write the string table, if any */ while ((n = fread(page, 1, sizeof page, afp)) > 0) { if (fwrite(page, 1, n, nfp) != n) Perror("sym write"); } if (n < 0) Perror("sym read"); } /* * 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"); } copy(a, b, size) register FILE *a, *b; long size; { char buf[BUFSIZ]; register int i, n; while (size > 0) { i = size; if (i > sizeof buf) i = sizeof buf; if ((n = fread(buf, 1, i, a)) <= 0) Perror("copy read"); if (fwrite(buf, 1, n, b) != n) Perror("copy write"); size -= n; } } Perror(s) char *s; { perror(s); exit(1); }