scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

coff32setsec.c (2337B)


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