|
|
1.1 ! root 1: /* Unexec for MIPS (including IRIS4D). ! 2: Copyright (C) 1988 Free Software Foundation, Inc. ! 3: ! 4: Note that the GNU project considers support for MIPS operation ! 5: a peripheral activity which should not be allowed to divert effort ! 6: from development of the GNU system. Changes in this code will be ! 7: installed when users send them in, but aside from that ! 8: we don't plan to think about it, or about whether other Emacs ! 9: maintenance might break it. ! 10: ! 11: This program is free software; you can redistribute it and/or modify ! 12: it under the terms of the GNU General Public License as published by ! 13: the Free Software Foundation; either version 1, or (at your option) ! 14: any later version. ! 15: ! 16: This program is distributed in the hope that it will be useful, ! 17: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 18: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 19: GNU General Public License for more details. ! 20: ! 21: You should have received a copy of the GNU General Public License ! 22: along with this program; if not, write to the Free Software ! 23: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 24: ! 25: In other words, you are welcome to use, share and improve this program. ! 26: You are forbidden to forbid anyone else to use, share and improve ! 27: what you give them. Help stamp out software-hoarding! */ ! 28: ! 29: #include "config.h" ! 30: #include <sys/types.h> ! 31: #include <sys/file.h> ! 32: #include <sys/stat.h> ! 33: #include <stdio.h> ! 34: #include <varargs.h> ! 35: #include <filehdr.h> ! 36: #include <aouthdr.h> ! 37: #include <scnhdr.h> ! 38: #include <sym.h> ! 39: ! 40: #if defined (IRIS_4D) || defined (sony) ! 41: #include "getpagesize.h" ! 42: #include <fcntl.h> ! 43: #endif ! 44: ! 45: static void fatal_unexec (); ! 46: static int mark_x (); ! 47: ! 48: #define READ(_fd, _buffer, _size, _error_message, _error_arg) \ ! 49: errno = EEOF; \ ! 50: if (read (_fd, _buffer, _size) != _size) \ ! 51: fatal_unexec (_error_message, _error_arg); ! 52: ! 53: #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \ ! 54: if (write (_fd, _buffer, _size) != _size) \ ! 55: fatal_unexec (_error_message, _error_arg); ! 56: ! 57: #define SEEK(_fd, _position, _error_message, _error_arg) \ ! 58: errno = EEOF; \ ! 59: if (lseek (_fd, _position, L_SET) != _position) \ ! 60: fatal_unexec (_error_message, _error_arg); ! 61: ! 62: extern int errno; ! 63: extern int sys_nerr; ! 64: extern char *sys_errlist[]; ! 65: #define EEOF -1 ! 66: ! 67: static struct scnhdr *text_section; ! 68: static struct scnhdr *init_section; ! 69: static struct scnhdr *finit_section; ! 70: static struct scnhdr *rdata_section; ! 71: static struct scnhdr *data_section; ! 72: static struct scnhdr *lit8_section; ! 73: static struct scnhdr *lit4_section; ! 74: static struct scnhdr *sdata_section; ! 75: static struct scnhdr *sbss_section; ! 76: static struct scnhdr *bss_section; ! 77: ! 78: struct headers { ! 79: struct filehdr fhdr; ! 80: struct aouthdr aout; ! 81: struct scnhdr section[10]; ! 82: }; ! 83: ! 84: /* Define name of label for entry point for the dumped executable. */ ! 85: ! 86: #ifndef DEFAULT_ENTRY_ADDRESS ! 87: #define DEFAULT_ENTRY_ADDRESS __start ! 88: #endif ! 89: ! 90: unexec (new_name, a_name, data_start, bss_start, entry_address) ! 91: char *new_name, *a_name; ! 92: unsigned data_start, bss_start, entry_address; ! 93: { ! 94: int new, old; ! 95: int pagesize, brk; ! 96: int newsyms, symrel; ! 97: int nread; ! 98: struct headers hdr; ! 99: int i; ! 100: int vaddr, scnptr; ! 101: #define BUFSIZE 8192 ! 102: char buffer[BUFSIZE]; ! 103: ! 104: old = open (a_name, O_RDONLY, 0); ! 105: if (old < 0) fatal_unexec ("opening %s", a_name); ! 106: ! 107: new = creat (new_name, 0666); ! 108: if (new < 0) fatal_unexec ("creating %s", new_name); ! 109: ! 110: hdr = *((struct headers *)TEXT_START); ! 111: #ifdef MIPS2 ! 112: if (hdr.fhdr.f_magic != MIPSELMAGIC ! 113: && hdr.fhdr.f_magic != MIPSEBMAGIC ! 114: && hdr.fhdr.f_magic != (MIPSELMAGIC | 1) ! 115: && hdr.fhdr.f_magic != (MIPSEBMAGIC | 1)) ! 116: { ! 117: fprintf (stderr, ! 118: "unexec: input file magic number is %x, not %x, %x, %x or %x.\n", ! 119: hdr.fhdr.f_magic, ! 120: MIPSELMAGIC, MIPSEBMAGIC, ! 121: MIPSELMAGIC | 1, MIPSEBMAGIC | 1); ! 122: exit (1); ! 123: } ! 124: #else /* not MIPS2 */ ! 125: if (hdr.fhdr.f_magic != MIPSELMAGIC ! 126: && hdr.fhdr.f_magic != MIPSEBMAGIC) ! 127: { ! 128: fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n", ! 129: hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC); ! 130: exit (1); ! 131: } ! 132: #endif /* not MIPS2 */ ! 133: if (hdr.fhdr.f_opthdr != sizeof (hdr.aout)) ! 134: { ! 135: fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n", ! 136: hdr.fhdr.f_opthdr, sizeof (hdr.aout)); ! 137: exit (1); ! 138: } ! 139: if (hdr.aout.magic != ZMAGIC) ! 140: { ! 141: fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n", ! 142: hdr.aout.magic, ZMAGIC); ! 143: exit (1); ! 144: } ! 145: ! 146: #define CHECK_SCNHDR(ptr, name, flags) \ ! 147: ptr = NULL; \ ! 148: for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \ ! 149: if (strcmp (hdr.section[i].s_name, name) == 0) { \ ! 150: if (hdr.section[i].s_flags != flags) { \ ! 151: fprintf (stderr, "unexec: %x flags where %x expected in %s section.\n", \ ! 152: hdr.section[i].s_flags, flags, name); \ ! 153: } \ ! 154: ptr = hdr.section + i; \ ! 155: } ! 156: ! 157: CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT); ! 158: CHECK_SCNHDR (init_section, _INIT, STYP_INIT); ! 159: CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA); ! 160: CHECK_SCNHDR (data_section, _DATA, STYP_DATA); ! 161: #ifdef _LIT8 ! 162: CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8); ! 163: CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4); ! 164: #endif /* _LIT8 */ ! 165: CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA); ! 166: CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS); ! 167: CHECK_SCNHDR (bss_section, _BSS, STYP_BSS); ! 168: #if 0 /* Apparently this error check goes off on irix 3.3, ! 169: but it doesn't indicate a real problem. */ ! 170: if (i != hdr.fhdr.f_nscns) ! 171: fprintf (stderr, "unexec: %d sections found instead of %d.\n", ! 172: i, hdr.fhdr.f_nscns); ! 173: #endif ! 174: ! 175: text_section->s_scnptr = 0; ! 176: ! 177: pagesize = getpagesize (); ! 178: brk = (sbrk (0) + pagesize - 1) & (-pagesize); ! 179: hdr.aout.dsize = brk - DATA_START; ! 180: hdr.aout.bsize = 0; ! 181: if (entry_address == 0) ! 182: { ! 183: extern DEFAULT_ENTRY_ADDRESS (); ! 184: hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS; ! 185: } ! 186: else ! 187: hdr.aout.entry = entry_address; ! 188: ! 189: hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize; ! 190: rdata_section->s_size = data_start - DATA_START; ! 191: ! 192: /* Adjust start and virtual addresses of rdata_section, too. */ ! 193: rdata_section->s_vaddr = DATA_START; ! 194: rdata_section->s_paddr = DATA_START; ! 195: rdata_section->s_scnptr = text_section->s_scnptr + hdr.aout.tsize; ! 196: ! 197: data_section->s_vaddr = data_start; ! 198: data_section->s_paddr = data_start; ! 199: data_section->s_size = brk - data_start; ! 200: data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size; ! 201: vaddr = data_section->s_vaddr + data_section->s_size; ! 202: scnptr = data_section->s_scnptr + data_section->s_size; ! 203: if (lit8_section != NULL) ! 204: { ! 205: lit8_section->s_vaddr = vaddr; ! 206: lit8_section->s_paddr = vaddr; ! 207: lit8_section->s_size = 0; ! 208: lit8_section->s_scnptr = scnptr; ! 209: } ! 210: if (lit4_section != NULL) ! 211: { ! 212: lit4_section->s_vaddr = vaddr; ! 213: lit4_section->s_paddr = vaddr; ! 214: lit4_section->s_size = 0; ! 215: lit4_section->s_scnptr = scnptr; ! 216: } ! 217: if (sdata_section != NULL) ! 218: { ! 219: sdata_section->s_vaddr = vaddr; ! 220: sdata_section->s_paddr = vaddr; ! 221: sdata_section->s_size = 0; ! 222: sdata_section->s_scnptr = scnptr; ! 223: } ! 224: if (sbss_section != NULL) ! 225: { ! 226: sbss_section->s_vaddr = vaddr; ! 227: sbss_section->s_paddr = vaddr; ! 228: sbss_section->s_size = 0; ! 229: sbss_section->s_scnptr = scnptr; ! 230: } ! 231: if (bss_section != NULL) ! 232: { ! 233: bss_section->s_vaddr = vaddr; ! 234: bss_section->s_paddr = vaddr; ! 235: bss_section->s_size = 0; ! 236: bss_section->s_scnptr = scnptr; ! 237: } ! 238: ! 239: WRITE (new, TEXT_START, hdr.aout.tsize, ! 240: "writing text section to %s", new_name); ! 241: WRITE (new, DATA_START, hdr.aout.dsize, ! 242: "writing text section to %s", new_name); ! 243: ! 244: SEEK (old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name); ! 245: errno = EEOF; ! 246: nread = read (old, buffer, BUFSIZE); ! 247: if (nread < sizeof (HDRR)) fatal_unexec ("reading symbols from %s", a_name); ! 248: #define symhdr ((pHDRR)buffer) ! 249: newsyms = hdr.aout.tsize + hdr.aout.dsize; ! 250: symrel = newsyms - hdr.fhdr.f_symptr; ! 251: hdr.fhdr.f_symptr = newsyms; ! 252: symhdr->cbLineOffset += symrel; ! 253: symhdr->cbDnOffset += symrel; ! 254: symhdr->cbPdOffset += symrel; ! 255: symhdr->cbSymOffset += symrel; ! 256: symhdr->cbOptOffset += symrel; ! 257: symhdr->cbAuxOffset += symrel; ! 258: symhdr->cbSsOffset += symrel; ! 259: symhdr->cbSsExtOffset += symrel; ! 260: symhdr->cbFdOffset += symrel; ! 261: symhdr->cbRfdOffset += symrel; ! 262: symhdr->cbExtOffset += symrel; ! 263: #undef symhdr ! 264: do ! 265: { ! 266: if (write (new, buffer, nread) != nread) ! 267: fatal_unexec ("writing symbols to %s", new_name); ! 268: nread = read (old, buffer, BUFSIZE); ! 269: if (nread < 0) fatal_unexec ("reading symbols from %s", a_name); ! 270: #undef BUFSIZE ! 271: } while (nread != 0); ! 272: ! 273: SEEK (new, 0, "seeking to start of header in %s", new_name); ! 274: WRITE (new, &hdr, sizeof (hdr), ! 275: "writing header of %s", new_name); ! 276: ! 277: close (old); ! 278: close (new); ! 279: mark_x (new_name); ! 280: } ! 281: ! 282: /* ! 283: * mark_x ! 284: * ! 285: * After succesfully building the new a.out, mark it executable ! 286: */ ! 287: ! 288: static int ! 289: mark_x (name) ! 290: char *name; ! 291: { ! 292: struct stat sbuf; ! 293: int um = umask (777); ! 294: umask (um); ! 295: if (stat (name, &sbuf) < 0) ! 296: fatal_unexec ("getting protection on %s", name); ! 297: sbuf.st_mode |= 0111 & ~um; ! 298: if (chmod (name, sbuf.st_mode) < 0) ! 299: fatal_unexec ("setting protection on %s", name); ! 300: } ! 301: ! 302: static void ! 303: fatal_unexec (s, va_alist) ! 304: va_dcl ! 305: { ! 306: va_list ap; ! 307: if (errno == EEOF) ! 308: fputs ("unexec: unexpected end of file, ", stderr); ! 309: else if (errno < sys_nerr) ! 310: fprintf (stderr, "unexec: %s, ", sys_errlist[errno]); ! 311: else ! 312: fprintf (stderr, "unexec: error code %d, ", errno); ! 313: va_start (ap); ! 314: _doprnt (s, ap, stderr); ! 315: fputs (".\n", stderr); ! 316: exit (1); ! 317: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.