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