|
|
1.1 root 1: /* coff.c -- rutines for manipulating coff executable files. */
2:
3: #include <coff.h>
4: #include "tboot.h"
5:
6: /* Convert COFF to load table.
7: * Used to generate loading instructions for use by tboot main().
8: * Returns true on successful translation.
9: */
10:
11: int
12: coff2load(ip, table, data_seg)
13: struct inode *ip; /* input: File to read. */
14: struct load_segment table[]; /* output: How to read it. */
15: uint16 *data_seg; /* output: Where to point es. */
16: {
17: FILHDR fh; /* COFF file header. */
18: AOUTHDR oh; /* COFF optional header. */
19: SCNHDR sh; /* COFF section header. */
20:
21: int i, j; /* Loop counters. */
22: fsize_t section_seek; /* Seek counter for section headers. */
23:
24: /* Read the file header. */
25: iread(ip, &fh, (fsize_t) 0, (uint16) sizeof (fh));
26:
27:
28: /* Check for the 5000 possible failures... */
29: /* Is this really a i386 COFF file? */
30: if (I386MAGIC != fh.f_magic) {
31: puts("COFF COFF! File header bad magic.\r\n");
32: puts("This is not an i386 COFF file.\r\n");
33: return 0;
34: }
35:
36: /* Is this an executable COFF file? */
37: if (!(fh.f_flags & F_EXEC)) {
38: puts("Non-executable COFF file.\r\n");
39: return 0;
40: }
41:
42: /* Does it have the information we need to execute it? */
43: if (sizeof(oh) != fh.f_opthdr) {
44: puts("COFF optional header is wrong size.\r\n");
45: return 0;
46: }
47:
48: /*
49: * Pointless witticism:
50: * (Actually, this helped us find a bug in ld.)
51: */
52: if (fh.f_timdat < 0x1000) {
53: puts(
54: "Wow! An executable from the first few thousand seconds of time!\r\n"
55: );
56: }
57:
58: /* ASSERTION: We know this to be an executable i386 COFF file. */
59:
60: /* Read the optional header. */
61: /* This is the one with the data we really want. */
62: iread(ip, &oh, (fsize_t) sizeof(fh), (uint16) sizeof (oh));
63:
64: /* Validate the optional header. */
65:
66: if (NORMAL_MAGIC != oh.magic) {
67: puts("COFF COFF! Optional header bad magic.\r\n");
68: puts("This isn't a normal executable file.\r\n");
69: return 0;
70: }
71:
72: /* Read through the section headers,
73: * looking for text and data segments, and
74: * turning them into little toads. Or something like that.
75: */
76:
77: #define TEXT table[0]
78: #define DATA table[1]
79:
80: /* Loop until we have both the sections we want, at most twice. */
81: for (TEXT.valid = 0, DATA.valid = 0, j = 0;
82: !(TEXT.valid && DATA.valid) && j < 2;
83: ++j) {
84:
85: for (section_seek = sizeof(FILHDR)+sizeof(AOUTHDR), i = 0;
86: i < fh.f_nscns; /* i < number of sections */
87: section_seek += SCNHSZ, ++i) {
88:
89: iread(ip, &sh, section_seek, SCNHSZ);
90: switch ((int) sh.s_flags) {
91: case STYP_TEXT:
92: TEXT.valid = 1;
93: TEXT.message = "\r\nLoading COHERENT.\r\n";
94: TEXT.load_toseg = sys_base;
95: TEXT.load_tooffset = 0;
96: TEXT.load_offset = sh.s_scnptr;
97: TEXT.load_length = sh.s_size;
98: break;
99:
100: case STYP_DATA:
101: /* The text header must already have been read to
102: * put meaningful numbers here.
103: */
104: if (TEXT.valid) {
105: DATA.valid = 1;
106: DATA.message = "\r\nLoading COHERENT data.\r\n";
107: /* Round up to next paragraph beyond end
108: * of text.
109: */
110: DATA.load_toseg = (sys_base +
111: (TEXT.load_length + 15) / 16);
112: DATA.load_tooffset = 0;
113: DATA.load_offset = sh.s_scnptr;
114: DATA.load_length = sh.s_size;
115: *data_seg = (sys_base +
116: (TEXT.load_length + 15) / 16);
117: }
118: break;
119: case STYP_BSS:
120: break;
121: default:
122: puts("Warning. Unrecognized COFF section.\r\n");
123: break;
124: } /* switch (sh.s_flags) */
125:
126: } /* for walk through headers */
127:
128: } /* while haven't got both, at most twice */
129:
130: if (!TEXT.valid) {
131: puts("Failed to find COFF text section.\r\n");
132: return 0;
133: }
134:
135: if (!DATA.valid) {
136: puts("Failed to find COFF data section.\r\n");
137: return 0;
138: }
139:
140: table[2].valid = 0; /* Terminate the list. */
141:
142: return 1;
143: }
144:
145:
146: /*
147: * Symbol name.
148: */
149: static char *
150: symName(sym, str_tab, work)
151: SYMENT *sym;
152: char *str_tab, *work;
153: {
154: if (!sym->_n._n_n._n_zeroes)
155: return (str_tab + sym->_n._n_n._n_offset - 4);
156:
157: memcpy(work, sym->_n._n_name, SYMNMLEN);
158: work[SYMNMLEN] = '\0';
159: return (work);
160: }
161:
162: /*
163: * Look up the value of a single data symbol in a coff file,
164: * relative to the start of the data segment.
165: *
166: * We use the symbol "sdata" to find the start of the data segment--
167: * this works for 386 COHERENT kernels but will not work in general.
168: * It should really fetch the address of the start of the data segment
169: * from the data section header.
170: */
171: uint32
172: wrap_coffnlist(fn, symbol)
173: char *fn; /* file name */
174: char *symbol; /* symbol to look up */
175: {
176: /* Something goes wrong with looking up symbol if
177: * nlp is automatic rather than static, even with a huge stack.
178: */
179: static SYMENT nlp[2];
180: uint32 retval;
181:
182: /* Start of the data segment. */
183: strcpy(nlp[0]._n._n_name, "sdata");
184: nlp[0].n_type = -1;
185:
186: nlp[1]._n._n_n._n_zeroes = 0;
187: nlp[1]._n._n_n._n_offset = sizeof(int32);
188: nlp[1].n_type = -1;
189:
190: coffnlist(fn, nlp, symbol, 2);
191:
192: retval = ((uint32)nlp[1].n_value) - ((uint32)nlp[0].n_value);
193:
194: if (verbose_flag)
195: printf("sdata=%lx %s=%lx retval=%lx\r\n",
196: nlp[0].n_value, symbol, nlp[1].n_value, retval);
197:
198: if (0L == nlp[1].n_value) {
199: return(0L);
200: } else {
201: return retval;
202: }
203: puts("Unreachable code in wrap_coffnlist().\r\n");
204: return(0L);
205: } /* wrap_coffnlist() */
206:
207: int
208: coffnlist(fn, nlp, names, count)
209: char *fn; /* file name */
210: SYMENT *nlp; /* names to look up */
211: char *names; /* long names */
212: int count; /* size of passed table */
213: {
214: FILHDR head;
215: int fp;
216: /* str_tab should be malloc'd. Blows up if file's sym table too big. */
217: #define STR_TAB_SIZE 5000
218: char str_tab[STR_TAB_SIZE];
219: long str_length;
220: int aux, i;
221:
222: if (-1 == (fp = open(fn, 0))) {
223: puts("coffnlist open failed\r\n");
224: return 0;
225: }
226:
227: if (FILHSZ != read(fp, &head, FILHSZ) || head.f_magic != I386MAGIC) {
228: close (fp);
229: printf("coffnlist header read (%d) failed\r\n", FILHSZ);
230: return 0;
231: }
232:
233: lseek(fp, head.f_symptr + (SYMESZ * head.f_nsyms), 0);
234:
235: if (sizeof(str_length) != read(fp, &str_length, sizeof(str_length)))
236: str_length = 0;
237: if (str_length) {
238: uint16 len;
239:
240: len = str_length -= 4;
241: if (len != str_length || len > STR_TAB_SIZE) {
242: close (fp);
243: printf("coffnlist str table overflow, len = %d\r\n",
244: len);
245: return 0;
246: }
247:
248: if (len != read(fp, str_tab, len)) {
249: close (fp);
250: puts("coffnlist str read failed\r\n");
251: return 0;
252: }
253: }
254:
255: lseek(fp, head.f_symptr, 0);
256: for (i = aux = 0; i < head.f_nsyms; i++) {
257: SYMENT sym; /* symbol read in */
258: int taux, j;
259:
260: if (SYMESZ != read(fp, &sym, SYMESZ)) {
261: close (fp);
262: puts("coffnlist sym read failed\r\n");
263: return 0;
264: }
265:
266: if (aux) {
267: aux--;
268: continue;
269: }
270: aux = sym.n_numaux;
271: for (j = taux = 0; j < count; j++) {
272: static char n1[SYMNMLEN + 1], n2[SYMNMLEN + 1];
273: register SYMENT *np;
274:
275: if (taux) {
276: taux--;
277: continue;
278: }
279: np = nlp + j;
280: taux = np->n_numaux;
281: if (np->n_type != -1 ||
282: strcmp(symName(np, names, n1),
283: symName(&sym, str_tab, n2)))
284: continue;
285: np->n_value = sym.n_value;
286: np->n_scnum = sym.n_scnum;
287: np->n_type = sym.n_type;
288: np->n_sclass = sym.n_sclass;
289: break;
290: }
291: }
292: close (fp);
293: return 1;
294: }
295:
296: #ifdef TEST
297: #include <stdio.h>
298:
299: main()
300: {
301: int i;
302: static SYMENT sym[3];
303: static char ptr[]="rootdev";
304:
305: strcpy(sym[0]._n._n_name, "NCLIST");
306: sym[0].n_type = -1;
307:
308: strcpy(sym[1]._n._n_name, "sdata");
309: sym[1].n_type = -1;
310:
311: sym[2]._n._n_n._n_zeroes = 0;
312: sym[2]._n._n_n._n_offset = sizeof(int32);
313: sym[2].n_type = -1;
314:
315: coffnlist("/at386", sym, ptr, 3);
316:
317: for (i = 0; i < 3; ++i) {
318: printf("sym[%d]._n._n_name: %s\n", i, sym[i]._n._n_name);
319: printf("sym[%d].n_value: %lx\n\n", i, sym[i].n_value);
320: }
321:
322: printf("\nrootdev as offset: %lx\n",
323: wrap_coffnlist("/at386", "rootdev"));
324: }
325: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.