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