|
|
1.1 root 1: /*
2: * obj.c
3: * routines universal to all object files
4: */
5: #include <u.h>
6: #include <libc.h>
7: #include <bio.h>
8: #include <ar.h>
9: #include <mach.h>
10: #include "obj.h"
11:
12: #define islocal(t) ((t)=='a' || (t)=='p')
13:
14: enum
15: {
16: NNAMES = 50,
17: MAXIS = 8, /* max length to determine if a file is a .? file */
18: MAXOFF = 0x7fffffff, /* larger than any possible local offset */
19: NHASH = 1024, /* must be power of two */
20: HASHMUL = 79L,
21: };
22:
23: int _is2(char*), /* in [$OS].c */
24: _is6(char*),
25: _is8(char*),
26: _isk(char*),
27: _isv(char*),
28: _isx(char*),
29: _read2(Biobuf*, Prog*),
30: _read6(Biobuf*, Prog*),
31: _read8(Biobuf*, Prog*),
32: _readk(Biobuf*, Prog*),
33: _readv(Biobuf*, Prog*),
34: _readx(Biobuf*, Prog*);
35:
36: typedef struct Obj Obj;
37: typedef struct Symtab Symtab;
38:
39: struct Obj /* functions to handle each intermediate (.$O) file */
40: {
41: char *name; /* name of each $O file */
42: int (*is)(char*); /* test for each type of $O file */
43: int (*read)(Biobuf*, Prog*); /* read for each type of $O file*/
44: };
45:
46: static Obj obj[] =
47: { /* functions to identify and parse each type of obj */
48: [Obj68020] "68020 .2", _is2, _read2,
49: [ObjSparc] "sparc .k", _isk, _readk,
50: [ObjMips] "mips .v", _isv, _readv,
51: [Obj386] "386 .8", _is8, _read8,
52: [Obj960] "960 .6", _is6, _read6,
53: [Obj3210] "3210 .x", _isx, _readx,
54: [Maxobjtype] 0, 0
55: };
56:
57: struct Symtab
58: {
59: struct Sym s;
60: struct Symtab *next;
61: };
62:
63: static Symtab *hash[NHASH];
64: static Sym *names[NNAMES]; /* working set of active names */
65:
66: static int processprog(Prog*,int); /* decode each symbol reference */
67: static void objreset(void);
68: static void objlookup(int, char *, int );
69: static void objupdate(int, int);
70:
71: int
72: objtype(Biobuf *bp, char **name)
73: {
74: int i;
75: char buf[MAXIS];
76:
77: if(Bread(bp, buf, MAXIS) < MAXIS)
78: return -1;
79: Bseek(bp, -MAXIS, 1);
80: for (i = 0; obj[i].is; i++) {
81: if ((*obj[i].is)(buf)) {
82: if (name)
83: *name = obj[i].name;
84: return i;
85: }
86: }
87: return -1;
88: }
89:
90: int
91: isar(Biobuf *bp)
92: {
93: int n;
94: char magbuf[SARMAG];
95:
96: n = Bread(bp, magbuf, SARMAG);
97: if(n == SARMAG && strncmp(magbuf, ARMAG, SARMAG) == 0)
98: return 1;
99: return 0;
100: }
101:
102: /*
103: * determine what kind of object file this is and process it.
104: * return whether or not this was a recognized intermediate file.
105: */
106: int
107: readobj(Biobuf *bp, int objtype)
108: {
109: Prog p;
110:
111: if (objtype < 0 || objtype >= Maxobjtype)
112: return 1;
113: objreset();
114: while ((*obj[objtype].read)(bp, &p))
115: if (!processprog(&p, 1))
116: return 0;
117: return 1;
118: }
119:
120: int
121: readar(Biobuf *bp, int objtype, int end, int doautos)
122: {
123: Prog p;
124:
125: if (objtype < 0 || objtype >= Maxobjtype)
126: return 1;
127: objreset();
128: while ((*obj[objtype].read)(bp, &p) && BOFFSET(bp) < end)
129: if (!processprog(&p, doautos))
130: return 0;
131: return 1;
132: }
133:
134: /*
135: * decode a symbol reference or definition
136: */
137: static int
138: processprog(Prog *p, int doautos)
139: {
140: if(p->kind == aNone)
141: return 1;
142: if(p->sym < 0 || p->sym >= NNAMES)
143: return 0;
144: switch(p->kind)
145: {
146: case aName:
147: if (!doautos)
148: if(p->type != 'U' && p->type != 'b')
149: break;
150: objlookup(p->sym, p->id, p->type);
151: break;
152: case aText:
153: objupdate(p->sym, 'T');
154: break;
155: case aData:
156: objupdate(p->sym, 'D');
157: break;
158: default:
159: break;
160: }
161: return 1;
162: }
163:
164: /*
165: * find the entry for s in the symbol array.
166: * make a new entry if it is not already there.
167: */
168: static void
169: objlookup(int id, char *name, int type)
170: {
171: long h;
172: char *cp;
173: Sym *s;
174: Symtab *sp;
175:
176: s = names[id];
177: if(s && strcmp(s->name, name) == 0) {
178: s->type = type;
179: return;
180: }
181:
182: h = *name;
183: for(cp = name+1; *cp; h += *cp++)
184: h *= HASHMUL;
185: if(h < 0)
186: h = ~h;
187: h &= (NHASH-1);
188: if (type == 'U' || type == 'b' || islocal(type)) {
189: for(sp = hash[h]; sp; sp = sp->next)
190: if(strcmp(sp->s.name, name) == 0) {
191: switch(sp->s.type) {
192: case 'T':
193: case 'D':
194: case 'U':
195: if (type == 'U') {
196: names[id] = &sp->s;
197: return;
198: }
199: break;
200: case 't':
201: case 'd':
202: case 'b':
203: if (type == 'b') {
204: names[id] = &sp->s;
205: return;
206: }
207: break;
208: case 'a':
209: case 'p':
210: if (islocal(type)) {
211: names[id] = &sp->s;
212: return;
213: }
214: break;
215: default:
216: break;
217: }
218: }
219: }
220: sp = malloc(sizeof(Symtab));
221: sp->s.name = name;
222: sp->s.type = type;
223: sp->s.value = islocal(type) ? MAXOFF : 0;
224: names[id] = &sp->s;
225: sp->next = hash[h];
226: hash[h] = sp;
227: return;
228: }
229: /*
230: * traverse the symbol lists
231: */
232: void
233: objtraverse(void (*fn)(Sym*, void*), void *pointer)
234: {
235: int i;
236: Symtab *s;
237:
238: for(i = 0; i < NHASH; i++)
239: for(s = hash[i]; s; s = s->next)
240: (*fn)(&s->s, pointer);
241: }
242:
243: /*
244: * update the offset information for a 'a' or 'p' symbol in an intermediate file
245: */
246: void
247: _offset(int id, long off)
248: {
249: Sym *s;
250:
251: s = names[id];
252: if (s && s->name[0] && islocal(s->type) && s->value > off)
253: s->value = off;
254: }
255:
256: /*
257: * update the type of a global text or data symbol
258: */
259: static void
260: objupdate(int id, int type)
261: {
262: Sym *s;
263:
264: s = names[id];
265: if (s && s->name[0])
266: if (s->type == 'U')
267: s->type = type;
268: else if (s->type == 'b')
269: s->type = tolower(type);
270: }
271:
272: /*
273: * look for the next file in an archive
274: */
275: int
276: nextar(Biobuf *bp, int offset, char *buf)
277: {
278: struct ar_hdr a;
279: int i, r;
280: long arsize;
281:
282: if (offset&01)
283: offset++;
284: Bseek(bp, offset, 0);
285: r = Bread(bp, &a, SAR_HDR);
286: if(r != SAR_HDR)
287: return 0;
288: if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag)))
289: return -1;
290: for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++)
291: buf[i] = a.name[i];
292: buf[i] = 0;
293: arsize = atol(a.size);
294: if (arsize&1)
295: arsize++;
296: return arsize + SAR_HDR;
297: }
298:
299: static void
300: objreset(void)
301: {
302: int i;
303: Symtab *s, *n;
304:
305: for(i = 0; i < NHASH; i++) {
306: for(s = hash[i]; s; s = n) {
307: n = s->next;
308: free(s->s.name);
309: free(s);
310: }
311: hash[i] = 0;
312: }
313: memset(names, 0, sizeof names);
314: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.