github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/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 char *p, *q; 44 45 if(elfstrsize == 0 && s[0] != 0) { 46 // first entry must be empty string 47 putelfstr(""); 48 } 49 50 n = strlen(s)+1; 51 if(elfstrsize+n > maxelfstr) { 52 maxelfstr = 2*(elfstrsize+n+(1<<20)); 53 elfstrdat = realloc(elfstrdat, maxelfstr); 54 } 55 off = elfstrsize; 56 elfstrsize += n; 57 memmove(elfstrdat+off, s, n); 58 // replace "·" as ".", because DTrace cannot handle it. 59 p = strstr(s, "·"); 60 if(p != nil) { 61 p = q = elfstrdat+off; 62 while (*q != '\0') { 63 if((uchar)*q == 0xc2 && (uchar)*(q+1) == 0xb7) { 64 q += 2; 65 *p++ = '.'; 66 elfstrsize--; 67 } else { 68 *p++ = *q++; 69 } 70 } 71 *p = '\0'; 72 } 73 return off; 74 } 75 76 static void 77 putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other) 78 { 79 switch(thechar) { 80 case '6': 81 LPUT(off); 82 cput(info); 83 cput(other); 84 WPUT(shndx); 85 VPUT(addr); 86 VPUT(size); 87 symsize += ELF64SYMSIZE; 88 break; 89 default: 90 LPUT(off); 91 LPUT(addr); 92 LPUT(size); 93 cput(info); 94 cput(other); 95 WPUT(shndx); 96 symsize += ELF32SYMSIZE; 97 break; 98 } 99 } 100 101 static int numelfsym = 1; // 0 is reserved 102 static int elfbind; 103 104 static void 105 putelfsym(LSym *x, char *s, int t, vlong addr, vlong size, int ver, LSym *go) 106 { 107 int bind, type, off; 108 LSym *xo; 109 110 USED(go); 111 switch(t) { 112 default: 113 return; 114 case 'T': 115 type = STT_FUNC; 116 break; 117 case 'D': 118 type = STT_OBJECT; 119 break; 120 case 'B': 121 type = STT_OBJECT; 122 break; 123 } 124 xo = x; 125 while(xo->outer != nil) 126 xo = xo->outer; 127 if(xo->sect == nil) { 128 ctxt->cursym = x; 129 diag("missing section in putelfsym"); 130 return; 131 } 132 if(xo->sect->elfsect == nil) { 133 ctxt->cursym = x; 134 diag("missing ELF section in putelfsym"); 135 return; 136 } 137 138 // One pass for each binding: STB_LOCAL, STB_GLOBAL, 139 // maybe one day STB_WEAK. 140 bind = STB_GLOBAL; 141 if(ver || (x->type & SHIDDEN)) 142 bind = STB_LOCAL; 143 144 // In external linking mode, we have to invoke gcc with -rdynamic 145 // to get the exported symbols put into the dynamic symbol table. 146 // To avoid filling the dynamic table with lots of unnecessary symbols, 147 // mark all Go symbols local (not global) in the final executable. 148 if(linkmode == LinkExternal && !(x->cgoexport&CgoExportStatic)) 149 bind = STB_LOCAL; 150 151 if(bind != elfbind) 152 return; 153 154 off = putelfstr(s); 155 if(linkmode == LinkExternal) 156 addr -= xo->sect->vaddr; 157 putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->shnum, (x->type & SHIDDEN) ? 2 : 0); 158 x->elfsym = numelfsym++; 159 } 160 161 void 162 putelfsectionsym(LSym* s, int shndx) 163 { 164 putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_SECTION, shndx, 0); 165 s->elfsym = numelfsym++; 166 } 167 168 void 169 putelfsymshndx(vlong sympos, int shndx) 170 { 171 vlong here; 172 173 here = cpos(); 174 switch(thechar) { 175 case '6': 176 cseek(sympos+6); 177 break; 178 default: 179 cseek(sympos+14); 180 break; 181 } 182 WPUT(shndx); 183 cseek(here); 184 } 185 186 void 187 asmelfsym(void) 188 { 189 LSym *s; 190 char *name; 191 192 // the first symbol entry is reserved 193 putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0); 194 195 dwarfaddelfsectionsyms(); 196 197 elfbind = STB_LOCAL; 198 genasmsym(putelfsym); 199 200 if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) { 201 s = linklookup(ctxt, "runtime.tlsgm", 0); 202 if(s->sect == nil) { 203 ctxt->cursym = nil; 204 diag("missing section for %s", s->name); 205 errorexit(); 206 } 207 putelfsyment(putelfstr(s->name), 0, 2*PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0); 208 s->elfsym = numelfsym++; 209 } 210 211 elfbind = STB_GLOBAL; 212 elfglobalsymndx = numelfsym; 213 genasmsym(putelfsym); 214 215 for(s=ctxt->allsym; s!=S; s=s->allsym) { 216 if(s->type != SHOSTOBJ && !(s->type == SDYNIMPORT && s->reachable)) 217 continue; 218 if(s->type == SDYNIMPORT) 219 name = s->extname; 220 else 221 name = s->name; 222 putelfsyment(putelfstr(name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0); 223 s->elfsym = numelfsym++; 224 } 225 } 226 227 static void 228 putplan9sym(LSym *x, char *s, int t, vlong addr, vlong size, int ver, LSym *go) 229 { 230 int i, l; 231 232 USED(go); 233 USED(ver); 234 USED(size); 235 USED(x); 236 switch(t) { 237 case 'T': 238 case 'L': 239 case 'D': 240 case 'B': 241 if(ver) 242 t += 'a' - 'A'; 243 case 'a': 244 case 'p': 245 case 'f': 246 case 'z': 247 case 'Z': 248 case 'm': 249 l = 4; 250 if(HEADTYPE == Hplan9 && thechar == '6' && !debug['8']) { 251 lputb(addr>>32); 252 l = 8; 253 } 254 lputb(addr); 255 cput(t+0x80); /* 0x80 is variable length */ 256 257 if(t == 'z' || t == 'Z') { 258 cput(s[0]); 259 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 260 cput(s[i]); 261 cput(s[i+1]); 262 } 263 cput(0); 264 cput(0); 265 i++; 266 } else { 267 /* skip the '<' in filenames */ 268 if(t == 'f') 269 s++; 270 for(i=0; s[i]; i++) 271 cput(s[i]); 272 cput(0); 273 } 274 symsize += l + 1 + i + 1; 275 break; 276 default: 277 return; 278 }; 279 } 280 281 void 282 asmplan9sym(void) 283 { 284 genasmsym(putplan9sym); 285 } 286 287 static LSym *symt; 288 289 void 290 wputl(ushort w) 291 { 292 cput(w); 293 cput(w>>8); 294 } 295 296 void 297 wputb(ushort w) 298 { 299 cput(w>>8); 300 cput(w); 301 } 302 303 void 304 lputb(int32 l) 305 { 306 cput(l>>24); 307 cput(l>>16); 308 cput(l>>8); 309 cput(l); 310 } 311 312 void 313 lputl(int32 l) 314 { 315 cput(l); 316 cput(l>>8); 317 cput(l>>16); 318 cput(l>>24); 319 } 320 321 void 322 vputb(uint64 v) 323 { 324 lputb(v>>32); 325 lputb(v); 326 } 327 328 void 329 vputl(uint64 v) 330 { 331 lputl(v); 332 lputl(v >> 32); 333 } 334 335 void 336 symtab(void) 337 { 338 LSym *s, *symtype, *symtypelink, *symgostring, *symgofunc; 339 340 dosymtype(); 341 342 // Define these so that they'll get put into the symbol table. 343 // data.c:/^address will provide the actual values. 344 xdefine("text", STEXT, 0); 345 xdefine("etext", STEXT, 0); 346 xdefine("typelink", SRODATA, 0); 347 xdefine("etypelink", SRODATA, 0); 348 xdefine("rodata", SRODATA, 0); 349 xdefine("erodata", SRODATA, 0); 350 xdefine("noptrdata", SNOPTRDATA, 0); 351 xdefine("enoptrdata", SNOPTRDATA, 0); 352 xdefine("data", SDATA, 0); 353 xdefine("edata", SDATA, 0); 354 xdefine("bss", SBSS, 0); 355 xdefine("ebss", SBSS, 0); 356 xdefine("noptrbss", SNOPTRBSS, 0); 357 xdefine("enoptrbss", SNOPTRBSS, 0); 358 xdefine("end", SBSS, 0); 359 xdefine("epclntab", SRODATA, 0); 360 xdefine("esymtab", SRODATA, 0); 361 362 // garbage collection symbols 363 s = linklookup(ctxt, "gcdata", 0); 364 s->type = SRODATA; 365 s->size = 0; 366 s->reachable = 1; 367 xdefine("egcdata", SRODATA, 0); 368 369 s = linklookup(ctxt, "gcbss", 0); 370 s->type = SRODATA; 371 s->size = 0; 372 s->reachable = 1; 373 xdefine("egcbss", SRODATA, 0); 374 375 // pseudo-symbols to mark locations of type, string, and go string data. 376 s = linklookup(ctxt, "type.*", 0); 377 s->type = STYPE; 378 s->size = 0; 379 s->reachable = 1; 380 symtype = s; 381 382 s = linklookup(ctxt, "go.string.*", 0); 383 s->type = SGOSTRING; 384 s->size = 0; 385 s->reachable = 1; 386 symgostring = s; 387 388 s = linklookup(ctxt, "go.func.*", 0); 389 s->type = SGOFUNC; 390 s->size = 0; 391 s->reachable = 1; 392 symgofunc = s; 393 394 symtypelink = linklookup(ctxt, "typelink", 0); 395 396 symt = linklookup(ctxt, "symtab", 0); 397 symt->type = SSYMTAB; 398 symt->size = 0; 399 symt->reachable = 1; 400 401 // assign specific types so that they sort together. 402 // within a type they sort by size, so the .* symbols 403 // just defined above will be first. 404 // hide the specific symbols. 405 for(s = ctxt->allsym; s != S; s = s->allsym) { 406 if(!s->reachable || s->special || s->type != SRODATA) 407 continue; 408 if(strncmp(s->name, "type.", 5) == 0) { 409 s->type = STYPE; 410 s->hide = 1; 411 s->outer = symtype; 412 } 413 if(strncmp(s->name, "go.typelink.", 12) == 0) { 414 s->type = STYPELINK; 415 s->hide = 1; 416 s->outer = symtypelink; 417 } 418 if(strncmp(s->name, "go.string.", 10) == 0) { 419 s->type = SGOSTRING; 420 s->hide = 1; 421 s->outer = symgostring; 422 } 423 if(strncmp(s->name, "go.func.", 8) == 0) { 424 s->type = SGOFUNC; 425 s->hide = 1; 426 s->outer = symgofunc; 427 } 428 if(strncmp(s->name, "gcargs.", 7) == 0 || strncmp(s->name, "gclocals.", 9) == 0 || strncmp(s->name, "gclocals·", 10) == 0) { 429 s->type = SGOFUNC; 430 s->hide = 1; 431 s->outer = symgofunc; 432 s->align = 4; 433 liveness += (s->size+s->align-1)&~(s->align-1); 434 } 435 } 436 }