scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | 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 }