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