coff32write.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
       ---
       coff32write.c (6703B)
       ---
            1 #include <assert.h>
            2 #include <limits.h>
            3 #include <stdint.h>
            4 #include <stdio.h>
            5 #include <stdlib.h>
            6 #include <string.h>
            7 
            8 #include <scc/mach.h>
            9 
           10 #include "../libmach.h"
           11 #include "coff32.h"
           12 
           13 static void
           14 pack_hdr(int order, unsigned char *buf, FILHDR *hdr)
           15 {
           16         int n;
           17 
           18         n = pack(order,
           19                  buf,
           20                  "sslllss",
           21                  hdr->f_magic,
           22                  hdr->f_nscns,
           23                  hdr->f_timdat,
           24                  hdr->f_symptr,
           25                  hdr->f_nsyms,
           26                  hdr->f_opthdr,
           27                  hdr->f_flags);
           28         assert(n == FILHSZ);
           29 }
           30 
           31 static void
           32 pack_scn(int order, unsigned char *buf, SCNHDR *scn)
           33 {
           34         int n;
           35 
           36         n = pack(order,
           37                  buf,
           38                  "'8llllllssl",
           39                  scn->s_name,
           40                  scn->s_paddr,
           41                  scn->s_vaddr,
           42                  scn->s_size,
           43                  scn->s_scnptr,
           44                  scn->s_relptr,
           45                  scn->s_lnnoptr,
           46                  scn->s_nrelloc,
           47                  scn->s_nlnno,
           48                  scn->s_flags);
           49         assert(n == SCNHSZ);
           50 }
           51 
           52 static void
           53 pack_ent(int order, unsigned char *buf, SYMENT *ent)
           54 {
           55         int n;
           56         char *s;
           57 
           58         /* TODO: What happens with the union? */
           59 
           60         n = pack(order,
           61                  buf,
           62                  "'8lsscc",
           63                  ent->n_name,
           64                  ent->n_value,
           65                  ent->n_scnum,
           66                  ent->n_type,
           67                  ent->n_sclass,
           68                  ent->n_numaux);
           69         assert(n == SYMESZ);
           70 }
           71 
           72 static void
           73 pack_aout(int order, unsigned char *buf, AOUTHDR *aout)
           74 {
           75         int n;
           76 
           77         n = pack(order,
           78                  buf,
           79                  "ssllllll",
           80                  aout->magic,
           81                  aout->vstamp,
           82                  aout->tsize,
           83                  aout->dsize,
           84                  aout->bsize,
           85                  aout->entry,
           86                  aout->text_start,
           87                  aout->data_start);
           88         assert(n == AOUTSZ);
           89 }
           90 
           91 static void
           92 pack_reloc(int order, unsigned char *buf, RELOC *rel)
           93 {
           94         int n;
           95 
           96         n = pack(order,
           97                  buf,
           98                  "lls",
           99                  rel->r_vaddr,
          100                  rel->r_symndx,
          101                  rel->r_type);
          102         assert(n == RELSZ);
          103 }
          104 
          105 static void
          106 pack_line(int order, unsigned char *buf, LINENO *lp)
          107 {
          108         int n;
          109 
          110         n = pack(order,
          111                  buf,
          112                  "lls",
          113                  lp->l_symndx,
          114                  lp->l_paddr,
          115                  lp->l_lnno);
          116         assert(n == LINESZ);
          117 }
          118 
          119 static int
          120 writehdr(Obj *obj, FILE *fp)
          121 {
          122         FILHDR *hdr;
          123         struct coff32 *coff;
          124         unsigned char buf[FILHSZ];
          125 
          126         coff  = obj->data;
          127         hdr = &coff->hdr;
          128 
          129         pack_hdr(ORDER(obj->type), buf, hdr);
          130         if (fwrite(buf, FILHSZ, 1, fp) != 1)
          131                 return 0;
          132 
          133         return 1;
          134 }
          135 
          136 static int
          137 writescns(Obj *obj, FILE *fp)
          138 {
          139         int i;
          140         SCNHDR *scn;
          141         FILHDR *hdr;
          142         struct coff32 *coff;
          143         unsigned char buf[SCNHSZ];
          144 
          145         coff  = obj->data;
          146         hdr = &coff->hdr;
          147 
          148         for (i = 0; i < hdr->f_nscns; i++) {
          149                 scn = &coff->scns[i];
          150                 pack_scn(ORDER(obj->type), buf, scn);
          151                 if (fwrite(buf, SCNHSZ, 1, fp) != 1)
          152                         return 0;
          153         }
          154 
          155         return 1;
          156 }
          157 
          158 static int
          159 writeents(Obj *obj, FILE *fp)
          160 {
          161         long i, len, strsiz;
          162         char *strtbl, *s, *name;
          163         FILHDR *hdr;
          164         struct coff32 *coff;
          165         unsigned char buf[SYMESZ];
          166 
          167         coff  = obj->data;
          168         hdr = &coff->hdr;
          169 
          170         if (!coff->ents)
          171                 return 1;
          172 
          173         strtbl = NULL;
          174         strsiz = 0;
          175 
          176         for (i = 0; i < hdr->f_nsyms; i++) {
          177                 SYMENT *ent = &coff->ents[i];
          178 
          179                 if (ent->n_zeroes == 0) {
          180                         name = &coff->strtbl[ent->n_offset];
          181                         len = strlen(name) + 1;
          182                         if (len > strsiz - LONG_MAX)
          183                                 goto err;
          184                         s = realloc(strtbl, strsiz + len);
          185                         if (!s)
          186                                 goto err;
          187                         memcpy(s + strsiz, name, len);
          188                         strtbl = s;
          189                         strsiz += len;
          190                 }
          191 
          192                 pack_ent(ORDER(obj->type), buf, ent);
          193                 if (fwrite(buf, SYMESZ, 1, fp) != 1)
          194                         return 0;
          195         }
          196 
          197         free(coff->strtbl);
          198         coff->strtbl = strtbl;
          199         coff->strsiz = strsiz;
          200 
          201         return 1;
          202 
          203 err:
          204         free(strtbl);
          205         return 0;
          206 }
          207 
          208 static int
          209 writestr(Obj *obj, FILE *fp)
          210 {
          211         struct coff32 *coff;
          212         unsigned char buf[4];
          213 
          214         coff = obj->data;
          215         if ((coff->strsiz & 0xffff) != coff->strsiz)
          216                 return 0;
          217 
          218         pack(ORDER(obj->type), buf, "l", coff->strsiz);
          219         fwrite(buf, 4, 1, fp);
          220         fwrite(coff->strtbl, coff->strsiz, 1, fp);
          221 
          222         return 1;
          223 }
          224 
          225 static int
          226 writeaout(Obj *obj, FILE *fp)
          227 {
          228         FILHDR *hdr;
          229         struct coff32 *coff;
          230         unsigned char buf[AOUTSZ];
          231 
          232         coff  = obj->data;
          233         hdr = &coff->hdr;
          234 
          235         if (hdr->f_opthdr == 0)
          236                 return 1;
          237         pack_aout(ORDER(obj->type), buf, &coff->aout);
          238 
          239         return fread(buf, AOUTSZ, 1, fp) != 1;
          240 }
          241 
          242 static int
          243 writereloc(Obj *obj, FILE *fp)
          244 {
          245         int i, j;
          246         RELOC *rp;
          247         SCNHDR *scn;
          248         FILHDR *hdr;
          249         struct coff32 *coff;
          250         unsigned char buf[RELSZ];
          251 
          252         coff  = obj->data;
          253         hdr = &coff->hdr;
          254 
          255         if (!coff->rels)
          256                 return 1;
          257 
          258         for (i = 0; i < hdr->f_nscns; i++) {
          259                 rp = coff->rels[i];
          260                 if (!rp)
          261                         continue;
          262                 scn = &coff->scns[i];
          263 
          264                 for (j = 0; j < scn->s_nrelloc; j++) {
          265                         pack_reloc(ORDER(obj->type), buf, &rp[i]);
          266                         if (fwrite(buf, RELSZ, 1, fp) != 1)
          267                                 return 0;
          268                 }
          269         }
          270 
          271         return 1;
          272 }
          273 
          274 static int
          275 writelines(Obj *obj, FILE *fp)
          276 {
          277         int i;
          278         long j;
          279         LINENO *lp;
          280         SCNHDR *scn;
          281         struct coff32 *coff = obj->data;
          282         FILHDR *hdr = &coff->hdr;
          283         unsigned char buf[LINESZ];
          284 
          285         if (!coff->lines)
          286                 return 1;
          287 
          288         for (i = 0; i < hdr->f_nscns; i++) {
          289                 lp = coff->lines[i];
          290                 if (!lp)
          291                         continue;
          292                 scn = &coff->scns[i];
          293                 for (j = 0; j < scn->s_nlnno; j++) {
          294                         pack_line(ORDER(obj->type), buf, &lp[j]);
          295                         if (fwrite(buf, LINESZ, 1, fp) == 1)
          296                                 return 0;
          297                 }
          298         }
          299 
          300         return 1;
          301 }
          302 
          303 static int
          304 writedata(Obj *obj, Map *map, FILE *fp)
          305 {
          306         int id;
          307         long nsec;
          308         unsigned long long n;
          309         struct coff32 *coff = obj->data;
          310         FILHDR *hdr = &coff->hdr;
          311         SCNHDR *scn;
          312         Mapsec *sec;
          313 
          314         nsec = hdr->f_nscns;
          315         for (scn = coff->scns; nsec--; scn++) {
          316                 if ((id = findsec(map, scn->s_name)) < 0)
          317                         continue;
          318                 sec = &map->sec[id];
          319                 if (!sec->fp)
          320                         continue;
          321 
          322                 fseek(sec->fp, sec->offset, SEEK_SET);
          323 
          324                 for (n = sec->end - sec->begin; n > 0; n--)
          325                         putc(getc(sec->fp), fp);
          326 
          327                 if (ferror(sec->fp))
          328                         return 0;
          329         }
          330 
          331         return 1;
          332 }
          333 
          334 int
          335 coff32write(Obj *obj, Map *map, FILE *fp)
          336 {
          337         int id;
          338         long ptr, n;
          339         SCNHDR *scn;
          340         Mapsec *sec;
          341         struct coff32 *coff = obj->data;
          342         FILHDR *hdr = &coff->hdr;
          343 
          344         ptr = ftell(fp);
          345         obj->pos = ptr;
          346 
          347         n = hdr->f_nscns;
          348         ptr += FILHSZ + hdr->f_opthdr + n*SCNHSZ;
          349         for (scn = coff->scns; n--; scn++) {
          350                 scn->s_scnptr = 0;
          351                 if ((id = findsec(map, scn->s_name)) < 0)
          352                         continue;
          353                 sec = &map->sec[id];
          354                 if (!sec->fp)
          355                         continue;
          356 
          357                 scn->s_scnptr = ptr;
          358                 ptr += scn->s_size;
          359         }
          360         hdr->f_symptr = (hdr->f_nsyms > 0) ? ptr : 0;
          361 
          362         n = hdr->f_nscns;
          363         for (scn = coff->scns; n--; scn++) {
          364                 scn->s_relptr = ptr;
          365                 ptr += scn->s_nrelloc * RELSZ;
          366         }
          367 
          368         n = hdr->f_nscns;
          369         for (scn = coff->scns; n--; scn++) {
          370                 scn->s_lnnoptr = ptr;
          371                 ptr += scn->s_nlnno * RELSZ;
          372         }
          373 
          374         /* and now update symbols */
          375 
          376         if (!writehdr(obj, fp))
          377                 return -1;
          378         if (!writeaout(obj, fp))
          379                 return -1;
          380         if (!writescns(obj, fp))
          381                 return -1;
          382         if (!writedata(obj, map, fp))
          383                 return -1;
          384         if (!writereloc(obj, fp))
          385                 return -1;
          386         if (!writelines(obj, fp))
          387                 return -1;
          388         if (!writeents(obj, fp))
          389                 return -1;
          390         if (!writestr(obj, fp))
          391                 return -1;
          392         if (ferror(fp))
          393                 return -1;
          394 
          395         return 0;
          396 }