github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/cmd/link/internal/ld/symtab.go (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 package ld 32 33 import ( 34 "cmd/internal/obj" 35 "fmt" 36 "path/filepath" 37 "strings" 38 ) 39 40 // Symbol table. 41 42 func putelfstr(s string) int { 43 if len(Elfstrdat) == 0 && s != "" { 44 // first entry must be empty string 45 putelfstr("") 46 } 47 48 // When dynamically linking, we create LSym's by reading the names from 49 // the symbol tables of the shared libraries and so the names need to 50 // match exactly. Tools like DTrace will have to wait for now. 51 if !DynlinkingGo() { 52 // Rewrite · to . for ASCII-only tools like DTrace (sigh) 53 s = strings.Replace(s, "·", ".", -1) 54 } 55 56 n := len(s) + 1 57 for len(Elfstrdat)+n > cap(Elfstrdat) { 58 Elfstrdat = append(Elfstrdat[:cap(Elfstrdat)], 0)[:len(Elfstrdat)] 59 } 60 61 off := len(Elfstrdat) 62 Elfstrdat = Elfstrdat[:off+n] 63 copy(Elfstrdat[off:], s) 64 65 return off 66 } 67 68 func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) { 69 switch Thearch.Thechar { 70 case '0', '6', '7', '9': 71 Thearch.Lput(uint32(off)) 72 Cput(uint8(info)) 73 Cput(uint8(other)) 74 Thearch.Wput(uint16(shndx)) 75 Thearch.Vput(uint64(addr)) 76 Thearch.Vput(uint64(size)) 77 Symsize += ELF64SYMSIZE 78 79 default: 80 Thearch.Lput(uint32(off)) 81 Thearch.Lput(uint32(addr)) 82 Thearch.Lput(uint32(size)) 83 Cput(uint8(info)) 84 Cput(uint8(other)) 85 Thearch.Wput(uint16(shndx)) 86 Symsize += ELF32SYMSIZE 87 } 88 } 89 90 var numelfsym int = 1 // 0 is reserved 91 92 var elfbind int 93 94 func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) { 95 var type_ int 96 97 switch t { 98 default: 99 return 100 101 case 'T': 102 type_ = STT_FUNC 103 104 case 'D': 105 type_ = STT_OBJECT 106 107 case 'B': 108 type_ = STT_OBJECT 109 110 case 'U': 111 // ElfType is only set for symbols read from Go shared libraries, but 112 // for other symbols it is left as STT_NOTYPE which is fine. 113 type_ = int(x.ElfType) 114 115 case 't': 116 type_ = STT_TLS 117 } 118 119 xo := x 120 for xo.Outer != nil { 121 xo = xo.Outer 122 } 123 124 var elfshnum int 125 if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ { 126 elfshnum = SHN_UNDEF 127 } else { 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 elfshnum = xo.Sect.Elfsect.shnum 139 } 140 141 // One pass for each binding: STB_LOCAL, STB_GLOBAL, 142 // maybe one day STB_WEAK. 143 bind := STB_GLOBAL 144 145 if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Local { 146 bind = STB_LOCAL 147 } 148 149 // In external linking mode, we have to invoke gcc with -rdynamic 150 // to get the exported symbols put into the dynamic symbol table. 151 // To avoid filling the dynamic table with lots of unnecessary symbols, 152 // mark all Go symbols local (not global) in the final executable. 153 // But when we're dynamically linking, we need all those global symbols. 154 if !DynlinkingGo() && Linkmode == LinkExternal && x.Cgoexport&CgoExportStatic == 0 && elfshnum != SHN_UNDEF { 155 bind = STB_LOCAL 156 } 157 158 if Linkmode == LinkExternal && elfshnum != SHN_UNDEF { 159 addr -= int64(xo.Sect.Vaddr) 160 } 161 other := STV_DEFAULT 162 if x.Type&obj.SHIDDEN != 0 { 163 other = STV_HIDDEN 164 } 165 if (Buildmode == BuildmodePIE || DynlinkingGo()) && Thearch.Thechar == '9' && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { 166 // On ppc64 the top three bits of the st_other field indicate how 167 // many instructions separate the global and local entry points. In 168 // our case it is two instructions, indicated by the value 3. 169 other |= 3 << 5 170 } 171 172 if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT { 173 // When dynamically linking, we want references to functions defined 174 // in this module to always be to the function object, not to the 175 // PLT. We force this by writing an additional local symbol for every 176 // global function symbol and making all relocations against the 177 // global symbol refer to this local symbol instead (see 178 // (*LSym).ElfsymForReloc). This is approximately equivalent to the 179 // ELF linker -Bsymbolic-functions option, but that is buggy on 180 // several platforms. 181 putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other) 182 x.LocalElfsym = int32(numelfsym) 183 numelfsym++ 184 return 185 } else if bind != elfbind { 186 return 187 } 188 189 putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other) 190 x.Elfsym = int32(numelfsym) 191 numelfsym++ 192 } 193 194 func putelfsectionsym(s *LSym, shndx int) { 195 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0) 196 s.Elfsym = int32(numelfsym) 197 numelfsym++ 198 } 199 200 func putelfsymshndx(sympos int64, shndx int) { 201 here := Cpos() 202 if elf64 { 203 Cseek(sympos + 6) 204 } else { 205 Cseek(sympos + 14) 206 } 207 208 Thearch.Wput(uint16(shndx)) 209 Cseek(here) 210 } 211 212 func Asmelfsym() { 213 // the first symbol entry is reserved 214 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) 215 216 dwarfaddelfsectionsyms() 217 218 elfbind = STB_LOCAL 219 genasmsym(putelfsym) 220 221 elfbind = STB_GLOBAL 222 elfglobalsymndx = numelfsym 223 genasmsym(putelfsym) 224 } 225 226 func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) { 227 switch t { 228 case 'T', 'L', 'D', 'B': 229 if ver != 0 { 230 t += 'a' - 'A' 231 } 232 fallthrough 233 234 case 'a', 235 'p', 236 'f', 237 'z', 238 'Z', 239 'm': 240 l := 4 241 if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 { 242 Lputb(uint32(addr >> 32)) 243 l = 8 244 } 245 246 Lputb(uint32(addr)) 247 Cput(uint8(t + 0x80)) /* 0x80 is variable length */ 248 249 var i int 250 if t == 'z' || t == 'Z' { 251 Cput(uint8(s[0])) 252 for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 { 253 Cput(uint8(s[i])) 254 Cput(uint8(s[i+1])) 255 } 256 257 Cput(0) 258 Cput(0) 259 i++ 260 } else { 261 /* skip the '<' in filenames */ 262 if t == 'f' { 263 s = s[1:] 264 } 265 for i = 0; i < len(s); i++ { 266 Cput(uint8(s[i])) 267 } 268 Cput(0) 269 } 270 271 Symsize += int32(l) + 1 + int32(i) + 1 272 273 default: 274 return 275 } 276 } 277 278 func Asmplan9sym() { 279 genasmsym(putplan9sym) 280 } 281 282 var symt *LSym 283 284 func Wputl(w uint16) { 285 Cput(uint8(w)) 286 Cput(uint8(w >> 8)) 287 } 288 289 func Wputb(w uint16) { 290 Cput(uint8(w >> 8)) 291 Cput(uint8(w)) 292 } 293 294 func Lputb(l uint32) { 295 Cput(uint8(l >> 24)) 296 Cput(uint8(l >> 16)) 297 Cput(uint8(l >> 8)) 298 Cput(uint8(l)) 299 } 300 301 func Lputl(l uint32) { 302 Cput(uint8(l)) 303 Cput(uint8(l >> 8)) 304 Cput(uint8(l >> 16)) 305 Cput(uint8(l >> 24)) 306 } 307 308 func Vputb(v uint64) { 309 Lputb(uint32(v >> 32)) 310 Lputb(uint32(v)) 311 } 312 313 func Vputl(v uint64) { 314 Lputl(uint32(v)) 315 Lputl(uint32(v >> 32)) 316 } 317 318 type byPkg []*Library 319 320 func (libs byPkg) Len() int { 321 return len(libs) 322 } 323 324 func (libs byPkg) Less(a, b int) bool { 325 return libs[a].Pkg < libs[b].Pkg 326 } 327 328 func (libs byPkg) Swap(a, b int) { 329 libs[a], libs[b] = libs[b], libs[a] 330 } 331 332 func symtab() { 333 dosymtype() 334 335 // Define these so that they'll get put into the symbol table. 336 // data.c:/^address will provide the actual values. 337 xdefine("runtime.text", obj.STEXT, 0) 338 339 xdefine("runtime.etext", obj.STEXT, 0) 340 xdefine("runtime.typelink", obj.SRODATA, 0) 341 xdefine("runtime.etypelink", obj.SRODATA, 0) 342 xdefine("runtime.rodata", obj.SRODATA, 0) 343 xdefine("runtime.erodata", obj.SRODATA, 0) 344 xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) 345 xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) 346 xdefine("runtime.data", obj.SDATA, 0) 347 xdefine("runtime.edata", obj.SDATA, 0) 348 xdefine("runtime.bss", obj.SBSS, 0) 349 xdefine("runtime.ebss", obj.SBSS, 0) 350 xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0) 351 xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0) 352 xdefine("runtime.end", obj.SBSS, 0) 353 xdefine("runtime.epclntab", obj.SRODATA, 0) 354 xdefine("runtime.esymtab", obj.SRODATA, 0) 355 356 // garbage collection symbols 357 s := Linklookup(Ctxt, "runtime.gcdata", 0) 358 359 s.Type = obj.SRODATA 360 s.Size = 0 361 s.Reachable = true 362 xdefine("runtime.egcdata", obj.SRODATA, 0) 363 364 s = Linklookup(Ctxt, "runtime.gcbss", 0) 365 s.Type = obj.SRODATA 366 s.Size = 0 367 s.Reachable = true 368 xdefine("runtime.egcbss", obj.SRODATA, 0) 369 370 // pseudo-symbols to mark locations of type, string, and go string data. 371 var symtype *LSym 372 var symtyperel *LSym 373 if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) { 374 s = Linklookup(Ctxt, "type.*", 0) 375 376 s.Type = obj.STYPE 377 s.Size = 0 378 s.Reachable = true 379 symtype = s 380 381 s = Linklookup(Ctxt, "typerel.*", 0) 382 383 s.Type = obj.STYPERELRO 384 s.Size = 0 385 s.Reachable = true 386 symtyperel = s 387 } else if !DynlinkingGo() { 388 s = Linklookup(Ctxt, "type.*", 0) 389 390 s.Type = obj.STYPE 391 s.Size = 0 392 s.Reachable = true 393 symtype = s 394 symtyperel = s 395 } 396 397 s = Linklookup(Ctxt, "go.string.*", 0) 398 s.Type = obj.SGOSTRING 399 s.Local = true 400 s.Size = 0 401 s.Reachable = true 402 symgostring := s 403 404 s = Linklookup(Ctxt, "go.func.*", 0) 405 s.Type = obj.SGOFUNC 406 s.Local = true 407 s.Size = 0 408 s.Reachable = true 409 symgofunc := s 410 411 s = Linklookup(Ctxt, "runtime.gcbits.*", 0) 412 s.Type = obj.SGCBITS 413 s.Local = true 414 s.Size = 0 415 s.Reachable = true 416 symgcbits := s 417 418 symtypelink := Linklookup(Ctxt, "runtime.typelink", 0) 419 symtypelink.Type = obj.STYPELINK 420 421 symt = Linklookup(Ctxt, "runtime.symtab", 0) 422 symt.Local = true 423 symt.Type = obj.SSYMTAB 424 symt.Size = 0 425 symt.Reachable = true 426 427 ntypelinks := 0 428 429 // assign specific types so that they sort together. 430 // within a type they sort by size, so the .* symbols 431 // just defined above will be first. 432 // hide the specific symbols. 433 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 434 if !s.Reachable || s.Special != 0 || s.Type != obj.SRODATA { 435 continue 436 } 437 438 if strings.HasPrefix(s.Name, "type.") && !DynlinkingGo() { 439 s.Hide = 1 440 if UseRelro() && len(s.R) > 0 { 441 s.Type = obj.STYPERELRO 442 s.Outer = symtyperel 443 } else { 444 s.Type = obj.STYPE 445 s.Outer = symtype 446 } 447 } 448 449 if strings.HasPrefix(s.Name, "go.typelink.") { 450 ntypelinks++ 451 s.Type = obj.STYPELINK 452 s.Hide = 1 453 s.Outer = symtypelink 454 } 455 456 if strings.HasPrefix(s.Name, "go.string.") { 457 s.Type = obj.SGOSTRING 458 s.Hide = 1 459 s.Outer = symgostring 460 } 461 462 if strings.HasPrefix(s.Name, "runtime.gcbits.") { 463 s.Type = obj.SGCBITS 464 s.Hide = 1 465 s.Outer = symgcbits 466 } 467 468 if strings.HasPrefix(s.Name, "go.func.") { 469 s.Type = obj.SGOFUNC 470 s.Hide = 1 471 s.Outer = symgofunc 472 } 473 474 if strings.HasPrefix(s.Name, "gcargs.") || strings.HasPrefix(s.Name, "gclocals.") || strings.HasPrefix(s.Name, "gclocals·") { 475 s.Type = obj.SGOFUNC 476 s.Hide = 1 477 s.Outer = symgofunc 478 s.Align = 4 479 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 480 } 481 } 482 483 if Buildmode == BuildmodeShared { 484 abihashgostr := Linklookup(Ctxt, "go.link.abihash."+filepath.Base(outfile), 0) 485 abihashgostr.Reachable = true 486 abihashgostr.Type = obj.SRODATA 487 hashsym := Linklookup(Ctxt, "go.link.abihashbytes", 0) 488 Addaddr(Ctxt, abihashgostr, hashsym) 489 adduint(Ctxt, abihashgostr, uint64(hashsym.Size)) 490 } 491 492 // Information about the layout of the executable image for the 493 // runtime to use. Any changes here must be matched by changes to 494 // the definition of moduledata in runtime/symtab.go. 495 // This code uses several global variables that are set by pcln.go:pclntab. 496 moduledata := Ctxt.Moduledata 497 // The pclntab slice 498 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0)) 499 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 500 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 501 // The ftab slice 502 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset)) 503 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 504 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 505 // The filetab slice 506 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset)) 507 adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1) 508 adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1) 509 // findfunctab 510 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0)) 511 // minpc, maxpc 512 Addaddr(Ctxt, moduledata, pclntabFirstFunc) 513 Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 514 // pointers to specific parts of the module 515 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0)) 516 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0)) 517 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0)) 518 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0)) 519 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0)) 520 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0)) 521 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0)) 522 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0)) 523 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0)) 524 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0)) 525 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0)) 526 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0)) 527 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0)) 528 // The typelinks slice 529 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0)) 530 adduint(Ctxt, moduledata, uint64(ntypelinks)) 531 adduint(Ctxt, moduledata, uint64(ntypelinks)) 532 if len(Ctxt.Shlibs) > 0 { 533 thismodulename := filepath.Base(outfile) 534 switch Buildmode { 535 case BuildmodeExe, BuildmodePIE: 536 // When linking an executable, outfile is just "a.out". Make 537 // it something slightly more comprehensible. 538 thismodulename = "the executable" 539 } 540 addgostring(moduledata, "go.link.thismodulename", thismodulename) 541 542 modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0) 543 modulehashes.Reachable = true 544 modulehashes.Local = true 545 modulehashes.Type = obj.SRODATA 546 547 for i, shlib := range Ctxt.Shlibs { 548 // modulehashes[i].modulename 549 modulename := filepath.Base(shlib.Path) 550 addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 551 552 // modulehashes[i].linktimehash 553 addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 554 555 // modulehashes[i].runtimehash 556 abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0) 557 abihash.Reachable = true 558 Addaddr(Ctxt, modulehashes, abihash) 559 } 560 561 Addaddr(Ctxt, moduledata, modulehashes) 562 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 563 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 564 } 565 // The rest of moduledata is zero initialized. 566 // When linking an object that does not contain the runtime we are 567 // creating the moduledata from scratch and it does not have a 568 // compiler-provided size, so read it from the type data. 569 moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0) 570 moduledata.Size = decodetype_size(moduledatatype) 571 Symgrow(Ctxt, moduledata, moduledata.Size) 572 573 lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0) 574 if lastmoduledatap.Type != obj.SDYNIMPORT { 575 lastmoduledatap.Type = obj.SNOPTRDATA 576 lastmoduledatap.Size = 0 // overwrite existing value 577 Addaddr(Ctxt, lastmoduledatap, moduledata) 578 } 579 }