github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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.tlsgm", 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, 2*PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0); 191 s->elfsym = numelfsym++; 192 } 193 194 elfbind = STB_GLOBAL; 195 elfglobalsymndx = numelfsym; 196 genasmsym(putelfsym); 197 198 for(s=allsym; s!=S; s=s->allsym) { 199 if(s->type != SHOSTOBJ) 200 continue; 201 putelfsyment(putelfstr(s->name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0); 202 s->elfsym = numelfsym++; 203 } 204 } 205 206 static void 207 putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) 208 { 209 int i, l; 210 211 USED(go); 212 USED(ver); 213 USED(size); 214 USED(x); 215 switch(t) { 216 case 'T': 217 case 'L': 218 case 'D': 219 case 'B': 220 if(ver) 221 t += 'a' - 'A'; 222 case 'a': 223 case 'p': 224 case 'f': 225 case 'z': 226 case 'Z': 227 case 'm': 228 l = 4; 229 if(HEADTYPE == Hplan9x64 && !debug['8']) { 230 lputb(addr>>32); 231 l = 8; 232 } 233 lputb(addr); 234 cput(t+0x80); /* 0x80 is variable length */ 235 236 if(t == 'z' || t == 'Z') { 237 cput(s[0]); 238 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 239 cput(s[i]); 240 cput(s[i+1]); 241 } 242 cput(0); 243 cput(0); 244 i++; 245 } else { 246 /* skip the '<' in filenames */ 247 if(t == 'f') 248 s++; 249 for(i=0; s[i]; i++) 250 cput(s[i]); 251 cput(0); 252 } 253 symsize += l + 1 + i + 1; 254 break; 255 default: 256 return; 257 }; 258 } 259 260 void 261 asmplan9sym(void) 262 { 263 genasmsym(putplan9sym); 264 } 265 266 static Sym *symt; 267 268 static void 269 scput(int b) 270 { 271 uchar *p; 272 273 symgrow(symt, symt->size+1); 274 p = symt->p + symt->size; 275 *p = b; 276 symt->size++; 277 } 278 279 static void 280 slputb(int32 v) 281 { 282 uchar *p; 283 284 symgrow(symt, symt->size+4); 285 p = symt->p + symt->size; 286 *p++ = v>>24; 287 *p++ = v>>16; 288 *p++ = v>>8; 289 *p = v; 290 symt->size += 4; 291 } 292 293 static void 294 slputl(int32 v) 295 { 296 uchar *p; 297 298 symgrow(symt, symt->size+4); 299 p = symt->p + symt->size; 300 *p++ = v; 301 *p++ = v>>8; 302 *p++ = v>>16; 303 *p = v>>24; 304 symt->size += 4; 305 } 306 307 static void (*slput)(int32); 308 309 void 310 wputl(ushort w) 311 { 312 cput(w); 313 cput(w>>8); 314 } 315 316 void 317 wputb(ushort w) 318 { 319 cput(w>>8); 320 cput(w); 321 } 322 323 void 324 lputb(int32 l) 325 { 326 cput(l>>24); 327 cput(l>>16); 328 cput(l>>8); 329 cput(l); 330 } 331 332 void 333 lputl(int32 l) 334 { 335 cput(l); 336 cput(l>>8); 337 cput(l>>16); 338 cput(l>>24); 339 } 340 341 void 342 vputb(uint64 v) 343 { 344 lputb(v>>32); 345 lputb(v); 346 } 347 348 void 349 vputl(uint64 v) 350 { 351 lputl(v); 352 lputl(v >> 32); 353 } 354 355 // Emit symbol table entry. 356 // The table format is described at the top of ../../pkg/runtime/symtab.c. 357 void 358 putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ) 359 { 360 int i, f, c; 361 vlong v1; 362 Reloc *rel; 363 364 USED(size); 365 366 // type byte 367 if('A' <= t && t <= 'Z') 368 c = t - 'A' + (ver ? 26 : 0); 369 else if('a' <= t && t <= 'z') 370 c = t - 'a' + 26; 371 else { 372 diag("invalid symbol table type %c", t); 373 errorexit(); 374 return; 375 } 376 377 if(s != nil) 378 c |= 0x40; // wide value 379 if(typ != nil) 380 c |= 0x80; // has go type 381 scput(c); 382 383 // value 384 if(s != nil) { 385 // full width 386 rel = addrel(symt); 387 rel->siz = PtrSize; 388 rel->sym = s; 389 rel->type = D_ADDR; 390 rel->off = symt->size; 391 if(PtrSize == 8) 392 slput(0); 393 slput(0); 394 } else { 395 // varint 396 if(v < 0) { 397 diag("negative value in symbol table: %s %lld", name, v); 398 errorexit(); 399 } 400 v1 = v; 401 while(v1 >= 0x80) { 402 scput(v1 | 0x80); 403 v1 >>= 7; 404 } 405 scput(v1); 406 } 407 408 // go type if present 409 if(typ != nil) { 410 if(!typ->reachable) 411 diag("unreachable type %s", typ->name); 412 rel = addrel(symt); 413 rel->siz = PtrSize; 414 rel->sym = typ; 415 rel->type = D_ADDR; 416 rel->off = symt->size; 417 if(PtrSize == 8) 418 slput(0); 419 slput(0); 420 } 421 422 // name 423 if(t == 'f') 424 name++; 425 426 if(t == 'Z' || t == 'z') { 427 scput(name[0]); 428 for(i=1; name[i] != 0 || name[i+1] != 0; i += 2) { 429 scput(name[i]); 430 scput(name[i+1]); 431 } 432 scput(0); 433 scput(0); 434 } else { 435 for(i=0; name[i]; i++) 436 scput(name[i]); 437 scput(0); 438 } 439 440 if(debug['n']) { 441 if(t == 'z' || t == 'Z') { 442 Bprint(&bso, "%c %.8llux ", t, v); 443 for(i=1; name[i] != 0 || name[i+1] != 0; i+=2) { 444 f = ((name[i]&0xff) << 8) | (name[i+1]&0xff); 445 Bprint(&bso, "/%x", f); 446 } 447 Bprint(&bso, "\n"); 448 return; 449 } 450 if(ver) 451 Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, name, ver, typ ? typ->name : ""); 452 else 453 Bprint(&bso, "%c %.8llux %s %s\n", t, v, name, typ ? typ->name : ""); 454 } 455 } 456 457 void 458 symtab(void) 459 { 460 Sym *s, *symtype, *symtypelink, *symgostring, *symgofunc; 461 462 dosymtype(); 463 464 // Define these so that they'll get put into the symbol table. 465 // data.c:/^address will provide the actual values. 466 xdefine("text", STEXT, 0); 467 xdefine("etext", STEXT, 0); 468 xdefine("typelink", SRODATA, 0); 469 xdefine("etypelink", SRODATA, 0); 470 xdefine("rodata", SRODATA, 0); 471 xdefine("erodata", SRODATA, 0); 472 xdefine("noptrdata", SNOPTRDATA, 0); 473 xdefine("enoptrdata", SNOPTRDATA, 0); 474 xdefine("data", SDATA, 0); 475 xdefine("edata", SDATA, 0); 476 xdefine("bss", SBSS, 0); 477 xdefine("ebss", SBSS, 0); 478 xdefine("noptrbss", SNOPTRBSS, 0); 479 xdefine("enoptrbss", SNOPTRBSS, 0); 480 xdefine("end", SBSS, 0); 481 xdefine("epclntab", SRODATA, 0); 482 xdefine("esymtab", SRODATA, 0); 483 484 // garbage collection symbols 485 s = lookup("gcdata", 0); 486 s->type = SRODATA; 487 s->size = 0; 488 s->reachable = 1; 489 xdefine("egcdata", SRODATA, 0); 490 491 s = lookup("gcbss", 0); 492 s->type = SRODATA; 493 s->size = 0; 494 s->reachable = 1; 495 xdefine("egcbss", SRODATA, 0); 496 497 // pseudo-symbols to mark locations of type, string, and go string data. 498 s = lookup("type.*", 0); 499 s->type = STYPE; 500 s->size = 0; 501 s->reachable = 1; 502 symtype = s; 503 504 s = lookup("go.string.*", 0); 505 s->type = SGOSTRING; 506 s->size = 0; 507 s->reachable = 1; 508 symgostring = s; 509 510 s = lookup("go.func.*", 0); 511 s->type = SGOFUNC; 512 s->size = 0; 513 s->reachable = 1; 514 symgofunc = s; 515 516 symtypelink = lookup("typelink", 0); 517 518 symt = lookup("symtab", 0); 519 symt->type = SSYMTAB; 520 symt->size = 0; 521 symt->reachable = 1; 522 523 // assign specific types so that they sort together. 524 // within a type they sort by size, so the .* symbols 525 // just defined above will be first. 526 // hide the specific symbols. 527 for(s = allsym; s != S; s = s->allsym) { 528 if(!s->reachable || s->special || s->type != SRODATA) 529 continue; 530 if(strncmp(s->name, "type.", 5) == 0) { 531 s->type = STYPE; 532 s->hide = 1; 533 s->outer = symtype; 534 } 535 if(strncmp(s->name, "go.typelink.", 12) == 0) { 536 s->type = STYPELINK; 537 s->hide = 1; 538 s->outer = symtypelink; 539 } 540 if(strncmp(s->name, "go.string.", 10) == 0) { 541 s->type = SGOSTRING; 542 s->hide = 1; 543 s->outer = symgostring; 544 } 545 if(strncmp(s->name, "go.func.", 8) == 0) { 546 s->type = SGOFUNC; 547 s->hide = 1; 548 s->outer = symgofunc; 549 } 550 } 551 552 if(debug['s']) 553 return; 554 555 switch(thechar) { 556 default: 557 diag("unknown architecture %c", thechar); 558 errorexit(); 559 case '5': 560 case '6': 561 case '8': 562 // little-endian symbol table 563 slput = slputl; 564 break; 565 case 'v': 566 // big-endian symbol table 567 slput = slputb; 568 break; 569 } 570 // new symbol table header. 571 slput(0xfffffffd); 572 scput(0); 573 scput(0); 574 scput(0); 575 scput(PtrSize); 576 577 genasmsym(putsymb); 578 }