pass1.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
---
pass1.c (4729B)
---
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, NULL)) < 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, 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 }
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 }