Home
       pass1.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       pass1.c (4717B)
       ---
            1 #include <errno.h>
            2 #include <ctype.h>
            3 #include <stdarg.h>
            4 #include <stdio.h>
            5 #include <stdlib.h>
            6 #include <string.h>
            7 
            8 #include <scc/mach.h>
            9 #include <scc/scc.h>
           10 #include <scc/ar.h>
           11 
           12 #include "ld.h"
           13 
           14 enum {
           15         OUTLIB,
           16         INLIB,
           17 };
           18 
           19 int bintype = -1;
           20 Obj *objhead;
           21 
           22 static int
           23 is_needed(Obj *obj)
           24 {
           25         int i;
           26         Symbol sym;
           27 
           28         for (i = 0; getsym(obj, &i, &sym); i++) {
           29                 if (hasref(sym.name))
           30                         return 1;
           31         }
           32 
           33         return 0;
           34 }
           35 
           36 static void
           37 newsec(Section *osec, Obj *obj)
           38 {
           39         int align;
           40         Section *sec;
           41         unsigned long long base;
           42 
           43         sec = lookupsec(osec->name);
           44         if (sec->type == 'U') {
           45                 sec->type = osec->type;
           46                 sec->base = osec->base;
           47                 sec->size = osec->size;
           48                 sec->flags = osec->flags;
           49                 align = 0;
           50         } else {
           51                 if (sec->type != osec->type
           52                 || sec->flags != osec->flags
           53                 || sec->align != osec->align) {
           54                         error("incompatible definition of section %s",
           55                               sec->name);
           56                         return;
           57                 }
           58                 align = osec->align;
           59                 align -= sec->size & align-1;
           60                 grow(sec, align);
           61         }
           62 
           63         rebase(obj, osec->index, sec->size);
           64         copy(obj, osec, sec);
           65 }
           66 
           67 static void
           68 newsym(Symbol *sym, Obj *obj)
           69 {
           70         int id;
           71         Section sec;
           72 
           73         if (sym->type == 'U' || islower(sym->type))
           74                 return;
           75 
           76         sym = define(sym, obj);
           77         id = sym->section;
           78         getsec(obj, &id, &sec);
           79           sym->value += sec.base;
           80 }
           81 
           82 static void
           83 load(FILE *fp, int inlib)
           84 {
           85         int t, i;
           86         Obj *obj;
           87         Section sec;
           88         Symbol sym;
           89         static Obj *last;
           90 
           91         if ((t = objprobe(fp, NULL)) < 0) {
           92                 error("bad format");
           93                 return;
           94         }
           95 
           96         if (bintype != -1 && bintype != t) {
           97                 error("not compatible object file");
           98                 return;
           99         }
          100         bintype = t;
          101 
          102         if ((obj = newobj(t)) == NULL) {
          103                 error(strerror(errno));
          104                 return;
          105         }
          106 
          107         if (readobj(obj, fp) < 0) {
          108                 error(strerror(errno));
          109                 goto delete;
          110         }
          111 
          112         if (inlib && !is_needed(obj))
          113                 goto delete;
          114 
          115         for (i = 0; getsec(obj, &i, &sec); i++)
          116                 newsec(&sec, obj);
          117 
          118         for ( i = 0; getsym(obj, &i, &sym); i++)
          119                 newsym(&sym, obj);
          120 
          121         obj->next = last;
          122         last = obj;
          123         if (!objhead)
          124                 objhead = obj;
          125 
          126         return;
          127 
          128  delete:
          129         delobj(obj);
          130         return;
          131 }
          132 
          133 static void
          134 scanindex(FILE *fp)
          135 {
          136         int t, added;
          137         long n, i, *offs;
          138         char **names;
          139         Symbol *sym;
          140 
          141         if (getindex(bintype, &n, &names, &offs, fp) < 0) {
          142                 error("corrupted index");
          143                 return;
          144         }
          145 
          146         for (added = 0; moreundef(); added = 0) {
          147                 for (i = 0; i < n; i++) {
          148                         if (!hasref(names[i]))
          149                                 continue;
          150 
          151                         if (fseek(fp, offs[i], SEEK_SET) == EOF) {
          152                                 error(strerror(errno));
          153                                 goto clean;
          154                         }
          155 
          156                         load(fp, OUTLIB);
          157                         added = 1;
          158                 }
          159 
          160                 if (!added)
          161                         break;
          162         }
          163 clean:
          164         for (i = 0; i < n; i++)
          165                 free(names[i]);
          166         free(names);
          167         free(offs);
          168 }
          169 
          170 void
          171 scanlib(FILE *fp)
          172 {
          173         long cur, off;
          174         char memb[SARNAM+1];
          175 
          176         if (bintype == -1) {
          177                 error("an object file is needed before any library");
          178                 return;
          179         }
          180 
          181         cur = ftell(fp);
          182         if ((off = armember(fp, memb)) < 0)
          183                 goto corrupted;
          184 
          185         if (strcmp(memb, "/") == 0 || strcmp(memb, "__.SYMDEF") == 0) {
          186                 scanindex(fp);
          187                 return;
          188         }
          189 
          190         fseek(fp, cur, SEEK_SET);
          191         for (;;) {
          192                 cur = ftell(fp);
          193                 off = armember(fp, memb);
          194                 switch (off) {
          195                 case -1:
          196                         goto corrupted;
          197                 case 0:
          198                         return;
          199                 default:
          200                         membname = memb;
          201                         if (objprobe(fp, NULL) != -1)
          202                                 load(fp, INLIB);
          203                         membname = NULL;
          204                         fseek(fp, cur, SEEK_SET);
          205                         fseek(fp, off, SEEK_CUR);
          206                         break;
          207                 }
          208         }
          209 
          210 corrupted:
          211         error(strerror(errno));
          212         error("library corrupted");
          213 }
          214 
          215 static FILE *
          216 openfile(char *name)
          217 {
          218         size_t pathlen, len;
          219         FILE *fp;
          220         char **bp;
          221         char libname[FILENAME_MAX];
          222         static char buffer[FILENAME_MAX];
          223 
          224         filename = name;
          225         membname = NULL;
          226         if (name[0] != '-' || name[1] != 'l') {
          227                 if ((fp = fopen(name, "rb")) == NULL)
          228                         error(strerror(errno));
          229                 return fp;
          230         }
          231 
          232         len = strlen(name+2) + 3;
          233         if (len > FILENAME_MAX-1) {
          234                 error("library name too long");
          235                 return NULL;
          236         }
          237         strcat(strcpy(buffer, "lib"), name+2);
          238 
          239         filename = buffer;
          240         if ((fp = fopen(buffer, "rb")) != NULL)
          241                 return fp;
          242 
          243         for (bp = libpaths; *bp; ++bp) {
          244                 pathlen = strlen(*bp);
          245                 if (pathlen + len > FILENAME_MAX-1)
          246                         continue;
          247                 memcpy(libname, *bp, pathlen);
          248                 memcpy(libname+pathlen+1, buffer, len);
          249                 buffer[pathlen] = '/';
          250 
          251                 if ((fp = fopen(libname, "rb")) != NULL)
          252                         return fp;
          253         }
          254 
          255         error("not found");
          256         return NULL;
          257 }
          258 
          259 static void
          260 process(char *name)
          261 {
          262         int t;
          263         FILE *fp;
          264 
          265         if ((fp = openfile(name)) == NULL)
          266                 return;
          267 
          268         if (archive(fp))
          269                 scanlib(fp);
          270         else
          271                 load(fp, OUTLIB);
          272 
          273         fclose(fp);
          274 }
          275 
          276 /*
          277  * Get the list of object files that are going to be linked
          278  */
          279 void
          280 pass1(int argc, char *argv[])
          281 {
          282         char **av, *ap;
          283 
          284         for (av = argv+1; *av; ++av) {
          285                 if (av[0][0] != '-') {
          286                         process(*av);
          287                         continue;
          288                 }
          289                 for (ap = &av[0][1]; *ap; ++ap) {
          290                         switch (*ap) {
          291                         case 'l':
          292                                 process(nextarg(&ap, &av));
          293                                 break;
          294                         case 'u':
          295                                 lookupsym(nextarg(&ap, &av));
          296                                 break;
          297                         }
          298                 }
          299         }
          300 
          301         if (moreundef()) {
          302                 listundef();
          303                 exit(EXIT_FAILURE);
          304         }
          305 }