Date: Tue, 25 Aug 1998 06:58:23 +0200 From: Wolfram Schneider <wosch@panke.de.freebsd.org> To: hackers@FreeBSD.ORG Subject: undump utility Message-ID: <19980825065823.A1824@panke.de>
next in thread | raw e-mail | index | archive | help
I tried to write an undump uitility for FreeBSD. It sometimes
works for the emacs, but in most cases it core'd immediately.
I don't know why. Any hints?
Wolfram
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# undump
# undump/Makefile
# undump/undump.c
#
echo c - undump
mkdir -p undump > /dev/null 2>&1
echo x - undump/Makefile
sed 's/^X//' >undump/Makefile << 'END-of-undump/Makefile'
XPROG= undump
XNOMAN=
XCLEANFILES+= sh.core sh.undump sh.undump.core
X
Xdump:
X -/bin/sh -c 'kill -6 $$$$'
X
Xtest: dump
X ./${PROG} -d sh.undump /bin/sh sh.core
X wc -c sh.undump /bin/sh
X size sh.undump /bin/sh
X ./sh.undump
X
X.include <bsd.prog.mk>
X
END-of-undump/Makefile
echo x - undump/undump.c
sed 's/^X//' >undump/undump.c << 'END-of-undump/undump.c'
X/*-
X * Copyright (c) Aug 1998 Wolfram Schneider <wosch@FreeBSD.org>, Berlin.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $Id$
X */
X
X/*
X * Convert a core dump to an executable binary. See perl -u
X *
X */
X
X#include <stdio.h>
X#include <a.out.h>
X
X/* core dump */
X#include <sys/param.h>
X#include <sys/user.h>
X
X#include <sys/types.h>
X#include <sys/mman.h>
X#include <sys/stat.h>
X#include <fcntl.h>
X#include <sys/uio.h>
X#include <unistd.h>
X
X#include <err.h>
X#include <stdlib.h>
X
Xextern char *optarg;
Xextern int optind;
X
Xint check_corefile_from_oldfile(char *oldp, char *corep);
Xint copy_text_from_oldfile_to_newfile(char *oldp, int newfd);
Xint copy_data_from_corefile_to_newfile(char *corep, int newfd);
Xint copy_symbol_from_oldfile_to_newfile(char *oldpp, int newfd, int len);
Xint set_exec_header(int newfd);
Xvoid usage();
X
X
Xint debug;
X
Xstatic struct exec oldhdr; /* exec header from old binary file */
Xstatic struct exec newhdr; /* exec header for the new file */
Xstatic struct user coreuser; /* text, data, and stack size from core dump */
X
X
Xmain(int argc, char **argv)
X{
X int c, oldfilelen;
X struct stat sb;
X
X char *newfile, *oldfile, *corefile;
X int newfd, oldfd, corefd;
X char *oldp, *corep;
X
X while((c = getopt(argc, argv, "d")) != -1) {
X switch(c) {
X case 'd':
X debug++;
X break;
X
X default:
X usage;
X exit(1);
X }
X }
X argc -= optind;
X argv += optind;
X
X /* usage: undump newfile oldfile corefile */
X if (argc < 3) {
X fprintf(stderr, "Too few arguments\n");
X usage();
X exit(1);
X }
X
X newfile = argv[0];
X oldfile = argv[1];
X corefile = argv[2];
X
X if ((newfd = open(newfile, O_CREAT | O_WRONLY, 0666)) == -1)
X err(1, "corefile: %s", corefile);
X
X if ((oldfd = open(oldfile, O_RDONLY, 0)) == -1)
X err(1, "Open oldfile: %s", oldfile);
X if (stat(oldfile, &sb) == -1)
X err(1, "Stat oldfile: %s", oldfile);
X if ((oldp = (char *)mmap((caddr_t)0, sb.st_size, PROT_READ,
X MAP_SHARED, oldfd, (off_t)0)) == MAP_FAILED)
X err(1, "mmap oldfile: %s", oldfile);
X oldfilelen = sb.st_size;
X
X if ((corefd = open(corefile, O_RDONLY, 0)) == -1)
X err(1, "corefile: %s", corefile);
X if (stat(corefile, &sb) == -1)
X err(1, "Stat corefile: %s", corefile);
X if ((corep = (char *)mmap((caddr_t)0, sb.st_size, PROT_READ,
X MAP_SHARED, corefd, (off_t)0)) == MAP_FAILED)
X err(1, "mmap corefile: %s", corefile);
X
X
X
X /* read exec header from old binary */
X oldhdr = newhdr = *(struct exec *) oldp;
X
X /* read text, data, and stack size from core dump */
X coreuser = *(struct user *) corep;
X
X
X if (check_corefile_from_oldfile(oldp, corep)) {
X fprintf(stderr, "Coredump %s was not generated from %s!\n",
X corefile, oldfile);
X exit(2);
X }
X
X copy_text_from_oldfile_to_newfile(oldp, newfd);
X copy_data_from_corefile_to_newfile(corep, newfd);
X copy_symbol_from_oldfile_to_newfile(oldp, newfd, oldfilelen);
X set_exec_header(newfd);
X
X if (fchmod(newfd, 0755) == -1)
X err(1, "set mode of new file: %s\n", newfile);
X if (close(newfd) == -1)
X err(1, "closing newfile: %s\n", newfile);
X close(oldfd);
X close(corefd);
X
X}
X
Xvoid usage ()
X{
X fprintf(stderr, "usage: undump [-d] newfile oldfile corefile\n");
X}
X
X
X/*
X * check if the corefile was
X * created from the oldfile
X */
Xint check_corefile_from_oldfile(char *oldp, char *corep)
X{
X if (debug) {
X printf("Old binary file: ");
X printf("a_text: %u, a_data: %u, a_bss: %u, a_syms: %u\n",
X oldhdr.a_text, oldhdr.a_data, oldhdr.a_bss,
X oldhdr.a_syms);
X printf("\t\t a_entry: %u, a_trsize: %u, a_drsize: %u\n",
X oldhdr.a_entry, oldhdr.a_trsize, oldhdr.a_drsize);
X
X printf("Core dump file: ");
X printf("u_tsize: %u, u_dsize: %u, u_ssize: %u\n",
X ptoa(coreuser.u_tsize),
X ptoa(coreuser.u_dsize),
X ptoa(coreuser.u_ssize));
X }
X
X if (oldhdr.a_text != ptoa(coreuser.u_tsize)) {
X return(1);
X }
X
X return (0);
X}
X
X
X/*
X * Copy text sgement from old file
X * to new file.
X */
Xint copy_text_from_oldfile_to_newfile(char *oldp, int newfd)
X{
X if (debug) {
X printf("Old binary file: N_TXTOFF: %u, N_TXTADDR: %u, "
X "a_text: %u\n",
X N_TXTOFF(oldhdr), N_TXTADDR(oldhdr), oldhdr.a_text);
X }
X
X if (lseek(newfd, (off_t)N_TXTOFF(newhdr), SEEK_SET) == -1)
X err(1, NULL);
X if (write(newfd, oldp + N_TXTOFF(oldhdr), oldhdr.a_text) == -1)
X err(1, NULL);
X
X return(0);
X};
X
X/*
X * Copy data from coredump file
X * into the data segement of the new file.
X */
X
Xint copy_data_from_corefile_to_newfile(char *corep, int newfd)
X{
X if (debug) {
X printf("Copy %u bytes from coredump data to new file\n",
X ptoa(coreuser.u_dsize));
X
X printf("Old binary file: N_DATOFF: %u, N_DATADDR: %u, "
X "a_data: %u\n",
X N_DATOFF(newhdr), N_DATADDR(newhdr), newhdr.a_data);
X
X }
X
X if (lseek(newfd, (off_t)N_DATOFF(newhdr), SEEK_SET) == -1)
X err(1, NULL);
X
X if (write(newfd, corep + ptoa(UPAGES), ptoa(coreuser.u_dsize)) == -1)
X err(1, NULL);
X
X return(0);
X};
X
X/*
X * Copy text relocations and the rest (data relocations, symbol table
X * string table) at end of the new file.
X */
X
Xint copy_symbol_from_oldfile_to_newfile(
X char *oldp, int newfd, int oldfilelen)
X{
X if (debug) {
X printf("Copy %u bytes rel + sym from old file to new file\n",
X oldfilelen - N_RELOFF(oldhdr));
X printf("N_RELOFF: %u\n", N_RELOFF(oldhdr));
X }
X
X if (lseek(newfd, (off_t)N_RELOFF(oldhdr), SEEK_SET) == -1)
X err(1, NULL);
X
X if (write(newfd, oldp + N_RELOFF(oldhdr),
X oldfilelen - N_RELOFF(oldhdr)) == -1)
X err(1, NULL);
X
X return(0);
X};
X
X
X
X
X/*
X * Set the exec header values of the
X * new file
X */
Xint set_exec_header(int newfd)
X{
X /* set data segment size */
X newhdr.a_data = ptoa(coreuser.u_dsize);
X
X /* the bss segment is now in the data of the new file */
X newhdr.a_bss = 0;
X
X
X if (debug) {
X printf("New binary file: ");
X printf("a_text: %u, a_data: %u, a_bss: %u, a_syms: %u\n",
X newhdr.a_text, newhdr.a_data, newhdr.a_bss,
X newhdr.a_syms);
X printf("\t\t a_entry: %u, a_trsize: %u, a_drsize: %u\n",
X newhdr.a_entry, newhdr.a_trsize, newhdr.a_drsize);
X }
X
X /* write the exec header at the beginning of the new file */
X if (lseek(newfd, (off_t)0, SEEK_SET) == -1)
X err(1, NULL);
X
X if (write(newfd, &newhdr, sizeof(newhdr)) == -1)
X err(1, NULL);
X
X return(0);
X};
X
END-of-undump/undump.c
exit
--
Wolfram Schneider <wosch@freebsd.org> http://www.freebsd.org/~w/
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19980825065823.A1824>
