coff32read.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
coff32read.c (10632B)
---
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <scc/mach.h>
9 #include <scc/coff32.h>
10
11 #include "../libmach.h"
12 #include "fun.h"
13
14 static void
15 unpack_hdr(int order, unsigned char *buf, FILHDR *hdr)
16 {
17 int n;
18
19 n = unpack(order,
20 buf,
21 "sslllss",
22 &hdr->f_magic,
23 &hdr->f_nscns,
24 &hdr->f_timdat,
25 &hdr->f_symptr,
26 &hdr->f_nsyms,
27 &hdr->f_opthdr,
28 &hdr->f_flags);
29 assert(n == FILHSZ);
30 }
31
32 static void
33 unpack_line(int order, unsigned char *buf, LINENO *lp)
34 {
35 int n;
36
37 n = unpack(order,
38 buf,
39 "ls",
40 &lp->l_addr.l_symndx,
41 &lp->l_lnno);
42 assert(n == LINESZ);
43 }
44
45 static void
46 unpack_scn(int order, unsigned char *buf, SCNHDR *scn)
47 {
48 int n;
49 char *s;
50
51 n = unpack(order,
52 buf,
53 "'8llllllssl",
54 scn->s_name,
55 &scn->s_paddr,
56 &scn->s_vaddr,
57 &scn->s_size,
58 &scn->s_scnptr,
59 &scn->s_relptr,
60 &scn->s_lnnoptr,
61 &scn->s_nrelloc,
62 &scn->s_nlnno,
63 &scn->s_flags);
64 assert(n == SCNHSZ);
65
66 s = scn->s_name;
67 if (!s[0] && !s[1] && !s[2] && !s[3])
68 unpack(order, buf, "ll", &scn->s_zeroes, &scn->s_offset);
69 }
70
71 static void
72 unpack_ent(int order, unsigned char *buf, SYMENT *ent)
73 {
74 int n;
75 char *s;
76
77 n = unpack(order,
78 buf,
79 "'8lsscc",
80 ent->n_name,
81 &ent->n_value,
82 &ent->n_scnum,
83 &ent->n_type,
84 &ent->n_sclass,
85 &ent->n_numaux);
86 assert(n == SYMESZ);
87
88 s = ent->n_name;
89 if (!s[0] && !s[1] && !s[2] && !s[3])
90 unpack(order, buf, "ll", &ent->n_zeroes, &ent->n_offset);
91 }
92
93 static void
94 unpack_reloc(int order, unsigned char *buf, RELOC *rel)
95 {
96 int n;
97
98 n = unpack(order,
99 buf,
100 "lls",
101 &rel->r_vaddr,
102 &rel->r_symndx,
103 &rel->r_type);
104 assert(n == RELSZ);
105 }
106
107 static void
108 unpack_aout(int order, unsigned char *buf, AOUTHDR *aout)
109 {
110 int n;
111
112 n = unpack(order,
113 buf,
114 "ssllllll",
115 &aout->magic,
116 &aout->vstamp,
117 &aout->tsize,
118 &aout->dsize,
119 &aout->bsize,
120 &aout->entry,
121 &aout->text_start,
122 &aout->data_start);
123 assert(n == AOUTSZ);
124 }
125
126 static void
127 unpack_aux_file(int order, unsigned char *buf, AUXENT *aux)
128 {
129 int n;
130 char *s;
131
132 n = unpack(order,
133 buf,
134 "'18",
135 aux->x_fname);
136 assert(n == AUXESZ);
137
138 s = aux->x_fname;
139 if (!s[0] && !s[1] && !s[2] && !s[3])
140 unpack(order, buf, "ll", &aux->x_zeroes, &aux->x_offset);
141 }
142
143 static void
144 unpack_aux_scn(int order, unsigned char *buf, AUXENT *aux)
145 {
146 char dummy1, dummy2, dummy3;
147 int n;
148
149 n = unpack(order,
150 buf,
151 "lsslscccc",
152 &aux->x_scnlen,
153 &aux->x_nreloc,
154 &aux->x_nlinno,
155 &aux->x_checksum,
156 &aux->x_associated,
157 &aux->x_comdat,
158 &dummy1,
159 &dummy2,
160 &dummy3);
161 assert(n == AUXESZ);
162 }
163
164 static void
165 unpack_aux_fun(int order, unsigned char *buf, AUXENT *aux)
166 {
167 int n;
168
169 n = unpack(order,
170 buf,
171 "lllls",
172 &aux->x_tagndx,
173 &aux->x_fsize,
174 &aux->x_lnnoptr,
175 &aux->x_endndx,
176 &aux->x_tvndx);
177 assert(n == AUXESZ);
178 }
179
180 static void
181 unpack_aux_ary(int order, unsigned char *buf, AUXENT *aux)
182 {
183 int n;
184
185 n = unpack(order,
186 buf,
187 "lssssss",
188 &aux->x_tagndx,
189 &aux->x_lnno,
190 &aux->x_size,
191 &aux->x_dimen[0],
192 &aux->x_dimen[1],
193 &aux->x_dimen[2],
194 &aux->x_dimen[3],
195 &aux->x_tvndx);
196 assert(n == AUXESZ);
197 }
198
199 static void
200 unpack_aux_sym(int order, unsigned char *buf, AUXENT *aux)
201 {
202 int n;
203
204 n = unpack(order,
205 buf,
206 "lsslls",
207 &aux->x_tagndx,
208 &aux->x_lnno,
209 &aux->x_size,
210 &aux->x_lnnoptr,
211 &aux->x_endndx,
212 &aux->x_tvndx);
213 assert(n == AUXESZ);
214 }
215
216 static int
217 readhdr(Obj *obj, FILE *fp)
218 {
219 FILHDR *hdr;
220 struct coff32 *coff;
221 unsigned char buf[FILHSZ];
222
223 coff = obj->data;
224 hdr = &coff->hdr;
225
226 if (fread(buf, FILHSZ, 1, fp) != 1)
227 return 0;
228 unpack_hdr(ORDER(obj->type), buf, hdr);
229
230 if (hdr->f_nsyms < 0 || hdr->f_nscns < 0)
231 return 0;
232
233 return 1;
234 }
235
236 static int
237 readstr(Obj *obj, FILE *fp)
238 {
239 FILHDR *hdr;
240 struct coff32 *coff;
241 long siz;
242 char *str;
243 unsigned char buf[10];
244
245 coff = obj->data;
246 hdr = &coff->hdr;
247
248 coff->strsiz = 0;
249 coff->strtbl = NULL;
250
251 if (hdr->f_nsyms == 0)
252 return 1;
253
254 if (fread(buf, 4, 1, fp) != 1)
255 return 0;
256 unpack(ORDER(obj->type), buf, "l", &siz);
257 if (siz < 4 || siz > SIZE_MAX)
258 return 0;
259 if (siz == 4)
260 return 1;
261
262 if ((str = malloc(siz)) == NULL)
263 return 0;
264 coff->strtbl = str;
265 coff->strsiz = siz;
266
267 return fread(str+4, siz-4, 1, fp) == 1;
268 }
269
270 static int
271 readreloc(Obj *obj, FILE *fp)
272 {
273 int i;
274 long j;
275 RELOC **rels, *rp;
276 SCNHDR *scn;
277 FILHDR *hdr;
278 struct coff32 *coff;
279 unsigned char buf[RELSZ];
280
281 coff = obj->data;
282 hdr = &coff->hdr;
283
284 if (hdr->f_nscns == 0)
285 return 1;
286
287 rels = calloc(hdr->f_nscns, sizeof(*rels));
288 if (!rels)
289 return 0;
290 coff->rels = rels;
291
292 for (i = 0; i < hdr->f_nscns; i++) {
293 scn = &coff->scns[i];
294 if (scn->s_nrelloc == 0)
295 continue;
296
297 if (!objpos(obj, fp, scn->s_relptr))
298 return 0;
299
300 rp = calloc(scn->s_nrelloc, sizeof(RELOC));
301 if (!rp)
302 return 0;
303 rels[i] = rp;
304
305 for (j = 0; j < scn->s_nrelloc; j++) {
306 if (fread(buf, RELSZ, 1, fp) != 1)
307 return 0;
308 unpack_reloc(ORDER(obj->type), buf, &rp[i]);
309 if (rp[i].r_symndx >= hdr->f_nsyms)
310 return 0;
311 }
312 }
313
314 return 1;
315 }
316
317 static int
318 readauxs(Obj *obj, FILE *fp, SYMENT *ent, long pos)
319 {
320 int i, n, typ, d1;
321 Entry *ep;
322 FILHDR *hdr;
323 struct coff32 *coff;
324 unsigned char buf[AUXESZ];
325
326 if ((n = ent->n_numaux) == 0)
327 return 1;
328 if (fread(buf, sizeof(buf), 1, fp) != 1)
329 return 0;
330
331 coff = obj->data;
332 ep = &coff->ents[pos+1];
333 typ = ent->n_type & 15;
334 d1 = (ent->n_type >> 4) & 15;
335
336 switch (ent->n_sclass) {
337 case C_FILE:
338 ep->type = SYM_AUX_FILE;
339 unpack_aux_file(ORDER(obj->type), buf, &ep->u.aux);
340 break;
341 case C_STAT:
342 if (d1 == DT_NON && typ == T_NULL) {
343 ep->type = SYM_AUX_SCN;
344 unpack_aux_scn(ORDER(obj->type), buf, &ep->u.aux);
345 break;
346 }
347 default:
348 switch (d1) {
349 case DT_FCN:
350 ep->type = SYM_AUX_FUN;
351 unpack_aux_fun(ORDER(obj->type), buf, &ep->u.aux);
352 break;
353 case DT_ARY:
354 ep->type = SYM_AUX_ARY;
355 unpack_aux_ary(ORDER(obj->type), buf, &ep->u.aux);
356 break;
357 default:
358 ep->type = SYM_AUX_SYM;
359 unpack_aux_sym(ORDER(obj->type), buf, &ep->u.aux);
360 }
361 }
362
363 for (++ep; --n > 0; ++ep) {
364 ep->type = SYM_AUX_UNK;
365 if (fread(ep->u.buf, AUXESZ, 1, fp) != 1)
366 return 0;
367 }
368
369 return 1;
370 }
371
372 static int
373 readents(Obj *obj, FILE *fp)
374 {
375 int n;
376 long i;
377 Entry *ep;
378 FILHDR *hdr;
379 struct coff32 *coff;
380 unsigned char buf[SYMESZ];
381
382 coff = obj->data;
383 hdr = &coff->hdr;
384
385 if (hdr->f_nsyms == 0)
386 return 1;
387
388 ep = calloc(hdr->f_nsyms, sizeof(*ep));
389 if (!ep)
390 return 0;
391 coff->ents = ep;
392
393 if (!objpos(obj, fp, hdr->f_symptr))
394 return 0;
395
396 for (i = 0; i < hdr->f_nsyms; i++) {
397 SYMENT *ent;
398
399 if (fread(buf, SYMESZ, 1, fp) != 1)
400 return 0;
401
402 ep = &coff->ents[i];
403 ep->type = SYM_ENT;
404 ent = &ep->u.sym;
405 unpack_ent(ORDER(obj->type), buf, ent);
406 if (ent->n_scnum > hdr->f_nscns)
407 return 0;
408
409 if (!readauxs(obj, fp, ent, i))
410 return 0;
411
412 i += ent->n_numaux;
413 }
414
415 return 1;
416 }
417
418 static int
419 readscns(Obj *obj, FILE *fp)
420 {
421 FILHDR *hdr;
422 struct coff32 *coff;
423 SCNHDR *scn;
424 long i;
425 unsigned char buf[SCNHSZ];
426
427 coff = obj->data;
428 hdr = &coff->hdr;
429
430 if (hdr->f_nscns == 0)
431 return 1;
432
433 scn = calloc(hdr->f_nscns, sizeof(*scn));
434 if (!scn)
435 return 0;
436 coff->scns = scn;
437
438 for (i = 0; i < hdr->f_nscns; i++) {
439 if (fread(buf, SCNHSZ, 1, fp) < 0)
440 return 0;
441 unpack_scn(ORDER(obj->type), buf, &scn[i]);
442 }
443
444 return 1;
445 }
446
447 static int
448 readlines(Obj *obj, FILE *fp)
449 {
450 int i,j;
451 LINENO **lines, *lp, *p;
452 FILHDR *hdr;
453 SCNHDR *scn;
454 struct coff32 *coff;
455 unsigned char buf[LINESZ];
456
457 coff = obj->data;
458 hdr = &coff->hdr;
459
460 if (hdr->f_nscns == 0)
461 return 1;
462
463 lines = calloc(hdr->f_nscns, sizeof(lp));
464 if (!lines)
465 return 0;
466 coff->lines = lines;
467
468 for (i = 0; i < hdr->f_nscns; i++) {
469 scn = &coff->scns[i];
470 if (scn->s_nlnno == 0)
471 continue;
472
473 lp = calloc(sizeof(*lp), scn->s_nlnno);
474 if (!lp)
475 return 0;
476 lines[i] = lp;
477
478 if (!objpos(obj, fp, scn->s_lnnoptr))
479 return 0;
480
481 for (j = 0; j < scn->s_nlnno; j++) {
482 if (fread(buf, LINESZ, 1, fp) != 1)
483 return 0;
484 unpack_line(ORDER(obj->type), buf, lp);
485 if (lp->l_lnno != 0
486 && lp->l_addr.l_symndx >= hdr->f_nsyms) {
487 return 0;
488 }
489 ++lp;
490 }
491 }
492
493 return 1;
494 }
495
496 static int
497 readaout(Obj *obj, FILE *fp)
498 {
499 struct coff32 *coff = obj->data;
500 FILHDR *hdr = &coff->hdr;
501 unsigned char buf[AOUTSZ];
502
503 if (hdr->f_opthdr == 0)
504 return 1;
505
506 if (fread(buf, AOUTSZ, 1, fp) != 1)
507 return 0;
508
509 unpack_aout(ORDER(obj->type), buf, &coff->aout);
510
511 return 1;
512 }
513
514 static int
515 validate(Obj *obj)
516 {
517 long i, n;
518 SYMENT *ent;
519 struct coff32 *coff = obj->data;
520 FILHDR *hdr = &coff->hdr;
521
522 ent = NULL;
523 for (i = 0; i < hdr->f_nsyms; i++) {
524 SCNHDR *scn;
525 AUXENT *aux;
526 Entry *ep = &coff->ents[i];
527
528 aux = &ep->u.aux;
529 switch (ep->type) {
530 case SYM_ENT:
531 ent = &ep->u.sym;
532 if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz)
533 return -1;
534 break;
535 case SYM_AUX_FILE:
536 if (aux->x_zeroes != 0 && aux->x_offset > coff->strsiz)
537 return -1;
538 break;
539 case SYM_AUX_SCN:
540 if (aux->x_scnlen < 0)
541 return -1;
542 n = ent->n_scnum;
543 if (n <= 0)
544 return -1;
545 scn = &coff->scns[n-1];
546 if (scn->s_nrelloc != aux->x_nreloc)
547 return -1;
548 if (scn->s_nlnno != aux->x_nlinno)
549 return -1;
550 break;
551 case SYM_AUX_FUN:
552 case SYM_AUX_SYM:
553 if (aux->x_endndx < 0 || aux->x_endndx > hdr->f_nsyms)
554 return -1;
555 case SYM_AUX_ARY:
556 if (aux->x_tagndx < 0 || aux->x_tagndx > hdr->f_nsyms)
557 return -1;
558 if (aux->x_tvndx < 0 || aux->x_tvndx > hdr->f_nsyms)
559 return -1;
560 break;
561 case SYM_AUX_UNK:
562 break;
563 default:
564 return -1;
565 }
566 }
567
568 return 0;
569 }
570
571 int
572 coff32read(Obj *obj, FILE *fp)
573 {
574
575 if (!readhdr(obj, fp))
576 return -1;
577 if (!readaout(obj, fp))
578 return -1;
579 if (!readscns(obj, fp))
580 return -1;
581 if (!readents(obj, fp))
582 return -1;
583 if (!readstr(obj, fp))
584 return -1;
585 if (!readreloc(obj, fp))
586 return -1;
587 if (!readlines(obj, fp))
588 return -1;
589
590 return validate(obj);
591 }