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 }