Xref: utzoo comp.emacs:2884 comp.sys.hp:498 Path: utzoo!mnetor!uunet!mcvax!enea!zyx!aj From: aj@zyx.UUCP (Arndt Jonasson) Newsgroups: comp.emacs,comp.sys.hp Subject: Re: HP9000, gnuemacs Message-ID: <2248@zyx.UUCP> Date: 24 Feb 88 11:00:21 GMT References: <470@gordon.UUCP> Reply-To: aj@zyx.UUCP (Arndt Jonasson) Organization: ZYX Sweden AB, Stockholm Lines: 416 Keywords: gnuemacs, hp9000 In article <470@gordon.UUCP> sra@gordon.UUCP (Sreedhar Annamalai) writes: >I have been trying to install gnuemacs on the HP9000/840 and am >having trouble compiling src/unexec.c. 'struct exec', MAGIC and >N_BADMAG are being used in this file and must have been declared >in apparently. The of HP9000/840 however does >not have any of these definitions. I could get the structure >definitions from a BSD4.2 machine and insert them but I doubt that >will work for this System V machine. I thought of just replying by mail at first, but this probably interests more people, so I'll post it. Below is a shar archive, containing two files: unexec.c and unexec.s800. Both contain unexec functions that work. unexec.s800 just barely works. Don't try to run adb on the dumped image; it will dump core. unexec.c is my own; it saves the symbol table, but not any extra debug info (which means you can debug with adb, but not xdb in source mode). Arndt Jonasson, ZYX Sweden AB, Styrmansgatan 6, 114 54 Stockholm, Sweden email address: !mcvax!enea!zyx!aj = aj@zyx.SE ------------------------------------------------------------------------ # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by arndt at lynx on Wed Feb 24 11:56:13 1988 # # This archive contains: # unexec.c unexec.s800 # LANG=""; export LANG echo x - unexec.c cat >unexec.c <<'@EOF' /* Public domain unexec for HP-UX series 800. Written 880220 Author: Arndt Jonasson uucp: aj@zyx.SE Bug: only saves sections 0 and 1 (code and data), not section 2 (debug info) */ #include #include #include #include #include #include extern int etext, edata, end; #include #define fseek lseek #define fclose close #define BAD_OPEN(f) (f == -1) #define slurp(f, x) if (read (f, &(x), sizeof (x)) != sizeof (x)) \ fatal_error ("slurp") static fatal_error (msg) char *msg; { printf ("%s\n", msg); exit (1); } #if 0 main (argc, argv) int argc; char **argv; { static int first_time = 1; if (first_time) { printf ("dumping to %s\n", argv[2]); first_time = 0; unexec (argv[2], argv[1], 0, 0, 0); } else printf ("Tjohej, dumpad!\n"); } #endif unexec (new, old, data_start, bss_start, entry_address) char *new, *old; unsigned data_start, bss_start, entry_address; { struct header hdr; struct som_exec_auxhdr auxhdr; int n, i; char buf[2048]; int in, out; char *start_of_data_area = (char *) 0x40000000; int file_data_start, data_size; if (entry_address != 0) fatal_error ("can't handle non-zero start address yet"); if (bss_start == 0) bss_start = (unsigned) sbrk (0); else fatal_error ("can't handle non-default bss start yet"); /* Currently, data_start is ignored */ in = open (old, O_RDONLY, 0); if (BAD_OPEN (in)) fatal_error ("couldn't open old file"); out = open (new, O_RDWR+O_CREAT, 0666); if (BAD_OPEN (out)) fatal_error ("couldn't open new file"); slurp (in, hdr); n = hdr.aux_header_location; fseek (in, hdr.aux_header_location, 0); slurp (in, auxhdr); if (auxhdr.som_auxhdr.type != HPUX_AUX_ID) fatal_error ("not right header type"); file_data_start = auxhdr.exec_dfile; data_size = auxhdr.exec_dsize; if (file_data_start % 2048 != 0) fatal_error ("data section doesn't start at 2K boundary"); #if 0 file_data_start = file_data_start + data_size; #endif fseek (in, 0, 0); for (i = 0; i < file_data_start; i += 2048) { if (read (in, buf, 2048) != 2048) fatal_error ("error in fread"); if (write (out, buf, 2048) != 2048) fatal_error ("error in fwrite"); } bss_start = (int) sbrk (0); bss_start = 2048 * ((bss_start - 1) / 2048 + 1); i = 0; while (i < ((char *) bss_start) - start_of_data_area) { if (write (out, start_of_data_area + i, 2048) != 2048) fatal_error ("error in fwrite 2"); i += 2048; } fseek (out, 0, 0); hdr.som_length = file_data_start + ((char *) bss_start) - start_of_data_area; if (write (out, &hdr, sizeof (hdr)) != sizeof (hdr)) fatal_error ("error in fwrite"); fseek (out, hdr.aux_header_location, 0); auxhdr.exec_dsize = ((char *) bss_start) - start_of_data_area; auxhdr.exec_bsize = 0; if (write (out, &auxhdr, sizeof (auxhdr)) != sizeof (auxhdr)) fatal_error ("error in fwrite"); fclose (in); fclose (out); mark_x (new); } static mark_x (name) char *name; { struct stat sbuf; int um = umask (777); umask (um); if (stat (name, &sbuf) < 0) fatal_error ("getting protection on %s", name); sbuf.st_mode |= 0111 & ~um; if (chmod (name, sbuf.st_mode) < 0) fatal_error ("setting protection on %s", name); } @EOF chmod 664 unexec.c echo x - unexec.s800 cat >unexec.s800 <<'@EOF' /* * 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. * * It doesn't preserve open files, and the program is re-entered at main * when you run it. */ /* * undump.c - Convert a core file to an a.out. * * Usage: * undump new-a.out [a.out] [core] */ #include #include #include #include #include #include #include #include "config.h" #define PSIZE 10240 struct header hdr,ohdr; unsigned datacnt; unsigned datastart; unsigned dataend; unexec( new_name, a_name, data_start, bss_start, entry_address) char *new_name, *a_name; unsigned data_start, bss_start, entry_address; { FILE *new, *a_out, *core; unsigned pagemask; /* avoid fclose hazards... */ char buf0[BUFSIZ]; char buf1[BUFSIZ]; pagemask = NBPG -1; datastart = DATA_START; dataend = ((sbrk(0) + pagemask) &~pagemask); if(dataend < datastart){ fprintf(stderr, "unexec error: data ends before beginning.\n"); return(-1); } datacnt = dataend - datastart; if ((a_out = fopen(a_name, "r")) == NULL) { perror(a_name); exit(1); } (void) setbuf(a_out, buf0); if ((new = fopen(new_name, "w")) == NULL) { perror(new_name); exit(1); } (void) setbuf(a_out, buf1); make_hdr(new, a_out, entry_address); copy_text(new, a_out); copy_data(new); fclose(new); fclose(a_out); mark_x(new_name); return(0); } /* * Make the header in the new a.out from the header in the old one * modified by the new data size. */ #ifdef hp9000s800 #undef N_BADMAG #define N_BADMAG(h) (h.a_magic != SHARE_MAGIC) struct som_exec_auxhdr auxhdr,oauxhdr; #endif hp9000s800 make_hdr(new, a_out, entry_addr) FILE *new, *a_out; unsigned entry_addr; { if (fread(&hdr, sizeof hdr, 1, a_out) != 1) { perror("Couldn't read header from a.out file"); exit(1); } ohdr = hdr; if (fread(&auxhdr, sizeof auxhdr, 1, a_out) != 1) { perror("Couldn't read auxiliary header from a.out file"); exit(1); } oauxhdr = auxhdr; printf("Bss segment size was %u\n", auxhdr.exec_bsize); printf("Data segment size was %u", auxhdr.exec_dsize); /* this is very hackly */ /* do just enough to make the exec loader happy */ auxhdr.exec_dsize = datacnt; auxhdr.exec_bsize = 0; /* all data is inited now! */ auxhdr.exec_tfile = roundup(hdr.aux_header_location + hdr.aux_header_size,NBPG); auxhdr.exec_dfile = roundup(auxhdr.exec_tfile+auxhdr.exec_tsize,NBPG); printf(" now is %u\n", auxhdr.exec_dsize); printf("Data segment loc was %u", auxhdr.exec_dmem); auxhdr.exec_dmem = datastart; printf(" now is %u\n", auxhdr.exec_dmem); /* entry point unchanged. */ if (fwrite(&hdr, sizeof hdr, 1, new) != 1) { perror("Couldn't write header to new a.out file"); exit(1); } if (fwrite(&auxhdr, sizeof auxhdr, 1, new) != 1) { perror("Couldn't write auxiliary header 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 = auxhdr.exec_tsize; if (hdr.a_magic == EXEC_MAGIC) { printf("a.out file is not shared text, this wont work.\n"); exit(1); } fseek(new, auxhdr.exec_tfile, 0); fseek(a_out, oauxhdr.exec_tfile, 0); 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) FILE *new; { fseek(new,auxhdr.exec_dfile,0); if (fwrite(datastart,datacnt,1,new) != 1) { perror("Write failure in data segment"); exit(1); } } /* * 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"); } @EOF chmod 664 unexec.s800 exit 0 -- Arndt Jonasson, ZYX Sweden AB, Styrmansgatan 6, 114 54 Stockholm, Sweden email address: !mcvax!enea!zyx!aj = aj@zyx.SE