|
|
1.1 ! root 1: /* ! 2: * Object file services. ! 3: * This section is similar to that in nm and size. ! 4: */ ! 5: ! 6: #include <stdio.h> ! 7: #include <canon.h> ! 8: ! 9: #if COHERENT ! 10: #include <n.out.h> ! 11: #include <signal.h> ! 12: #endif ! 13: #if MSDOS ! 14: #include <nout.h> ! 15: #define DOEXE 1 ! 16: #endif ! 17: #if GEMDOS ! 18: #include <nout.h> ! 19: #define DOPRG 1 ! 20: #endif ! 21: ! 22: char *argv0; /* Command name */ ! 23: char *fn; /* File name */ ! 24: FILE *ifp; /* Input File Pointer */ ! 25: FILE *ofp; /* Output File Pointer */ ! 26: struct ldheader ldh; /* The l.out.h header */ ! 27: long loadsize; /* Amount of input to copy to output */ ! 28: ! 29: /* ! 30: * Read in the l.out header. ! 31: */ ! 32: gethdr() ! 33: { ! 34: register int i; ! 35: fread((char *)&ldh, 1, sizeof(ldh), ifp); ! 36: canshort(ldh.l_magic); ! 37: canshort(ldh.l_flag); ! 38: canshort(ldh.l_machine); ! 39: if (ldh.l_magic != L_MAGIC) ! 40: return 1; ! 41: if ((ldh.l_flag&LF_32) == 0) { ! 42: canshort(ldh.l_tbase); ! 43: ldh.l_entry = ldh.l_tbase; ! 44: ldh.l_tbase = sizeof(ldh) - 2*sizeof(short); ! 45: } else { ! 46: canshort(ldh.l_tbase); ! 47: canlong(ldh.l_entry); ! 48: } ! 49: loadsize = 0; ! 50: for (i=0; i<NLSEG; i++) { ! 51: canlong(ldh.l_ssize[i]); ! 52: if (i < L_DEBUG && i != L_BSSI && i != L_BSSD) ! 53: loadsize += ldh.l_ssize[i]; ! 54: } ! 55: return (0); ! 56: } ! 57: ! 58: /* ! 59: * Read the exe header. ! 60: */ ! 61: #ifndef DOEXE ! 62: getexe() { return 1; } ! 63: #else ! 64: #include "exe.h" ! 65: ! 66: ! 67: execani(ip) /* convert from MSDOS exe header byte order to host */ ! 68: register short *ip; ! 69: { ! 70: /* First convert to standard pdp-11 byte order */ ! 71: /* Notice, nothing to do to accomplish this */ ! 72: ! 73: /* Now convert from pdp-11 byte order to host */ ! 74: ! 75: canshort(*ip); ! 76: } ! 77: ! 78: getexe() ! 79: { ! 80: long daddr; ! 81: exehdr_t exehdr; ! 82: ! 83: fseek(ifp, 0L, 0); ! 84: fread((char *)&exehdr, 1, sizeof(exehdr), ifp); ! 85: execani(&exehdr.x_magic); ! 86: if (exehdr.x_magic != EXEMAGIC) ! 87: return (1); ! 88: execani(&exehdr.x_sectors); ! 89: execani(&exehdr.x_bytes); ! 90: daddr = (long) exehdr.x_sectors * 512; ! 91: if ( exehdr.x_bytes != 0 ) ! 92: daddr += exehdr.x_bytes - 512; ! 93: fseek(ifp, daddr, 0); ! 94: if (gethdr() != 0) ! 95: return 1; ! 96: loadsize = daddr; ! 97: return 0; ! 98: } ! 99: #endif ! 100: ! 101: /* ! 102: * Read a gemdos .prg header. ! 103: */ ! 104: #ifndef DOPRG ! 105: getprg() { return 1; } ! 106: #else ! 107: #include "gemout.h" ! 108: /* convert 68000 byte order to pdp11 byte order and vice versa */ ! 109: #if PDP11 ! 110: gemcani(ip) register unsigned char *ip; ! 111: { ! 112: register t; ! 113: t = ip[0]; ip[0] = ip[1]; ip[1] = t; ! 114: } ! 115: gemcanl(lp) register unsigned char *lp; ! 116: { ! 117: register t; ! 118: t = lp[0]; lp[0] = lp[1]; lp[1] = t; ! 119: t = lp[2]; lp[2] = lp[3]; lp[3] = t; ! 120: } ! 121: #endif ! 122: #if M68000 ! 123: #define gemcani(i) /* Nil */ ! 124: #define gemcanl(l) /* Nil */ ! 125: #endif ! 126: ! 127: getprg() ! 128: { ! 129: struct gemohdr ghd; ! 130: register long daddr; ! 131: register int c; ! 132: fseek(ifp, 0L, 0); ! 133: fread((char *)&ghd, 1, sizeof(ghd), ifp); ! 134: gemcani(&ghd.g_magic); ! 135: if (ghd.g_magic != GEMOMAGIC) ! 136: return 1; ! 137: gemcanl(&ghd.g_ssize[0]); ! 138: gemcanl(&ghd.g_ssize[1]); ! 139: gemcanl(&ghd.g_ssize[2]); ! 140: gemcanl(&ghd.g_ssize[3]); ! 141: daddr = sizeof(ghd) + ghd.g_ssize[0] + ghd.g_ssize[1] + ghd.g_ssize[3]; ! 142: fseek(ifp, daddr, 0); ! 143: if (getw(ifp) | getw(ifp)) { ! 144: while (c = getc(ifp)) ! 145: if (c == EOF) ! 146: return 1; ! 147: } ! 148: daddr = ftell(ifp); ! 149: if (gethdr() != 0) ! 150: return 1; ! 151: loadsize = daddr; ! 152: return 0; ! 153: } ! 154: #endif ! 155: ! 156: /* ! 157: * Strip specific code. ! 158: * Strip the debug table, the symbol ! 159: * table and the relocation information from a ! 160: * object file. ! 161: * Optionally keep any combination of the three. ! 162: */ ! 163: ! 164: char *tmp; ! 165: char werror[] = "write error"; ! 166: char rerror[] = "cannot reopen"; ! 167: char xerror[] = "unexpected end of file"; ! 168: char oerror[] = "not an object file"; ! 169: char usemsg[] = "Usage: %s [-drs] file [ ... ]\n"; ! 170: ! 171: int dkeep; ! 172: int rkeep; ! 173: int skeep; ! 174: ! 175: int notcoh = 1; /* flag indicative of what object type the file is */ ! 176: int notexe = 1; ! 177: int notprg = 1; ! 178: ! 179: struct ldheader olh; /* output file l.out.h header */ ! 180: ! 181: int cleanup(); ! 182: ! 183: main(argc, argv) ! 184: char *argv[]; ! 185: { ! 186: register estat, i; ! 187: register char *cp; ! 188: register c; ! 189: extern char *tempnam(); ! 190: ! 191: argv0 = argv[0]; ! 192: if (argc < 2) ! 193: usage(); ! 194: tmp = tempnam(NULL, "s"); ! 195: #if COHERENT ! 196: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 197: signal(SIGINT, cleanup); ! 198: #endif ! 199: estat = 0; ! 200: for (i=1; i<argc; i++) { ! 201: cp = argv[i]; ! 202: if (cp[0] == '-') { ! 203: while ((c = *++cp) != 0) ! 204: if (c == 'd') ++dkeep; ! 205: else if (c == 'r') ++rkeep; ! 206: else if (c == 's') ++skeep; ! 207: else usage(); ! 208: continue; ! 209: } ! 210: fn = argv[i]; ! 211: estat |= strip(); ! 212: if (ifp != NULL) { ! 213: fclose(ifp); ! 214: ifp = NULL; ! 215: } ! 216: if (ofp != NULL) { ! 217: fclose(ofp); ! 218: ofp = NULL; ! 219: } ! 220: } ! 221: cleanup(estat); ! 222: } ! 223: ! 224: /* ! 225: * Do all the work. ! 226: * The external variables 'ifp' and 'ofp' ! 227: * will be closed by the mainline. This makes the ! 228: * many error conditions a little easier to ! 229: * deal with. ! 230: */ ! 231: strip() ! 232: { ! 233: int i; ! 234: register long nsize; ! 235: ! 236: if ((ifp = fopen(fn, "rb")) == NULL) { ! 237: diag("cannot open", fn); ! 238: return(1); ! 239: } ! 240: if ((ofp = fopen(tmp, "wb")) == NULL) { ! 241: diag("cannot create", tmp); ! 242: return(1); ! 243: } ! 244: if ( (notcoh=gethdr()) != 0 ! 245: && (notexe=getexe()) != 0 ! 246: && (notprg=getprg()) != 0) { ! 247: diag("not an object file", fn); ! 248: return(1); ! 249: } ! 250: olh = ldh; ! 251: if ( ! dkeep) { ! 252: olh.l_ssize[L_DEBUG] = 0; ! 253: olh.l_flag &= ~LF_DEBUG; ! 254: } ! 255: if ( ! rkeep) { ! 256: olh.l_flag |= LF_NRB; ! 257: olh.l_ssize[L_REL] = 0; ! 258: } ! 259: if ( ! skeep) ! 260: olh.l_ssize[L_SYM] = 0; ! 261: if (ldh.l_flag == olh.l_flag ! 262: && ldh.l_ssize[L_DEBUG] == olh.l_ssize[L_DEBUG] ! 263: && ldh.l_ssize[L_SYM] == olh.l_ssize[L_SYM] ! 264: && ldh.l_ssize[L_REL] == olh.l_ssize[L_REL]) ! 265: return(0); ! 266: ! 267: if (writehead() != 0 /* header of output file */ ! 268: || copy(loadsize) != 0 /* all loadable segments */ ! 269: || writelout() != 0) /* l.out.h header in exe and prg */ ! 270: return(1); ! 271: ! 272: for (i = L_DEBUG; i < NLSEG; i += 1) { ! 273: nsize = ldh.l_ssize[i]; ! 274: if (olh.l_ssize[i] == nsize) ! 275: copy(nsize); ! 276: else ! 277: fseek(ifp, nsize, 1); ! 278: } ! 279: fflush(ofp); ! 280: if (ferror(ofp)) { ! 281: diag(werror, tmp); ! 282: return (1); ! 283: } ! 284: if (ferror(ifp)) { ! 285: diag("read error", fn); ! 286: return 1; ! 287: } else if (feof(ifp)) { ! 288: diag(xerror, fn); ! 289: return 1; ! 290: } ! 291: fclose(ifp); ! 292: ifp = NULL; ! 293: loadsize = ftell(ofp); ! 294: fclose(ofp); ! 295: ofp = NULL; ! 296: if ((ifp = fopen(tmp, "rb")) == NULL) { ! 297: diag(rerror, tmp); ! 298: return (1); ! 299: } ! 300: if ((ofp = fopen(fn, "wb")) == NULL) { ! 301: diag(rerror, fn); ! 302: return (1); ! 303: } ! 304: copy(loadsize); ! 305: fflush(ofp); ! 306: if (ferror(ofp)) { ! 307: diag(werror, fn); ! 308: fprintf(stderr, "%s: file saved in %s\n", argv0, tmp); ! 309: exit(1); ! 310: } ! 311: return (0); ! 312: } ! 313: ! 314: /* ! 315: * Convert the l.out header structure ! 316: * in the buffer 'lh' to and from standard ! 317: * ordering. ! 318: */ ! 319: canlh(ldhp) ! 320: register struct ldheader *ldhp; ! 321: { ! 322: register i; ! 323: ! 324: canshort(ldhp->l_magic); ! 325: canshort(ldhp->l_flag); ! 326: canshort(ldhp->l_machine); ! 327: canshort(ldhp->l_tbase); ! 328: for (i=0; i<NLSEG; ++i) ! 329: canlong(ldhp->l_ssize[i]); ! 330: canlong(ldhp->l_entry); ! 331: } ! 332: ! 333: /* ! 334: * Writes the header at the beginning of the output file ! 335: * References flags: notcoh, notexe, and notprg. ! 336: */ ! 337: writehead() ! 338: { ! 339: if ( !notcoh ) { ! 340: register int size; ! 341: if ((size = olh.l_tbase) < sizeof olh) ! 342: olh.l_tbase = olh.l_entry; ! 343: canlh(&olh); ! 344: if (fwrite(&olh, size, 1, ofp) != 1) { ! 345: diag(werror, tmp); ! 346: return (1); ! 347: } ! 348: canlh(&olh); ! 349: if (size < sizeof olh) { ! 350: olh.l_entry = olh.l_tbase; ! 351: olh.l_tbase = size; ! 352: fseek(ifp, (long)-2*sizeof(short), 1); ! 353: } ! 354: } else ! 355: fseek(ifp, 0l, 0); ! 356: return(0); ! 357: } ! 358: ! 359: /* ! 360: * Copy nbytes from ifp to ofp. ! 361: */ ! 362: copy(nbytes) long nbytes; ! 363: { ! 364: register int n; ! 365: static char buff[16*1024]; ! 366: ! 367: while (nbytes > 0) { ! 368: n = nbytes > sizeof buff ? sizeof buff : nbytes; ! 369: if (fread(buff, 1, n, ifp) != n) ! 370: return 1; ! 371: if (fwrite(buff, 1, n, ofp) != n) ! 372: return 1; ! 373: nbytes -= n; ! 374: } ! 375: return 0; ! 376: } ! 377: ! 378: /* ! 379: * Write the l.out.h header in the middle of the file for ! 380: * MS-DOS .exe and GEMDOS .prg ! 381: * Leave ifp at the beginning of L_DEBUG. ! 382: */ ! 383: writelout() ! 384: { ! 385: if ( !notcoh ) ! 386: return(0); ! 387: ! 388: canlh(&olh); ! 389: if (fwrite(&olh, sizeof(olh), 1, ofp) != 1) { ! 390: diag(werror, tmp); ! 391: return(1); ! 392: } ! 393: canlh(&olh); ! 394: fseek(ifp, (long)sizeof(ldh), 1); ! 395: return(0); ! 396: } ! 397: ! 398: ! 399: /* ! 400: * Print diagnostics. ! 401: */ ! 402: diag(s, fn) ! 403: char *s; ! 404: char *fn; ! 405: { ! 406: fprintf(stderr, "%s: ", argv0); ! 407: if (fn != NULL) ! 408: fprintf(stderr, "%s: ", fn); ! 409: fprintf(stderr, "%s\n", s); ! 410: } ! 411: ! 412: /* ! 413: * Cleanup tempfile and exit. ! 414: * The status is the exit status. ! 415: * When a signal occurs, it is the signal ! 416: * number which is non-zero so ! 417: * this will be an acceptable exit status. ! 418: */ ! 419: cleanup(s) ! 420: { ! 421: unlink(tmp); ! 422: exit(s); ! 423: } ! 424: ! 425: /* ! 426: * Print usage message. ! 427: */ ! 428: usage() ! 429: { ! 430: fprintf(stderr, usemsg, argv0); ! 431: exit(1); ! 432: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.