github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/ld/symtab.c (about) 1 // Inferno utils/6l/span.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Symbol table. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 #include "../ld/elf.h" 36 37 static int maxelfstr; 38 39 static int 40 putelfstr(char *s) 41 { 42 int off, n; 43 44 if(elfstrsize == 0 && s[0] != 0) { 45 // first entry must be empty string 46 putelfstr(""); 47 } 48 49 n = strlen(s)+1; 50 if(elfstrsize+n > maxelfstr) { 51 maxelfstr = 2*(elfstrsize+n+(1<<20)); 52 elfstrdat = realloc(elfstrdat, maxelfstr); 53 } 54 off = elfstrsize; 55 elfstrsize += n; 56 memmove(elfstrdat+off, s, n); 57 return off; 58 } 59 60 static void 61 putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other) 62 { 63 switch(thechar) { 64 case '6': 65 LPUT(off); 66 cput(info); 67 cput(other); 68 WPUT(shndx); 69 VPUT(addr); 70 VPUT(size); 71 symsize += ELF64SYMSIZE; 72 break; 73 default: 74 LPUT(off); 75 LPUT(addr); 76 LPUT(size); 77 cput(info); 78 cput(other); 79 WPUT(shndx); 80 symsize += ELF32SYMSIZE; 81 break; 82 } 83 } 84 85 static int numelfsym = 1; // 0 is reserved 86 static int elfbind; 87 88 static void 89 putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) 90 { 91 int bind, type, off; 92 Sym *xo; 93 94 USED(go); 95 switch(t) { 96 default: 97 return; 98 case 'T': 99 type = STT_FUNC; 100 break; 101 case 'D': 102 type = STT_OBJECT; 103 break; 104 case 'B': 105 type = STT_OBJECT; 106 break; 107 } 108 xo = x; 109 while(xo->outer != nil) 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. 124 bind = STB_GLOBAL; 125 if(ver || (x->type & SHIDDEN)) 126 bind = STB_LOCAL; 127 128 // In external linking mode, we have to invoke gcc with -rdynamic 129 // to get the exported symbols put into the dynamic symbol table. 130 // To avoid filling the dynamic table with lots of unnecessary symbols, 131 // mark all Go symbols local (not global) in the final executable. 132 if(linkmode == LinkExternal && !(x->cgoexport&CgoExportStatic)) 133 bind = STB_LOCAL; 134 135 if(bind != elfbind) 136 return; 137 138 off = putelfstr(s); 139 if(linkmode == LinkExternal) 140 addr -= xo->sect->vaddr; 141 putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->shnum, (x->type & SHIDDEN) ? 2 : 0); 142 x->elfsym = numelfsym++; 143 } 144 145 void 146 putelfsectionsym(Sym* s, int shndx) 147 { 148 putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_SECTION, shndx, 0); 149 s->elfsym = numelfsym++; 150 } 151 152 void 153 putelfsymshndx(vlong sympos, int shndx) 154 { 155 vlong here; 156 157 here = cpos(); 158 switch(thechar) { 159 case '6': 160 cseek(sympos+6); 161 break; 162 default: 163 cseek(sympos+14); 164 break; 165 } 166 WPUT(shndx); 167 cseek(here); 168 } 169 170 void 171 asmelfsym(void) 172 { 173 Sym *s; 174 175 // the first symbol entry is reserved 176 putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0); 177 178 dwarfaddelfsectionsyms(); 179 180 elfbind = STB_LOCAL; 181 genasmsym(putelfsym); 182 183 if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) { 184 s = lookup("runtime.m", 0); 185 if(s->sect == nil) { 186 cursym = nil; 187 diag("missing section for %s", s->name); 188 errorexit(); 189 } 190 putelfsyment(putelfstr(s->name), 0, PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0); 191 s->elfsym = numelfsym++; 192 193 s = lookup("runtime.g", 0); 194 if(s->sect == nil) { 195 cursym = nil; 196 diag("missing section for %s", s->name); 197 errorexit(); 198 } 199 putelfsyment(putelfstr(s->name), PtrSize, PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0); 200 s->elfsym = numelfsym++; 201 } 202 203 elfbind = STB_GLOBAL; 204 elfglobalsymndx = numelfsym; 205 genasmsym(putelfsym); 206 207 for(s=allsym; s!=S; s=s->allsym) { 208 if(s->type != SHOSTOBJ) 209 continue; 210 putelfsyment(putelfstr(s->name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0); 211 s->elfsym = numelfsym++; 212 } 213 } 214 215 static void 216 putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) 217 { 218 int i, l; 219 220 USED(go); 221 USED(ver); 222 USED(size); 223 USED(x); 224 switch(t) { 225 case 'T': 226 case 'L': 227 case 'D': 228 case 'B': 229 if(ver) 230 t += 'a' - 'A'; 231 case 'a': 232 case 'p': 233 case 'f': 234 case 'z': 235 case 'Z': 236 case 'm': 237 l = 4; 238 if(HEADTYPE == Hplan9x64 && !debug['8']) { 239 lputb(addr>>32); 240 l = 8; 241 } 242 lputb(addr); 243 cput(t+0x80); /* 0x80 is variable length */ 244 245 if(t == 'z' || t == 'Z') { 246 cput(s[0]); 247 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 248 cput(s[i]); 249 cput(s[i+1]); 250 } 251 cput(0); 252 cput(0); 253 i++; 254 } else { 255 /* skip the '<' in filenames */ 256 if(t == 'f') 257 s++; 258 for(i=0; s[i]; i++) 259 cput(s[i]); 260 cput(0); 261 } 262 symsize += l + 1 + i + 1; 263 break; 264 default: 265 return; 266 }; 267 } 268 269 void 270 asmplan9sym(void) 271 { 272 genasmsym(putplan9sym); 273 } 274 275 static Sym *symt; 276 277 static void 278 scput(int b) 279 { 280 uchar *p; 281 282 symgrow(symt, symt->size+1); 283 p = symt->p + symt->size; 284 *p = b; 285 symt->size++; 286 } 287 288 static void 289 slputb(int32 v) 290 { 291 uchar *p; 292 293 symgrow(symt, symt->size+4); 294 p = symt->p + symt->size; 295 *p++ = v>>24; 296 *p++ = v>>16; 297 *p++ = v>>8; 298 *p = v; 299 symt->size += 4; 300 } 301 302 static void 303 slputl(int32 v) 304 { 305 uchar *p; 306 307 symgrow(symt, symt->size+4); 308 p = symt->p + symt->size; 309 *p++ = v; 310 *p++ = v>>8; 311 *p++ = v>>16; 312 *p = v>>24; 313 symt->size += 4; 314 } 315 316 static void (*slput)(int32); 317 318 void 319 wputl(ushort w) 320 { 321 cput(w); 322 cput(w>>8); 323 } 324 325 void 326 wputb(ushort w) 327 { 328 cput(w>>8); 329 cput(w); 330 } 331 332 void 333 lputb(int32 l) 334 { 335 cput(l>>24); 336 cput(l>>16); 337 cput(l>>8); 338 cput(l); 339 } 340 341 void 342 lputl(int32 l) 343 { 344 cput(l); 345 cput(l>>8); 346 cput(l>>16); 347 cput(l>>24); 348 } 349 350 void 351 vputb(uint64 v) 352 { 353 lputb(v>>32); 354 lputb(v); 355 } 356 357 void 358 vputl(uint64 v) 359 { 360 lputl(v); 361 lputl(v >> 32); 362 } 363 364 // Emit symbol table entry. 365 // The table format is described at the top of ../../pkg/runtime/symtab.c. 366 void 367 putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ) 368 { 369 int i, f, c; 370 vlong v1; 371 Reloc *rel; 372 373 USED(size); 374 375 // type byte 376 if('A' <= t && t <= 'Z') 377 c = t - 'A' + (ver ? 26 : 0); 378 else if('a' <= t && t <= 'z') 379 c = t - 'a' + 26; 380 else { 381 diag("invalid symbol table type %c", t); 382 errorexit(); 383 return; 384 } 385 386 if(s != nil) 387 c |= 0x40; // wide value 388 if(typ != nil) 389 c |= 0x80; // has go type 390 scput(c); 391 392 // value 393 if(s != nil) { 394 // full width 395 rel = addrel(symt); 396 rel->siz = PtrSize; 397 rel->sym = s; 398 rel->type = D_ADDR; 399 rel->off = symt->size; 400 if(PtrSize == 8) 401 slput(0); 402 slput(0); 403 } else { 404 // varint 405 if(v < 0) { 406 diag("negative value in symbol table: %s %lld", name, v); 407 errorexit(); 408 } 409 v1 = v; 410 while(v1 >= 0x80) { 411 scput(v1 | 0x80); 412 v1 >>= 7; 413 } 414 scput(v1); 415 } 416 417 // go type if present 418 if(typ != nil) { 419 if(!typ->reachable) 420 diag("unreachable type %s", typ->name); 421 rel = addrel(symt); 422 rel->siz = PtrSize; 423 rel->sym = typ; 424 rel->type = D_ADDR; 425 rel->off = symt->size; 426 if(PtrSize == 8) 427 slput(0); 428 slput(0); 429 } 430 431 // name 432 if(t == 'f') 433 name++; 434 435 if(t == 'Z' || t == 'z') { 436 scput(name[0]); 437 for(i=1; name[i] != 0 || name[i+1] != 0; i += 2) { 438 scput(name[i]); 439 scput(name[i+1]); 440 } 441 scput(0); 442 scput(0); 443 } else { 444 for(i=0; name[i]; i++) 445 scput(name[i]); 446 scput(0); 447 } 448 449 if(debug['n']) { 450 if(t == 'z' || t == 'Z') { 451 Bprint(&bso, "%c %.8llux ", t, v); 452 for(i=1; name[i] != 0 || name[i+1] != 0; i+=2) { 453 f = ((name[i]&0xff) << 8) | (name[i+1]&0xff); 454 Bprint(&bso, "/%x", f); 455 } 456 Bprint(&bso, "\n"); 457 return; 458 } 459 if(ver) 460 Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, name, ver, typ ? typ->name : ""); 461 else 462 Bprint(&bso, "%c %.8llux %s %s\n", t, v, name, typ ? typ->name : ""); 463 } 464 } 465 466 void 467 symtab(void) 468 { 469 Sym *s, *symtype, *symtypelink, *symgostring; 470 dosymtype(); 471 472 // Define these so that they'll get put into the symbol table. 473 // data.c:/^address will provide the actual values. 474 xdefine("text", STEXT, 0); 475 xdefine("etext", STEXT, 0); 476 xdefine("typelink", SRODATA, 0); 477 xdefine("etypelink", SRODATA, 0); 478 xdefine("rodata", SRODATA, 0); 479 xdefine("erodata", SRODATA, 0); 480 if(flag_shared) { 481 xdefine("datarelro", SDATARELRO, 0); 482 xdefine("edatarelro", SDATARELRO, 0); 483 } 484 xdefine("egcdata", STYPE, 0); 485 xdefine("egcbss", STYPE, 0); 486 xdefine("noptrdata", SNOPTRDATA, 0); 487 xdefine("enoptrdata", SNOPTRDATA, 0); 488 xdefine("data", SDATA, 0); 489 xdefine("edata", SDATA, 0); 490 xdefine("bss", SBSS, 0); 491 xdefine("ebss", SBSS, 0); 492 xdefine("noptrbss", SNOPTRBSS, 0); 493 xdefine("enoptrbss", SNOPTRBSS, 0); 494 xdefine("end", SBSS, 0); 495 xdefine("epclntab", SRODATA, 0); 496 xdefine("esymtab", SRODATA, 0); 497 498 // pseudo-symbols to mark locations of type, string, and go string data. 499 s = lookup("type.*", 0); 500 s->type = STYPE; 501 s->size = 0; 502 s->reachable = 1; 503 symtype = s; 504 505 s = lookup("go.string.*", 0); 506 s->type = SGOSTRING; 507 s->size = 0; 508 s->reachable = 1; 509 symgostring = s; 510 511 symtypelink = lookup("typelink", 0); 512 513 symt = lookup("symtab", 0); 514 symt->type = SSYMTAB; 515 symt->size = 0; 516 symt->reachable = 1; 517 518 // assign specific types so that they sort together. 519 // within a type they sort by size, so the .* symbols 520 // just defined above will be first. 521 // hide the specific symbols. 522 for(s = allsym; s != S; s = s->allsym) { 523 if(!s->reachable || s->special || s->type != SRODATA) 524 continue; 525 if(strncmp(s->name, "type.", 5) == 0) { 526 s->type = STYPE; 527 s->hide = 1; 528 s->outer = symtype; 529 } 530 if(strncmp(s->name, "go.typelink.", 12) == 0) { 531 s->type = STYPELINK; 532 s->hide = 1; 533 s->outer = symtypelink; 534 } 535 if(strncmp(s->name, "go.string.", 10) == 0) { 536 s->type = SGOSTRING; 537 s->hide = 1; 538 s->outer = symgostring; 539 } 540 } 541 542 if(debug['s']) 543 return; 544 545 switch(thechar) { 546 default: 547 diag("unknown architecture %c", thechar); 548 errorexit(); 549 case '5': 550 case '6': 551 case '8': 552 // little-endian symbol table 553 slput = slputl; 554 break; 555 case 'v': 556 // big-endian symbol table 557 slput = slputb; 558 break; 559 } 560 // new symbol table header. 561 slput(0xfffffffd); 562 scput(0); 563 scput(0); 564 scput(0); 565 scput(PtrSize); 566 567 genasmsym(putsymb); 568 }