1#include <errno.h>2#include <ctype.h>3#include <stdarg.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>78#include <scc/mach.h>9#include <scc/scc.h>10#include <scc/ar.h>1112#include "ld.h"1314enum {15 OUTLIB,16 INLIB,17};1819int bintype = -1;20Obj *objhead;2122static int23is_needed(Obj *obj)24{25 int i;26 Symbol sym;2728 for (i = 0; getsym(obj, &i, &sym); i++) {29 if (hasref(sym.name))30 return 1;31 }3233 return 0;34}3536static void37newsec(Section *osec, Obj *obj)38{39 int align;40 Section *sec;41 unsigned long long base;4243 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->type52 || sec->flags != osec->flags53 || 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 }6263 rebase(obj, osec->index, sec->size);64 copy(obj, osec, sec);65}6667static void68newsym(Symbol *sym, Obj *obj)69{70 int id;71 Section sec;7273 if (sym->type == 'U' || islower(sym->type))74 return;7576 sym = define(sym, obj);77 id = sym->section;78 getsec(obj, &id, &sec);79 sym->value += sec.base;80}8182static void83load(FILE *fp, int inlib)84{85 int t, i;86 Obj *obj;87 Section sec;88 Symbol sym;89 static Obj *last;9091 if ((t = objprobe(fp, NULL)) < 0) {92 error("bad format");93 return;94 }9596 if (bintype != -1 && bintype != t) {97 error("not compatible object file");98 return;99 }100 bintype = t;101102 if ((obj = newobj(t)) == NULL) {103 error(strerror(errno));104 return;105 }106107 if (readobj(obj, fp) < 0) {108 error(strerror(errno));109 goto delete;110 }111112 if (inlib && !is_needed(obj))113 goto delete;114115 for (i = 0; getsec(obj, &i, &sec); i++)116 newsec(&sec, obj);117118 for ( i = 0; getsym(obj, &i, &sym); i++)119 newsym(&sym, obj);120121 obj->next = last;122 last = obj;123 if (!objhead)124 objhead = obj;125126 return;127128 delete:129 delobj(obj);130 return;131}132133static void134scanindex(FILE *fp)135{136 int t, added;137 long n, i, *offs;138 char **names;139 Symbol *sym;140141 if (getindex(bintype, &n, &names, &offs, fp) < 0) {142 error("corrupted index");143 return;144 }145146 for (added = 0; moreundef(); added = 0) {147 for (i = 0; i < n; i++) {148 if (!hasref(names[i]))149 continue;150151 if (fseek(fp, offs[i], SEEK_SET) == EOF) {152 error(strerror(errno));153 goto clean;154 }155156 load(fp, OUTLIB);157 added = 1;158 }159160 if (!added)161 break;162 }163clean:164 for (i = 0; i < n; i++)165 free(names[i]);166 free(names);167 free(offs);168}169170void171scanlib(FILE *fp)172{173 long cur, off;174 char memb[SARNAM+1];175176 if (bintype == -1) {177 error("an object file is needed before any library");178 return;179 }180181 cur = ftell(fp);182 if ((off = armember(fp, memb, NULL)) < 0)183 goto corrupted;184185 if (strcmp(memb, "/") == 0 || strcmp(memb, "__.SYMDEF") == 0) {186 scanindex(fp);187 return;188 }189190 fseek(fp, cur, SEEK_SET);191 for (;;) {192 cur = ftell(fp);193 off = armember(fp, memb, NULL);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 }209210corrupted:211 error(strerror(errno));212 error("library corrupted");213}214215static FILE *216openfile(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];223224 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 }231232 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);238239 filename = buffer;240 if ((fp = fopen(buffer, "rb")) != NULL)241 return fp;242243 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] = '/';250251 if ((fp = fopen(libname, "rb")) != NULL)252 return fp;253 }254255 error("not found");256 return NULL;257}258259static void260process(char *name)261{262 int t;263 FILE *fp;264265 if ((fp = openfile(name)) == NULL)266 return;267268 if (archive(fp))269 scanlib(fp);270 else271 load(fp, OUTLIB);272273 fclose(fp);274}275276/*277 * Get the list of object files that are going to be linked278 */279void280pass1(int argc, char *argv[])281{282 char **av, *ap;283284 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 }300301 if (moreundef()) {302 listundef();303 exit(EXIT_FAILURE);304 }305}