|
|
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.