LEFT | RIGHT |
1 // Inferno utils/6l/span.c | 1 // Inferno utils/6l/span.c |
2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c | 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c |
3 // | 3 // |
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. | 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. |
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) | 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) |
6 // Portions Copyright © 1997-1999 Vita Nuova Limited | 6 // Portions Copyright © 1997-1999 Vita Nuova Limited |
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) | 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) |
8 // Portions Copyright © 2004,2006 Bruce Ellis | 8 // Portions Copyright © 2004,2006 Bruce Ellis |
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) | 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) |
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others | 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 LPUT(addr); | 75 LPUT(addr); |
76 LPUT(size); | 76 LPUT(size); |
77 cput(info); | 77 cput(info); |
78 cput(other); | 78 cput(other); |
79 WPUT(shndx); | 79 WPUT(shndx); |
80 symsize += ELF32SYMSIZE; | 80 symsize += ELF32SYMSIZE; |
81 break; | 81 break; |
82 } | 82 } |
83 } | 83 } |
84 | 84 |
| 85 static int numelfsym = 1; // 0 is reserved |
| 86 static int elfbind; |
| 87 |
85 static void | 88 static void |
86 putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) | 89 putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) |
87 { | 90 { |
88 » int bind, type, shndx, off; | 91 » int bind, type, off; |
| 92 » Sym *xo; |
89 | 93 |
90 USED(go); | 94 USED(go); |
91 switch(t) { | 95 switch(t) { |
92 default: | 96 default: |
93 return; | 97 return; |
94 case 'T': | 98 case 'T': |
95 type = STT_FUNC; | 99 type = STT_FUNC; |
96 shndx = elftextsh + 0; | |
97 break; | 100 break; |
98 case 'D': | 101 case 'D': |
99 type = STT_OBJECT; | 102 type = STT_OBJECT; |
100 if((x->type&SMASK) == SRODATA) | |
101 shndx = elftextsh + 1; | |
102 else | |
103 shndx = elftextsh + 2; | |
104 break; | 103 break; |
105 case 'B': | 104 case 'B': |
106 type = STT_OBJECT; | 105 type = STT_OBJECT; |
107 » » shndx = elftextsh + 3; | 106 » » break; |
108 » » break; | 107 » } |
109 » } | 108 » xo = x; |
110 » // TODO(minux): we need to place all STB_LOCAL precede all STB_GLOBAL an
d | 109 » while(xo->outer != nil) |
111 » // STB_WEAK symbols in the symbol table | 110 » » xo = xo->outer; |
| 111 » if(xo->sect == nil) { |
| 112 » » cursym = x; |
| 113 » » diag("missing section in putelfsym"); |
| 114 » » return; |
| 115 » } |
| 116 » if(xo->sect->elfsect == nil) { |
| 117 » » cursym = x; |
| 118 » » diag("missing ELF section in putelfsym"); |
| 119 » » return; |
| 120 » } |
| 121 |
| 122 » // One pass for each binding: STB_LOCAL, STB_GLOBAL, |
| 123 » // maybe one day STB_WEAK. |
112 bind = (ver || (x->type & SHIDDEN)) ? STB_LOCAL : STB_GLOBAL; | 124 bind = (ver || (x->type & SHIDDEN)) ? STB_LOCAL : STB_GLOBAL; |
| 125 if(bind != elfbind) |
| 126 return; |
| 127 |
113 off = putelfstr(s); | 128 off = putelfstr(s); |
114 » putelfsyment(off, addr, size, (bind<<4)|(type&0xf), shndx, (x->type & SH
IDDEN) ? 2 : 0); | 129 » putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->s
hnum, (x->type & SHIDDEN) ? 2 : 0); |
| 130 » x->elfsym = numelfsym++; |
115 } | 131 } |
116 | 132 |
117 void | 133 void |
118 asmelfsym(void) | 134 asmelfsym(void) |
119 { | 135 { |
120 // the first symbol entry is reserved | 136 // the first symbol entry is reserved |
121 putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0); | 137 putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0); |
| 138 |
| 139 elfbind = STB_LOCAL; |
| 140 genasmsym(putelfsym); |
| 141 |
| 142 elfbind = STB_GLOBAL; |
| 143 elfglobalsymndx = numelfsym; |
122 genasmsym(putelfsym); | 144 genasmsym(putelfsym); |
123 } | 145 } |
124 | 146 |
125 static void | 147 static void |
126 putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) | 148 putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) |
127 { | 149 { |
128 int i, l; | 150 int i, l; |
129 | 151 |
130 USED(go); | 152 USED(go); |
131 USED(ver); | 153 USED(ver); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 symgrow(symt, symt->size+1); | 214 symgrow(symt, symt->size+1); |
193 p = symt->p + symt->size; | 215 p = symt->p + symt->size; |
194 *p = b; | 216 *p = b; |
195 symt->size++; | 217 symt->size++; |
196 } | 218 } |
197 | 219 |
198 static void | 220 static void |
199 slputb(int32 v) | 221 slputb(int32 v) |
200 { | 222 { |
201 uchar *p; | 223 uchar *p; |
202 » | 224 |
203 symgrow(symt, symt->size+4); | 225 symgrow(symt, symt->size+4); |
204 p = symt->p + symt->size; | 226 p = symt->p + symt->size; |
205 *p++ = v>>24; | 227 *p++ = v>>24; |
206 *p++ = v>>16; | 228 *p++ = v>>16; |
207 *p++ = v>>8; | 229 *p++ = v>>8; |
208 *p = v; | 230 *p = v; |
209 symt->size += 4; | 231 symt->size += 4; |
210 } | 232 } |
| 233 |
| 234 static void |
| 235 slputl(int32 v) |
| 236 { |
| 237 uchar *p; |
| 238 |
| 239 symgrow(symt, symt->size+4); |
| 240 p = symt->p + symt->size; |
| 241 *p++ = v; |
| 242 *p++ = v>>8; |
| 243 *p++ = v>>16; |
| 244 *p = v>>24; |
| 245 symt->size += 4; |
| 246 } |
| 247 |
| 248 static void (*slput)(int32); |
211 | 249 |
212 void | 250 void |
213 wputl(ushort w) | 251 wputl(ushort w) |
214 { | 252 { |
215 cput(w); | 253 cput(w); |
216 cput(w>>8); | 254 cput(w>>8); |
217 } | 255 } |
218 | 256 |
219 void | 257 void |
220 wputb(ushort w) | 258 wputb(ushort w) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 Reloc *rel; | 300 Reloc *rel; |
263 | 301 |
264 USED(size); | 302 USED(size); |
265 if(t == 'f') | 303 if(t == 'f') |
266 name++; | 304 name++; |
267 l = 4; | 305 l = 4; |
268 // if(!debug['8']) | 306 // if(!debug['8']) |
269 // l = 8; | 307 // l = 8; |
270 if(s != nil) { | 308 if(s != nil) { |
271 rel = addrel(symt); | 309 rel = addrel(symt); |
272 » » rel->siz = l + Rbig; | 310 » » rel->siz = l; |
273 rel->sym = s; | 311 rel->sym = s; |
274 rel->type = D_ADDR; | 312 rel->type = D_ADDR; |
275 rel->off = symt->size; | 313 rel->off = symt->size; |
276 v = 0; | 314 v = 0; |
277 » }»······ | 315 » } |
278 » if(l == 8) | 316 |
279 » » slputb(v>>32); | 317 » if(l == 8) { |
280 » slputb(v); | 318 » » if(slput == slputl) { |
| 319 » » » slputl(v); |
| 320 » » » slputl(v>>32); |
| 321 » » } else { |
| 322 » » » slputb(v>>32); |
| 323 » » » slputb(v); |
| 324 » » } |
| 325 » } else |
| 326 » » slput(v); |
| 327 |
281 if(ver) | 328 if(ver) |
282 t += 'a' - 'A'; | 329 t += 'a' - 'A'; |
283 scput(t+0x80); /* 0x80 is variable length */ | 330 scput(t+0x80); /* 0x80 is variable length */ |
284 | 331 |
285 if(t == 'Z' || t == 'z') { | 332 if(t == 'Z' || t == 'z') { |
286 scput(name[0]); | 333 scput(name[0]); |
287 for(i=1; name[i] != 0 || name[i+1] != 0; i += 2) { | 334 for(i=1; name[i] != 0 || name[i+1] != 0; i += 2) { |
288 scput(name[i]); | 335 scput(name[i]); |
289 scput(name[i+1]); | 336 scput(name[i+1]); |
290 } | 337 } |
291 scput(0); | 338 scput(0); |
292 scput(0); | 339 scput(0); |
293 } | 340 } |
294 else { | 341 else { |
295 for(i=0; name[i]; i++) | 342 for(i=0; name[i]; i++) |
296 scput(name[i]); | 343 scput(name[i]); |
297 scput(0); | 344 scput(0); |
298 } | 345 } |
299 if(typ) { | 346 if(typ) { |
300 if(!typ->reachable) | 347 if(!typ->reachable) |
301 diag("unreachable type %s", typ->name); | 348 diag("unreachable type %s", typ->name); |
302 rel = addrel(symt); | 349 rel = addrel(symt); |
303 rel->siz = l; | 350 rel->siz = l; |
304 rel->sym = typ; | 351 rel->sym = typ; |
305 rel->type = D_ADDR; | 352 rel->type = D_ADDR; |
306 rel->off = symt->size; | 353 rel->off = symt->size; |
307 } | 354 } |
308 if(l == 8) | 355 if(l == 8) |
309 » » slputb(0); | 356 » » slput(0); |
310 » slputb(0); | 357 » slput(0); |
311 | 358 |
312 if(debug['n']) { | 359 if(debug['n']) { |
313 if(t == 'z' || t == 'Z') { | 360 if(t == 'z' || t == 'Z') { |
314 Bprint(&bso, "%c %.8llux ", t, v); | 361 Bprint(&bso, "%c %.8llux ", t, v); |
315 for(i=1; name[i] != 0 || name[i+1] != 0; i+=2) { | 362 for(i=1; name[i] != 0 || name[i+1] != 0; i+=2) { |
316 f = ((name[i]&0xff) << 8) | (name[i+1]&0xff); | 363 f = ((name[i]&0xff) << 8) | (name[i+1]&0xff); |
317 Bprint(&bso, "/%x", f); | 364 Bprint(&bso, "/%x", f); |
318 } | 365 } |
319 Bprint(&bso, "\n"); | 366 Bprint(&bso, "\n"); |
320 return; | 367 return; |
321 } | 368 } |
322 if(ver) | 369 if(ver) |
323 Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s->name, ve
r, typ ? typ->name : ""); | 370 Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s->name, ve
r, typ ? typ->name : ""); |
324 else | 371 else |
325 Bprint(&bso, "%c %.8llux %s %s\n", t, v, s->name, typ ?
typ->name : ""); | 372 Bprint(&bso, "%c %.8llux %s %s\n", t, v, s->name, typ ?
typ->name : ""); |
326 } | 373 } |
327 } | 374 } |
328 | 375 |
329 void | 376 void |
330 symtab(void) | 377 symtab(void) |
331 { | 378 { |
332 » Sym *s; | 379 » Sym *s, *symtype, *symtypelink, *symgostring; |
333 | |
334 dosymtype(); | 380 dosymtype(); |
335 | 381 |
336 // Define these so that they'll get put into the symbol table. | 382 // Define these so that they'll get put into the symbol table. |
337 // data.c:/^address will provide the actual values. | 383 // data.c:/^address will provide the actual values. |
338 xdefine("text", STEXT, 0); | 384 xdefine("text", STEXT, 0); |
339 xdefine("etext", STEXT, 0); | 385 xdefine("etext", STEXT, 0); |
340 xdefine("typelink", SRODATA, 0); | 386 xdefine("typelink", SRODATA, 0); |
341 xdefine("etypelink", SRODATA, 0); | 387 xdefine("etypelink", SRODATA, 0); |
342 xdefine("rodata", SRODATA, 0); | 388 xdefine("rodata", SRODATA, 0); |
343 xdefine("erodata", SRODATA, 0); | 389 xdefine("erodata", SRODATA, 0); |
344 » if (debug['U']) { | 390 » xdefine("reloffset", SRODATA, 0); |
| 391 » if(flag_shared) { |
345 xdefine("datarelro", SDATARELRO, 0); | 392 xdefine("datarelro", SDATARELRO, 0); |
346 xdefine("edatarelro", SDATARELRO, 0); | 393 xdefine("edatarelro", SDATARELRO, 0); |
347 } | 394 } |
348 xdefine("gcdata", SGCDATA, 0); | 395 xdefine("gcdata", SGCDATA, 0); |
349 xdefine("egcdata", SGCDATA, 0); | 396 xdefine("egcdata", SGCDATA, 0); |
350 xdefine("gcbss", SGCBSS, 0); | 397 xdefine("gcbss", SGCBSS, 0); |
351 xdefine("egcbss", SGCBSS, 0); | 398 xdefine("egcbss", SGCBSS, 0); |
352 xdefine("noptrdata", SNOPTRDATA, 0); | 399 xdefine("noptrdata", SNOPTRDATA, 0); |
353 xdefine("enoptrdata", SNOPTRDATA, 0); | 400 xdefine("enoptrdata", SNOPTRDATA, 0); |
354 xdefine("data", SDATA, 0); | 401 xdefine("data", SDATA, 0); |
355 xdefine("edata", SDATA, 0); | 402 xdefine("edata", SDATA, 0); |
356 xdefine("bss", SBSS, 0); | 403 xdefine("bss", SBSS, 0); |
357 xdefine("ebss", SBSS, 0); | 404 xdefine("ebss", SBSS, 0); |
358 xdefine("noptrbss", SNOPTRBSS, 0); | 405 xdefine("noptrbss", SNOPTRBSS, 0); |
359 xdefine("enoptrbss", SNOPTRBSS, 0); | 406 xdefine("enoptrbss", SNOPTRBSS, 0); |
360 xdefine("end", SBSS, 0); | 407 xdefine("end", SBSS, 0); |
361 xdefine("epclntab", SRODATA, 0); | 408 xdefine("epclntab", SRODATA, 0); |
362 xdefine("esymtab", SRODATA, 0); | 409 xdefine("esymtab", SRODATA, 0); |
363 » | 410 |
364 // pseudo-symbols to mark locations of type, string, and go string data. | 411 // pseudo-symbols to mark locations of type, string, and go string data. |
365 s = lookup("type.*", 0); | 412 s = lookup("type.*", 0); |
366 s->type = STYPE; | 413 s->type = STYPE; |
367 s->size = 0; | 414 s->size = 0; |
368 s->reachable = 1; | 415 s->reachable = 1; |
| 416 symtype = s; |
369 | 417 |
370 s = lookup("go.string.*", 0); | 418 s = lookup("go.string.*", 0); |
371 s->type = SGOSTRING; | 419 s->type = SGOSTRING; |
372 s->size = 0; | 420 s->size = 0; |
373 s->reachable = 1; | 421 s->reachable = 1; |
| 422 symgostring = s; |
| 423 ········ |
| 424 symtypelink = lookup("typelink", 0); |
374 | 425 |
375 symt = lookup("symtab", 0); | 426 symt = lookup("symtab", 0); |
376 symt->type = SSYMTAB; | 427 symt->type = SSYMTAB; |
377 symt->size = 0; | 428 symt->size = 0; |
378 symt->reachable = 1; | 429 symt->reachable = 1; |
379 » | 430 |
380 // assign specific types so that they sort together. | 431 // assign specific types so that they sort together. |
381 // within a type they sort by size, so the .* symbols | 432 // within a type they sort by size, so the .* symbols |
382 // just defined above will be first. | 433 // just defined above will be first. |
383 // hide the specific symbols. | 434 // hide the specific symbols. |
384 for(s = allsym; s != S; s = s->allsym) { | 435 for(s = allsym; s != S; s = s->allsym) { |
385 if(!s->reachable || s->special || s->type != SRODATA) | 436 if(!s->reachable || s->special || s->type != SRODATA) |
386 continue; | 437 continue; |
387 if(strncmp(s->name, "type.", 5) == 0) { | 438 if(strncmp(s->name, "type.", 5) == 0) { |
388 s->type = STYPE; | 439 s->type = STYPE; |
389 s->hide = 1; | 440 s->hide = 1; |
| 441 s->outer = symtype; |
390 } | 442 } |
391 if(strncmp(s->name, "go.typelink.", 12) == 0) { | 443 if(strncmp(s->name, "go.typelink.", 12) == 0) { |
392 s->type = STYPELINK; | 444 s->type = STYPELINK; |
393 s->hide = 1; | 445 s->hide = 1; |
| 446 s->outer = symtypelink; |
394 } | 447 } |
395 if(strncmp(s->name, "go.string.", 10) == 0) { | 448 if(strncmp(s->name, "go.string.", 10) == 0) { |
396 s->type = SGOSTRING; | 449 s->type = SGOSTRING; |
397 s->hide = 1; | 450 s->hide = 1; |
| 451 s->outer = symgostring; |
398 } | 452 } |
399 } | 453 } |
400 | 454 |
401 if(debug['s']) | 455 if(debug['s']) |
402 return; | 456 return; |
| 457 |
| 458 switch(thechar) { |
| 459 default: |
| 460 diag("unknown architecture %c", thechar); |
| 461 errorexit(); |
| 462 case '5': |
| 463 case '6': |
| 464 case '8': |
| 465 // magic entry to denote little-endian symbol table |
| 466 slputl(0xfffffffe); |
| 467 scput(0); |
| 468 scput(0); |
| 469 slput = slputl; |
| 470 break; |
| 471 case 'v': |
| 472 // big-endian (in case one comes along) |
| 473 slput = slputb; |
| 474 break; |
| 475 } |
| 476 |
403 genasmsym(putsymb); | 477 genasmsym(putsymb); |
404 } | 478 } |
LEFT | RIGHT |