coff32setsec.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
       ---
       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 }