changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/libmach/obj.c

changeset 7186: 4dd5e2428c1d
parent: 05fff33231d5
author: cinap_lenrek@felloff.net
date: Fri, 03 May 2019 21:00:17 +0200
permissions: -rw-r--r--
description: libmach: initial arm64 support
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  _is5(char*),
25  _is6(char*),
26  _is7(char*),
27  _is8(char*),
28  _is9(char*),
29  _isk(char*),
30  _isq(char*),
31  _isv(char*),
32  _isu(char*),
33  _read2(Biobuf*, Prog*),
34  _read5(Biobuf*, Prog*),
35  _read6(Biobuf*, Prog*),
36  _read7(Biobuf*, Prog*),
37  _read8(Biobuf*, Prog*),
38  _read9(Biobuf*, Prog*),
39  _readk(Biobuf*, Prog*),
40  _readq(Biobuf*, Prog*),
41  _readv(Biobuf*, Prog*),
42  _readu(Biobuf*, Prog*);
43 
44 typedef struct Obj Obj;
45 typedef struct Symtab Symtab;
46 
47 struct Obj /* functions to handle each intermediate (.$O) file */
48 {
49  char *name; /* name of each $O file */
50  int (*is)(char*); /* test for each type of $O file */
51  int (*read)(Biobuf*, Prog*); /* read for each type of $O file*/
52 };
53 
54 static Obj obj[] =
55 { /* functions to identify and parse each type of obj */
56  [Obj68020] "68020 .2", _is2, _read2,
57  [ObjAmd64] "amd64 .6", _is6, _read6,
58  [ObjArm] "arm .5", _is5, _read5,
59  [ObjArm64] "arm64 .7", _is7, _read7,
60  [Obj386] "386 .8", _is8, _read8,
61  [ObjSparc] "sparc .k", _isk, _readk,
62  [ObjPower] "power .q", _isq, _readq,
63  [ObjMips] "mips .v", _isv, _readv,
64  [ObjSparc64] "sparc64 .u", _isu, _readu,
65  [ObjPower64] "power64 .9", _is9, _read9,
66  [Maxobjtype] 0, 0
67 };
68 
69 struct Symtab
70 {
71  struct Sym s;
72  struct Symtab *next;
73 };
74 
75 static Symtab *hash[NHASH];
76 static Sym *names[NNAMES]; /* working set of active names */
77 
78 static int processprog(Prog*,int); /* decode each symbol reference */
79 static void objreset(void);
80 static void objlookup(int, char *, int, uint);
81 static void objupdate(int, int);
82 
83 int
84 objtype(Biobuf *bp, char **name)
85 {
86  int i;
87  char buf[MAXIS];
88 
89  if(Bread(bp, buf, MAXIS) < MAXIS)
90  return -1;
91  Bseek(bp, -MAXIS, 1);
92  for (i = 0; i < Maxobjtype; i++) {
93  if (obj[i].is && (*obj[i].is)(buf)) {
94  if (name)
95  *name = obj[i].name;
96  return i;
97  }
98  }
99  return -1;
100 }
101 
102 int
103 isar(Biobuf *bp)
104 {
105  int n;
106  char magbuf[SARMAG];
107 
108  n = Bread(bp, magbuf, SARMAG);
109  if(n == SARMAG && strncmp(magbuf, ARMAG, SARMAG) == 0)
110  return 1;
111  return 0;
112 }
113 
114 /*
115  * determine what kind of object file this is and process it.
116  * return whether or not this was a recognized intermediate file.
117  */
118 int
119 readobj(Biobuf *bp, int objtype)
120 {
121  Prog p;
122 
123  if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0)
124  return 1;
125  objreset();
126  while ((*obj[objtype].read)(bp, &p))
127  if (!processprog(&p, 1))
128  return 0;
129  return 1;
130 }
131 
132 int
133 readar(Biobuf *bp, int objtype, vlong end, int doautos)
134 {
135  Prog p;
136 
137  if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0)
138  return 1;
139  objreset();
140  while ((*obj[objtype].read)(bp, &p) && Boffset(bp) < end)
141  if (!processprog(&p, doautos))
142  return 0;
143  return 1;
144 }
145 
146 /*
147  * decode a symbol reference or definition
148  */
149 static int
150 processprog(Prog *p, int doautos)
151 {
152  if(p->kind == aNone)
153  return 1;
154  if(p->sym < 0 || p->sym >= NNAMES)
155  return 0;
156  switch(p->kind)
157  {
158  case aName:
159  if (!doautos)
160  if(p->type != 'U' && p->type != 'b')
161  break;
162  objlookup(p->sym, p->id, p->type, p->sig);
163  break;
164  case aText:
165  objupdate(p->sym, 'T');
166  break;
167  case aData:
168  objupdate(p->sym, 'D');
169  break;
170  default:
171  break;
172  }
173  return 1;
174 }
175 
176 /*
177  * find the entry for s in the symbol array.
178  * make a new entry if it is not already there.
179  */
180 static void
181 objlookup(int id, char *name, int type, uint sig)
182 {
183  long h;
184  char *cp;
185  Sym *s;
186  Symtab *sp;
187 
188  s = names[id];
189  if(s && strcmp(s->name, name) == 0) {
190  s->type = type;
191  s->sig = sig;
192  return;
193  }
194 
195  h = *name;
196  for(cp = name+1; *cp; h += *cp++)
197  h *= HASHMUL;
198  if(h < 0)
199  h = ~h;
200  h &= (NHASH-1);
201  if (type == 'U' || type == 'b' || islocal(type)) {
202  for(sp = hash[h]; sp; sp = sp->next)
203  if(strcmp(sp->s.name, name) == 0) {
204  switch(sp->s.type) {
205  case 'T':
206  case 'D':
207  case 'U':
208  if (type == 'U') {
209  names[id] = &sp->s;
210  return;
211  }
212  break;
213  case 't':
214  case 'd':
215  case 'b':
216  if (type == 'b') {
217  names[id] = &sp->s;
218  return;
219  }
220  break;
221  case 'a':
222  case 'p':
223  if (islocal(type)) {
224  names[id] = &sp->s;
225  return;
226  }
227  break;
228  default:
229  break;
230  }
231  }
232  }
233  sp = malloc(sizeof(Symtab));
234  sp->s.name = name;
235  sp->s.type = type;
236  sp->s.sig = sig;
237  sp->s.value = islocal(type) ? MAXOFF : 0;
238  names[id] = &sp->s;
239  sp->next = hash[h];
240  hash[h] = sp;
241  return;
242 }
243 /*
244  * traverse the symbol lists
245  */
246 void
247 objtraverse(void (*fn)(Sym*, void*), void *pointer)
248 {
249  int i;
250  Symtab *s;
251 
252  for(i = 0; i < NHASH; i++)
253  for(s = hash[i]; s; s = s->next)
254  (*fn)(&s->s, pointer);
255 }
256 
257 /*
258  * update the offset information for a 'a' or 'p' symbol in an intermediate file
259  */
260 void
261 _offset(int id, vlong off)
262 {
263  Sym *s;
264 
265  s = names[id];
266  if (s && s->name[0] && islocal(s->type) && s->value > off)
267  s->value = off;
268 }
269 
270 /*
271  * update the type of a global text or data symbol
272  */
273 static void
274 objupdate(int id, int type)
275 {
276  Sym *s;
277 
278  s = names[id];
279  if (s && s->name[0])
280  if (s->type == 'U')
281  s->type = type;
282  else if (s->type == 'b')
283  s->type = tolower(type);
284 }
285 
286 /*
287  * look for the next file in an archive
288  */
289 int
290 nextar(Biobuf *bp, int offset, char *buf)
291 {
292  struct ar_hdr a;
293  int i, r;
294  long arsize;
295 
296  if (offset&01)
297  offset++;
298  Bseek(bp, offset, 0);
299  r = Bread(bp, &a, SAR_HDR);
300  if(r != SAR_HDR)
301  return 0;
302  if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag)))
303  return -1;
304  for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++)
305  buf[i] = a.name[i];
306  buf[i] = 0;
307  arsize = strtol(a.size, 0, 0);
308  if (arsize&1)
309  arsize++;
310  return arsize + SAR_HDR;
311 }
312 
313 static void
314 objreset(void)
315 {
316  int i;
317  Symtab *s, *n;
318 
319  for(i = 0; i < NHASH; i++) {
320  for(s = hash[i]; s; s = n) {
321  n = s->next;
322  free(s->s.name);
323  free(s);
324  }
325  hash[i] = 0;
326  }
327  memset(names, 0, sizeof names);
328 }