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 (9373B)
       ---
            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 #include <scc/coff32.h>
           10 
           11 #include "../libmach.h"
           12 #include "fun.h"
           13 
           14 struct strtbl {
           15         char *s;
           16         long siz;
           17 };
           18 
           19 static void
           20 pack_hdr(int order, unsigned char *buf, FILHDR *hdr)
           21 {
           22         int n;
           23 
           24         n = pack(order,
           25                  buf,
           26                  "sslllss",
           27                  hdr->f_magic,
           28                  hdr->f_nscns,
           29                  hdr->f_timdat,
           30                  hdr->f_symptr,
           31                  hdr->f_nsyms,
           32                  hdr->f_opthdr,
           33                  hdr->f_flags);
           34         assert(n == FILHSZ);
           35 }
           36 
           37 static void
           38 pack_scn(int order, unsigned char *buf, SCNHDR *scn)
           39 {
           40         int n;
           41 
           42         if (scn->s_zeroes == 0)
           43                 pack(order, buf, "ll", scn->s_zeroes, scn->s_offset);
           44         else
           45                 memcpy(buf, scn->s_name, 8);
           46 
           47         n = pack(order,
           48                  buf + 8,
           49                  "llllllssl",
           50                  scn->s_paddr,
           51                  scn->s_vaddr,
           52                  scn->s_size,
           53                  scn->s_scnptr,
           54                  scn->s_relptr,
           55                  scn->s_lnnoptr,
           56                  scn->s_nrelloc,
           57                  scn->s_nlnno,
           58                  scn->s_flags);
           59         n += 8;
           60         assert(n == SCNHSZ);
           61 }
           62 
           63 static void
           64 pack_ent(int order, unsigned char *buf, SYMENT *ent)
           65 {
           66         int n;
           67 
           68         if (ent->n_zeroes == 0)
           69                 pack(order, buf, "ll", ent->n_zeroes, ent->n_offset);
           70         else
           71                 memcpy(buf, ent->n_name, 8);
           72 
           73         n = pack(order,
           74                  buf + 8,
           75                  "lsscc",
           76                      ent->n_value,
           77                      ent->n_scnum,
           78                      ent->n_type,
           79                      ent->n_sclass,
           80                      ent->n_numaux);
           81         n += 8;
           82 
           83         assert(n == SYMESZ);
           84 }
           85 
           86 static void
           87 pack_aux_file(int order, unsigned char *buf, AUXENT *aux)
           88 {
           89 
           90         if (aux->x_zeroes == 0) {
           91                 memset(buf, 0, sizeof(AUXESZ));
           92                 pack(order, buf, "ll", aux->x_zeroes, aux->x_offset);
           93         } else {
           94                 memcpy(buf, aux->x_fname, E_FILNMLEN);
           95         }
           96 }
           97 
           98 static void
           99 pack_aux_scn(int order, unsigned char *buf, AUXENT *aux)
          100 {
          101         int n;
          102 
          103         n = pack(order,
          104                  buf,
          105                  "lsslsc",
          106                  aux->x_scnlen,
          107                  aux->x_nreloc,
          108                  aux->x_nlinno,
          109                  aux->x_checksum,
          110                  aux->x_associated,
          111                  aux->x_comdat);
          112         assert(n == AUXESZ);
          113 }
          114 
          115 static void
          116 pack_aux_fun(int order, unsigned char *buf, AUXENT *aux)
          117 {
          118         int n;
          119 
          120         n = pack(order,
          121                  buf,
          122                  "lllls",
          123                  aux->x_tagndx,
          124                  aux->x_fsize,
          125                  aux->x_lnnoptr,
          126                  aux->x_endndx,
          127                  aux->x_tvndx);
          128         assert(n == AUXESZ);
          129 }
          130 
          131 static void
          132 pack_aux_ary(int order, unsigned char *buf, AUXENT *aux)
          133 {
          134         int n;
          135 
          136         n = pack(order,
          137                  buf,
          138                  "lssssss",
          139                  aux->x_tagndx,
          140                  aux->x_lnno,
          141                  aux->x_size,
          142                  aux->x_dimen[0],
          143                  aux->x_dimen[1],
          144                  aux->x_dimen[2],
          145                  aux->x_dimen[3],
          146                  aux->x_tvndx);
          147         assert(n == AUXESZ);
          148 }
          149 
          150 static void
          151 pack_aux_sym(int order, unsigned char *buf, AUXENT *aux)
          152 {
          153         int n;
          154 
          155         n = pack(order,
          156                  buf,
          157                  "lsslls",
          158                  aux->x_tagndx,
          159                  aux->x_lnno,
          160                  aux->x_size,
          161                  aux->x_lnnoptr,
          162                  aux->x_endndx,
          163                  aux->x_tvndx);
          164         assert(n == AUXESZ);
          165 }
          166 
          167 static void
          168 pack_aout(int order, unsigned char *buf, AOUTHDR *aout)
          169 {
          170         int n;
          171 
          172         n = pack(order,
          173                  buf,
          174                  "ssllllll",
          175                  aout->magic,
          176                  aout->vstamp,
          177                  aout->tsize,
          178                  aout->dsize,
          179                  aout->bsize,
          180                  aout->entry,
          181                  aout->text_start,
          182                  aout->data_start);
          183         assert(n == AOUTSZ);
          184 }
          185 
          186 static void
          187 pack_reloc(int order, unsigned char *buf, RELOC *rel)
          188 {
          189         int n;
          190 
          191         n = pack(order,
          192                  buf,
          193                  "lls",
          194                  rel->r_vaddr,
          195                  rel->r_symndx,
          196                  rel->r_type);
          197         assert(n == RELSZ);
          198 }
          199 
          200 static void
          201 pack_line(int order, unsigned char *buf, LINENO *lp)
          202 {
          203         int n;
          204 
          205         n = pack(order,
          206                  buf,
          207                  "lls",
          208                  lp->l_addr.l_symndx,
          209                  lp->l_lnno);
          210         assert(n == LINESZ);
          211 }
          212 
          213 static int
          214 writehdr(Obj *obj, FILE *fp)
          215 {
          216         FILHDR *hdr;
          217         struct coff32 *coff;
          218         unsigned char buf[FILHSZ];
          219 
          220         coff  = obj->data;
          221         hdr = &coff->hdr;
          222 
          223         pack_hdr(ORDER(obj->type), buf, hdr);
          224         if (fwrite(buf, FILHSZ, 1, fp) != 1)
          225                 return 0;
          226 
          227         return 1;
          228 }
          229 
          230 static int
          231 allocstring(struct coff32 *coff, long off, struct strtbl *tbl)
          232 {
          233         char *s, *name;
          234         long len, siz;
          235 
          236         siz = tbl->siz;
          237         name = &coff->strtbl[off];
          238         len = strlen(name) + 1;
          239         if (len > siz - LONG_MAX)
          240                 return 0;
          241 
          242         s = realloc(tbl->s, siz + len);
          243         if (!s)
          244                 return 0;
          245         memcpy(s + siz, name, len);
          246 
          247         tbl->s = s;
          248         tbl->siz += len;
          249 
          250         return 1;
          251 }
          252 
          253 static int
          254 writescns(Obj *obj, FILE *fp, struct strtbl *tbl)
          255 {
          256         int i;
          257         SCNHDR *scn;
          258         FILHDR *hdr;
          259         struct coff32 *coff;
          260         unsigned char buf[SCNHSZ];
          261 
          262         coff  = obj->data;
          263         hdr = &coff->hdr;
          264 
          265         for (i = 0; i < hdr->f_nscns; i++) {
          266                 scn = &coff->scns[i];
          267                 if (scn->s_zeroes == 0) {
          268                         if (!allocstring(coff, scn->s_offset, tbl))
          269                                 return 0;
          270                 }
          271                 pack_scn(ORDER(obj->type), buf, scn);
          272                 if (fwrite(buf, SCNHSZ, 1, fp) != 1)
          273                         return 0;
          274         }
          275 
          276         return 1;
          277 }
          278 
          279 static int
          280 writeents(Obj *obj, FILE *fp, struct strtbl *tbl)
          281 {
          282         long i;
          283         FILHDR *hdr;
          284         struct coff32 *coff;
          285         unsigned char buf[SYMESZ];
          286 
          287         coff  = obj->data;
          288         hdr = &coff->hdr;
          289 
          290         if (!coff->ents)
          291                 return 1;
          292 
          293         for (i = 0; i < hdr->f_nsyms; i++) {
          294                 SYMENT *ent;
          295                 AUXENT *aux;
          296                 Entry *ep = &coff->ents[i];
          297 
          298                 aux = &ep->u.aux;
          299                 switch (ep->type) {
          300                 case SYM_ENT:
          301                         ent = &ep->u.sym;
          302                         if (ent->n_zeroes == 0) {
          303                                 if (!allocstring(coff, ent->n_offset, tbl))
          304                                         return 0;
          305                         }
          306                         pack_ent(ORDER(obj->type), buf, ent);
          307                         break;
          308                 case SYM_AUX_UNK:
          309                         memcpy(buf, ep->u.buf, AUXESZ);
          310                         break;
          311                 case SYM_AUX_SYM:
          312                         pack_aux_file(ORDER(obj->type), buf, aux);
          313                         break;
          314                 case SYM_AUX_FILE:
          315                         if (aux->x_zeroes == 0) {
          316                                 if (!allocstring(coff, aux->x_offset, tbl))
          317                                         return 0;
          318                         }
          319                         pack_aux_file(ORDER(obj->type), buf, aux);
          320                         break;
          321                 case SYM_AUX_SCN:
          322                         pack_aux_scn(ORDER(obj->type), buf, aux);
          323                         break;
          324                 case SYM_AUX_FUN:
          325                         pack_aux_fun(ORDER(obj->type), buf, aux);
          326                         break;
          327                 case SYM_AUX_ARY:
          328                         pack_aux_ary(ORDER(obj->type), buf, aux);
          329                         break;
          330                 }
          331 
          332                 if (fwrite(buf, SYMESZ, 1, fp) != 1)
          333                         return 0;
          334         }
          335 
          336         return 1;
          337 }
          338 
          339 static int
          340 writestr(Obj *obj, FILE *fp, struct strtbl *tbl)
          341 {
          342         struct coff32 *coff;
          343         unsigned char buf[4];
          344 
          345         coff = obj->data;
          346 
          347         free(coff->strtbl);
          348         coff->strtbl = tbl->s;
          349         coff->strsiz = tbl->siz;
          350         tbl->s = NULL;
          351         tbl->siz = 0;
          352 
          353         if ((coff->strsiz & 0xffff) != coff->strsiz)
          354                 return 0;
          355 
          356         pack(ORDER(obj->type), buf, "l", coff->strsiz);
          357         fwrite(buf, 4, 1, fp);
          358         fwrite(coff->strtbl, coff->strsiz, 1, fp);
          359 
          360         return 1;
          361 }
          362 
          363 static int
          364 writeaout(Obj *obj, FILE *fp)
          365 {
          366         FILHDR *hdr;
          367         struct coff32 *coff;
          368         unsigned char buf[AOUTSZ];
          369 
          370         coff  = obj->data;
          371         hdr = &coff->hdr;
          372 
          373         if (hdr->f_opthdr == 0)
          374                 return 1;
          375         pack_aout(ORDER(obj->type), buf, &coff->aout);
          376 
          377         return fread(buf, AOUTSZ, 1, fp) != 1;
          378 }
          379 
          380 static int
          381 writereloc(Obj *obj, FILE *fp)
          382 {
          383         int i, j;
          384         RELOC *rp;
          385         SCNHDR *scn;
          386         FILHDR *hdr;
          387         struct coff32 *coff;
          388         unsigned char buf[RELSZ];
          389 
          390         coff  = obj->data;
          391         hdr = &coff->hdr;
          392 
          393         if (!coff->rels)
          394                 return 1;
          395 
          396         for (i = 0; i < hdr->f_nscns; i++) {
          397                 rp = coff->rels[i];
          398                 if (!rp)
          399                         continue;
          400                 scn = &coff->scns[i];
          401 
          402                 for (j = 0; j < scn->s_nrelloc; j++) {
          403                         pack_reloc(ORDER(obj->type), buf, &rp[i]);
          404                         if (fwrite(buf, RELSZ, 1, fp) != 1)
          405                                 return 0;
          406                 }
          407         }
          408 
          409         return 1;
          410 }
          411 
          412 static int
          413 writelines(Obj *obj, FILE *fp)
          414 {
          415         int i;
          416         long j;
          417         LINENO *lp;
          418         SCNHDR *scn;
          419         struct coff32 *coff = obj->data;
          420         FILHDR *hdr = &coff->hdr;
          421         unsigned char buf[LINESZ];
          422 
          423         if (!coff->lines)
          424                 return 1;
          425 
          426         for (i = 0; i < hdr->f_nscns; i++) {
          427                 lp = coff->lines[i];
          428                 if (!lp)
          429                         continue;
          430                 scn = &coff->scns[i];
          431                 for (j = 0; j < scn->s_nlnno; j++) {
          432                         pack_line(ORDER(obj->type), buf, &lp[j]);
          433                         if (fwrite(buf, LINESZ, 1, fp) == 1)
          434                                 return 0;
          435                 }
          436         }
          437 
          438         return 1;
          439 }
          440 
          441 static int
          442 writedata(Obj *obj, Map *map, FILE *fp)
          443 {
          444         long n;
          445         int id, nsec;
          446         Mapsec *msec;
          447         Section *sec;
          448         struct coff32 *coff = obj->data;
          449         FILHDR *hdr = &coff->hdr;
          450         SCNHDR *scn;
          451 
          452         nsec = hdr->f_nscns;
          453         for (scn = coff->scns; nsec--; scn++) {
          454                 if ((id = findsec(map, scn->s_name)) < 0)
          455                         continue;
          456                 msec = &map->sec[id];
          457                 sec = &msec->sec;
          458                 if (!msec->fp)
          459                         continue;
          460 
          461                 if (copysec(msec, fp) < 0)
          462                         return -1;
          463         }
          464 
          465         return 1;
          466 }
          467 
          468 int
          469 coff32write(Obj *obj, Map *map, FILE *fp)
          470 {
          471         int id;
          472         long ptr, n;
          473         SCNHDR *scn;
          474         Mapsec *sec;
          475         struct strtbl tbl;
          476         struct coff32 *coff = obj->data;
          477         FILHDR *hdr = &coff->hdr;
          478 
          479         ptr = ftell(fp);
          480         obj->pos = ptr;
          481         tbl.s = NULL;
          482         tbl.siz = 0;
          483 
          484         n = hdr->f_nscns;
          485         ptr += FILHSZ + hdr->f_opthdr + n*SCNHSZ;
          486         for (scn = coff->scns; n--; scn++) {
          487                 scn->s_scnptr = 0;
          488                 if ((id = findsec(map, scn->s_name)) < 0)
          489                         continue;
          490                 sec = &map->sec[id];
          491                 if (!sec->fp)
          492                         continue;
          493 
          494                 scn->s_scnptr = ptr;
          495                 ptr += scn->s_size;
          496         }
          497         hdr->f_symptr = (hdr->f_nsyms > 0) ? ptr : 0;
          498 
          499         n = hdr->f_nscns;
          500         for (scn = coff->scns; n--; scn++) {
          501                 scn->s_relptr = (scn->s_nrelloc > 0) ? ptr : 0;
          502                 ptr += scn->s_nrelloc * RELSZ;
          503         }
          504 
          505         n = hdr->f_nscns;
          506         for (scn = coff->scns; n--; scn++) {
          507                 scn->s_lnnoptr = (scn->s_nlnno > 0) ? ptr : 0;
          508                 ptr += scn->s_nlnno * RELSZ;
          509         }
          510 
          511         /* and now update symbols */
          512 
          513         if (!writehdr(obj, fp))
          514                 goto err;
          515         if (!writeaout(obj, fp))
          516                 goto err;
          517         if (!writescns(obj, fp, &tbl))
          518                 goto err;
          519         if (!writedata(obj, map, fp))
          520                 goto err;
          521         if (!writereloc(obj, fp))
          522                 goto err;
          523         if (!writelines(obj, fp))
          524                 goto err;
          525         if (!writeents(obj, fp, &tbl))
          526                 goto err;
          527         if (!writestr(obj, fp, &tbl))
          528                 goto err;
          529         if (ferror(fp))
          530                 goto err;
          531         return 0;
          532 
          533 err:
          534         free(tbl.s);
          535         return -1;
          536 }