scc

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

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

  1#include <limits.h>
  2#include <stdio.h>
  3#include <stdlib.h>
  4#include <string.h>
  5
  6#include <scc/mach.h>
  7#include <scc/coff32.h>
  8
  9#include "../libmach.h"
 10#include "fun.h"
 11
 12static char *
 13secname(Coff32 *coff, SCNHDR *scn, Section *sec)
 14{
 15	char *p;
 16	unsigned long siz = strlen(sec->name);
 17
 18	if (siz < SCNNMLEN)
 19		return strncpy(scn->s_name, sec->name, SCNNMLEN);
 20
 21	if (coff->strsiz > ULONG_MAX - siz - 1)
 22		return NULL;
 23
 24	siz += coff->strsiz + 1;
 25	if ((p = realloc(coff->strtbl, siz)) == NULL)
 26		return NULL;
 27	coff->strtbl = p;
 28
 29	scn->s_zeroes = 0;
 30	scn->s_offset = coff->strsiz;
 31	coff->strsiz += siz;
 32	return strcpy(&coff->strtbl[scn->s_offset], sec->name);
 33}
 34
 35Section *
 36coff32setsec(Obj *obj, int *idx, Section *sec)
 37{
 38	long flags, n = *idx;
 39	SCNHDR *scn;
 40	Coff32 *coff = obj->data;
 41	FILHDR *hdr = &coff->hdr;
 42
 43	/* TODO: what happens with SABS? */
 44	switch (sec->type) {
 45	case 'D':
 46		switch (sec->flags) {
 47		case SALLOC | SRELOC | SLOAD | SWRITE | SREAD:
 48			if (strcmp(sec->name ,".data") == 0)
 49				flags = STYP_DATA;
 50			else
 51				flags = STYP_REG;
 52			break;
 53		case SALLOC | SREAD | SWRITE:
 54			flags = STYP_NOLOAD;
 55			break;
 56		case SALLOC | SRELOC | SLOAD | SREAD:
 57			flags = STYP_RDATA;
 58			break;
 59		case SEXEC | SALLOC | SRELOC | SLOAD | SREAD:
 60			flags = STYP_TEXT | STYP_DATA;
 61			break;
 62		default:
 63			goto invalid;
 64		}
 65		break;
 66	case 'T':
 67		flags = STYP_TEXT;
 68		break;
 69	case 'B':
 70		flags = STYP_BSS;
 71		break;
 72	case 'N':
 73	case '?':
 74	default:
 75	invalid:
 76		/* TODO */
 77		return NULL;
 78	}
 79
 80	if (strlen(sec->name) >= SCNNMLEN)
 81		return NULL;
 82
 83	if (n >= hdr->f_nscns) {
 84		if (n > SHRT_MAX - 1)
 85			return NULL;
 86		scn = realloc(coff->scns, (n+1) * sizeof(SCNHDR));
 87		if (!scn)
 88			return NULL;
 89		coff->scns = scn;
 90		hdr->f_nscns = n + 1;
 91	}
 92
 93	scn = &coff->scns[n];
 94	if (!secname(coff, scn, sec))
 95		return NULL;
 96
 97	/*
 98	 * sec->offset is ignored because it is very unlikely
 99	 * that the vaule is meaningful here. The field offset
100	 * was added only to allow getsec to retrive the information
101	 * in a generic way, but it was never expected to be a 2 way
102	 * relation. That pointer is updated when the object file
103	 * is written using a mapping.
104	 */
105	scn->s_paddr = sec->load;
106	scn->s_vaddr = sec->base;
107	scn->s_size = sec->size;
108	scn->s_scnptr = 0;
109	scn->s_relptr = 0;
110	scn->s_lnnoptr = 0;
111	scn->s_nrelloc = 0;
112	scn->s_nlnno = 0;
113	scn->s_flags = flags; 
114
115	return sec;
116}