github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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.tlsg", 0); 202 if(s->sect == nil) { 203 ctxt->cursym = nil; 204 diag("missing section for %s", s->name); 205 errorexit(); 206 } 207 if (strcmp(goos, "android") == 0) { 208 // Android emulates runtime.tlsg as a regular variable. 209 putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_OBJECT, s->sect->elfsect->shnum, 0); 210 } else { 211 putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0); 212 } 213 s->elfsym = numelfsym++; 214 } 215 216 elfbind = STB_GLOBAL; 217 elfglobalsymndx = numelfsym; 218 genasmsym(putelfsym); 219 220 for(s=ctxt->allsym; s!=S; s=s->allsym) { 221 if(s->type != SHOSTOBJ && !(s->type == SDYNIMPORT && s->reachable)) 222 continue; 223 if(s->type == SDYNIMPORT) 224 name = s->extname; 225 else 226 name = s->name; 227 putelfsyment(putelfstr(name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0); 228 s->elfsym = numelfsym++; 229 } 230 } 231 232 static void 233 putplan9sym(LSym *x, char *s, int t, vlong addr, vlong size, int ver, LSym *go) 234 { 235 int i, l; 236 237 USED(go); 238 USED(ver); 239 USED(size); 240 USED(x); 241 switch(t) { 242 case 'T': 243 case 'L': 244 case 'D': 245 case 'B': 246 if(ver) 247 t += 'a' - 'A'; 248 case 'a': 249 case 'p': 250 case 'f': 251 case 'z': 252 case 'Z': 253 case 'm': 254 l = 4; 255 if(HEADTYPE == Hplan9 && thechar == '6' && !debug['8']) { 256 lputb(addr>>32); 257 l = 8; 258 } 259 lputb(addr); 260 cput(t+0x80); /* 0x80 is variable length */ 261 262 if(t == 'z' || t == 'Z') { 263 cput(s[0]); 264 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 265 cput(s[i]); 266 cput(s[i+1]); 267 } 268 cput(0); 269 cput(0); 270 i++; 271 } else { 272 /* skip the '<' in filenames */ 273 if(t == 'f') 274 s++; 275 for(i=0; s[i]; i++) 276 cput(s[i]); 277 cput(0); 278 } 279 symsize += l + 1 + i + 1; 280 break; 281 default: 282 return; 283 }; 284 } 285 286 void 287 asmplan9sym(void) 288 { 289 genasmsym(putplan9sym); 290 } 291 292 static LSym *symt; 293 294 void 295 wputl(ushort w) 296 { 297 cput(w); 298 cput(w>>8); 299 } 300 301 void 302 wputb(ushort w) 303 { 304 cput(w>>8); 305 cput(w); 306 } 307 308 void 309 lputb(int32 l) 310 { 311 cput(l>>24); 312 cput(l>>16); 313 cput(l>>8); 314 cput(l); 315 } 316 317 void 318 lputl(int32 l) 319 { 320 cput(l); 321 cput(l>>8); 322 cput(l>>16); 323 cput(l>>24); 324 } 325 326 void 327 vputb(uint64 v) 328 { 329 lputb(v>>32); 330 lputb(v); 331 } 332 333 void 334 vputl(uint64 v) 335 { 336 lputl(v); 337 lputl(v >> 32); 338 } 339 340 void 341 symtab(void) 342 { 343 LSym *s, *symtype, *symtypelink, *symgostring, *symgofunc; 344 345 dosymtype(); 346 347 // Define these so that they'll get put into the symbol table. 348 // data.c:/^address will provide the actual values. 349 xdefine("runtime.text", STEXT, 0); 350 xdefine("runtime.etext", STEXT, 0); 351 xdefine("runtime.typelink", SRODATA, 0); 352 xdefine("runtime.etypelink", SRODATA, 0); 353 xdefine("runtime.rodata", SRODATA, 0); 354 xdefine("runtime.erodata", SRODATA, 0); 355 xdefine("runtime.noptrdata", SNOPTRDATA, 0); 356 xdefine("runtime.enoptrdata", SNOPTRDATA, 0); 357 xdefine("runtime.data", SDATA, 0); 358 xdefine("runtime.edata", SDATA, 0); 359 xdefine("runtime.bss", SBSS, 0); 360 xdefine("runtime.ebss", SBSS, 0); 361 xdefine("runtime.noptrbss", SNOPTRBSS, 0); 362 xdefine("runtime.enoptrbss", SNOPTRBSS, 0); 363 xdefine("runtime.end", SBSS, 0); 364 xdefine("runtime.epclntab", SRODATA, 0); 365 xdefine("runtime.esymtab", SRODATA, 0); 366 367 // garbage collection symbols 368 s = linklookup(ctxt, "runtime.gcdata", 0); 369 s->type = SRODATA; 370 s->size = 0; 371 s->reachable = 1; 372 xdefine("runtime.egcdata", SRODATA, 0); 373 374 s = linklookup(ctxt, "runtime.gcbss", 0); 375 s->type = SRODATA; 376 s->size = 0; 377 s->reachable = 1; 378 xdefine("runtime.egcbss", SRODATA, 0); 379 380 // pseudo-symbols to mark locations of type, string, and go string data. 381 s = linklookup(ctxt, "type.*", 0); 382 s->type = STYPE; 383 s->size = 0; 384 s->reachable = 1; 385 symtype = s; 386 387 s = linklookup(ctxt, "go.string.*", 0); 388 s->type = SGOSTRING; 389 s->size = 0; 390 s->reachable = 1; 391 symgostring = s; 392 393 s = linklookup(ctxt, "go.func.*", 0); 394 s->type = SGOFUNC; 395 s->size = 0; 396 s->reachable = 1; 397 symgofunc = s; 398 399 symtypelink = linklookup(ctxt, "runtime.typelink", 0); 400 401 symt = linklookup(ctxt, "runtime.symtab", 0); 402 symt->type = SSYMTAB; 403 symt->size = 0; 404 symt->reachable = 1; 405 406 // assign specific types so that they sort together. 407 // within a type they sort by size, so the .* symbols 408 // just defined above will be first. 409 // hide the specific symbols. 410 for(s = ctxt->allsym; s != S; s = s->allsym) { 411 if(!s->reachable || s->special || s->type != SRODATA) 412 continue; 413 if(strncmp(s->name, "type.", 5) == 0) { 414 s->type = STYPE; 415 s->hide = 1; 416 s->outer = symtype; 417 } 418 if(strncmp(s->name, "go.typelink.", 12) == 0) { 419 s->type = STYPELINK; 420 s->hide = 1; 421 s->outer = symtypelink; 422 } 423 if(strncmp(s->name, "go.string.", 10) == 0) { 424 s->type = SGOSTRING; 425 s->hide = 1; 426 s->outer = symgostring; 427 } 428 if(strncmp(s->name, "go.func.", 8) == 0) { 429 s->type = SGOFUNC; 430 s->hide = 1; 431 s->outer = symgofunc; 432 } 433 if(strncmp(s->name, "gcargs.", 7) == 0 || strncmp(s->name, "gclocals.", 9) == 0 || strncmp(s->name, "gclocals·", 10) == 0) { 434 s->type = SGOFUNC; 435 s->hide = 1; 436 s->outer = symgofunc; 437 s->align = 4; 438 liveness += (s->size+s->align-1)&~(s->align-1); 439 } 440 } 441 }