scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 14static void
 15unpack_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
 32static void
 33unpack_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
 45static void
 46unpack_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
 71static void
 72unpack_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
 93static void
 94unpack_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
107static void
108unpack_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
126static void
127unpack_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
143static void
144unpack_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
164static void
165unpack_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
180static void
181unpack_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
199static void
200unpack_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
216static int
217readhdr(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
236static int
237readstr(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
270static int
271readreloc(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
317static int
318readauxs(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
372static int
373readents(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
418static int
419readscns(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
447static int
448readlines(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
496static int
497readaout(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
514static int
515validate(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
571int
572coff32read(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}