scc

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

coff32setsec.c (2354B)


      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 
     12 static char *
     13 secname(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 
     35 Section *
     36 coff32setsec(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 }