github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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 '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 166 if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT { 167 // When dynamically linking, we want references to functions defined 168 // in this module to always be to the function object, not to the 169 // PLT. We force this by writing an additional local symbol for every 170 // global function symbol and making all relocations against the 171 // global symbol refer to this local symbol instead (see 172 // (*LSym).ElfsymForReloc). This is approximately equivalent to the 173 // ELF linker -Bsymbolic-functions option, but that is buggy on 174 // several platforms. 175 putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other) 176 x.LocalElfsym = int32(numelfsym) 177 numelfsym++ 178 } else if bind != elfbind { 179 return 180 } 181 182 putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other) 183 x.Elfsym = int32(numelfsym) 184 numelfsym++ 185 } 186 187 func putelfsectionsym(s *LSym, shndx int) { 188 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0) 189 s.Elfsym = int32(numelfsym) 190 numelfsym++ 191 } 192 193 func putelfsymshndx(sympos int64, shndx int) { 194 here := Cpos() 195 if elf64 { 196 Cseek(sympos + 6) 197 } else { 198 Cseek(sympos + 14) 199 } 200 201 Thearch.Wput(uint16(shndx)) 202 Cseek(here) 203 } 204 205 func Asmelfsym() { 206 // the first symbol entry is reserved 207 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) 208 209 dwarfaddelfsectionsyms() 210 211 elfbind = STB_LOCAL 212 genasmsym(putelfsym) 213 214 elfbind = STB_GLOBAL 215 elfglobalsymndx = numelfsym 216 genasmsym(putelfsym) 217 } 218 219 func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) { 220 switch t { 221 case 'T', 'L', 'D', 'B': 222 if ver != 0 { 223 t += 'a' - 'A' 224 } 225 fallthrough 226 227 case 'a', 228 'p', 229 'f', 230 'z', 231 'Z', 232 'm': 233 l := 4 234 if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 { 235 Lputb(uint32(addr >> 32)) 236 l = 8 237 } 238 239 Lputb(uint32(addr)) 240 Cput(uint8(t + 0x80)) /* 0x80 is variable length */ 241 242 var i int 243 if t == 'z' || t == 'Z' { 244 Cput(uint8(s[0])) 245 for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 { 246 Cput(uint8(s[i])) 247 Cput(uint8(s[i+1])) 248 } 249 250 Cput(0) 251 Cput(0) 252 i++ 253 } else { 254 /* skip the '<' in filenames */ 255 if t == 'f' { 256 s = s[1:] 257 } 258 for i = 0; i < len(s); i++ { 259 Cput(uint8(s[i])) 260 } 261 Cput(0) 262 } 263 264 Symsize += int32(l) + 1 + int32(i) + 1 265 266 default: 267 return 268 } 269 } 270 271 func Asmplan9sym() { 272 genasmsym(putplan9sym) 273 } 274 275 var symt *LSym 276 277 func Wputl(w uint16) { 278 Cput(uint8(w)) 279 Cput(uint8(w >> 8)) 280 } 281 282 func Wputb(w uint16) { 283 Cput(uint8(w >> 8)) 284 Cput(uint8(w)) 285 } 286 287 func Lputb(l uint32) { 288 Cput(uint8(l >> 24)) 289 Cput(uint8(l >> 16)) 290 Cput(uint8(l >> 8)) 291 Cput(uint8(l)) 292 } 293 294 func Lputl(l uint32) { 295 Cput(uint8(l)) 296 Cput(uint8(l >> 8)) 297 Cput(uint8(l >> 16)) 298 Cput(uint8(l >> 24)) 299 } 300 301 func Vputb(v uint64) { 302 Lputb(uint32(v >> 32)) 303 Lputb(uint32(v)) 304 } 305 306 func Vputl(v uint64) { 307 Lputl(uint32(v)) 308 Lputl(uint32(v >> 32)) 309 } 310 311 type byPkg []*Library 312 313 func (libs byPkg) Len() int { 314 return len(libs) 315 } 316 317 func (libs byPkg) Less(a, b int) bool { 318 return libs[a].Pkg < libs[b].Pkg 319 } 320 321 func (libs byPkg) Swap(a, b int) { 322 libs[a], libs[b] = libs[b], libs[a] 323 } 324 325 func symtab() { 326 dosymtype() 327 328 // Define these so that they'll get put into the symbol table. 329 // data.c:/^address will provide the actual values. 330 xdefine("runtime.text", obj.STEXT, 0) 331 332 xdefine("runtime.etext", obj.STEXT, 0) 333 xdefine("runtime.typelink", obj.SRODATA, 0) 334 xdefine("runtime.etypelink", obj.SRODATA, 0) 335 xdefine("runtime.rodata", obj.SRODATA, 0) 336 xdefine("runtime.erodata", obj.SRODATA, 0) 337 xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) 338 xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) 339 xdefine("runtime.data", obj.SDATA, 0) 340 xdefine("runtime.edata", obj.SDATA, 0) 341 xdefine("runtime.bss", obj.SBSS, 0) 342 xdefine("runtime.ebss", obj.SBSS, 0) 343 xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0) 344 xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0) 345 xdefine("runtime.end", obj.SBSS, 0) 346 xdefine("runtime.epclntab", obj.SRODATA, 0) 347 xdefine("runtime.esymtab", obj.SRODATA, 0) 348 349 // garbage collection symbols 350 s := Linklookup(Ctxt, "runtime.gcdata", 0) 351 352 s.Type = obj.SRODATA 353 s.Size = 0 354 s.Reachable = true 355 xdefine("runtime.egcdata", obj.SRODATA, 0) 356 357 s = Linklookup(Ctxt, "runtime.gcbss", 0) 358 s.Type = obj.SRODATA 359 s.Size = 0 360 s.Reachable = true 361 xdefine("runtime.egcbss", obj.SRODATA, 0) 362 363 // pseudo-symbols to mark locations of type, string, and go string data. 364 var symtype *LSym 365 var symtyperel *LSym 366 if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) { 367 s = Linklookup(Ctxt, "type.*", 0) 368 369 s.Type = obj.STYPE 370 s.Size = 0 371 s.Reachable = true 372 symtype = s 373 374 s = Linklookup(Ctxt, "typerel.*", 0) 375 376 s.Type = obj.STYPERELRO 377 s.Size = 0 378 s.Reachable = true 379 symtyperel = s 380 } else if !DynlinkingGo() { 381 s = Linklookup(Ctxt, "type.*", 0) 382 383 s.Type = obj.STYPE 384 s.Size = 0 385 s.Reachable = true 386 symtype = s 387 symtyperel = s 388 } 389 390 s = Linklookup(Ctxt, "go.string.*", 0) 391 s.Type = obj.SGOSTRING 392 s.Local = true 393 s.Size = 0 394 s.Reachable = true 395 symgostring := s 396 397 s = Linklookup(Ctxt, "go.func.*", 0) 398 s.Type = obj.SGOFUNC 399 s.Local = true 400 s.Size = 0 401 s.Reachable = true 402 symgofunc := s 403 404 s = Linklookup(Ctxt, "runtime.gcbits.*", 0) 405 s.Type = obj.SGCBITS 406 s.Local = true 407 s.Size = 0 408 s.Reachable = true 409 symgcbits := s 410 411 symtypelink := Linklookup(Ctxt, "runtime.typelink", 0) 412 symtypelink.Type = obj.STYPELINK 413 414 symt = Linklookup(Ctxt, "runtime.symtab", 0) 415 symt.Local = true 416 symt.Type = obj.SSYMTAB 417 symt.Size = 0 418 symt.Reachable = true 419 420 ntypelinks := 0 421 422 // assign specific types so that they sort together. 423 // within a type they sort by size, so the .* symbols 424 // just defined above will be first. 425 // hide the specific symbols. 426 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 427 if !s.Reachable || s.Special != 0 || s.Type != obj.SRODATA { 428 continue 429 } 430 431 if strings.HasPrefix(s.Name, "type.") && !DynlinkingGo() { 432 s.Hide = 1 433 if UseRelro() && len(s.R) > 0 { 434 s.Type = obj.STYPERELRO 435 s.Outer = symtyperel 436 } else { 437 s.Type = obj.STYPE 438 s.Outer = symtype 439 } 440 } 441 442 if strings.HasPrefix(s.Name, "go.typelink.") { 443 ntypelinks++ 444 s.Type = obj.STYPELINK 445 s.Hide = 1 446 s.Outer = symtypelink 447 } 448 449 if strings.HasPrefix(s.Name, "go.string.") { 450 s.Type = obj.SGOSTRING 451 s.Hide = 1 452 s.Outer = symgostring 453 } 454 455 if strings.HasPrefix(s.Name, "runtime.gcbits.") { 456 s.Type = obj.SGCBITS 457 s.Hide = 1 458 s.Outer = symgcbits 459 } 460 461 if strings.HasPrefix(s.Name, "go.func.") { 462 s.Type = obj.SGOFUNC 463 s.Hide = 1 464 s.Outer = symgofunc 465 } 466 467 if strings.HasPrefix(s.Name, "gcargs.") || strings.HasPrefix(s.Name, "gclocals.") || strings.HasPrefix(s.Name, "gclocals·") { 468 s.Type = obj.SGOFUNC 469 s.Hide = 1 470 s.Outer = symgofunc 471 s.Align = 4 472 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 473 } 474 } 475 476 if Buildmode == BuildmodeShared { 477 abihashgostr := Linklookup(Ctxt, "go.link.abihash."+filepath.Base(outfile), 0) 478 abihashgostr.Reachable = true 479 abihashgostr.Type = obj.SRODATA 480 hashsym := Linklookup(Ctxt, "go.link.abihashbytes", 0) 481 Addaddr(Ctxt, abihashgostr, hashsym) 482 adduint(Ctxt, abihashgostr, uint64(hashsym.Size)) 483 } 484 485 // Information about the layout of the executable image for the 486 // runtime to use. Any changes here must be matched by changes to 487 // the definition of moduledata in runtime/symtab.go. 488 // This code uses several global variables that are set by pcln.go:pclntab. 489 moduledata := Ctxt.Moduledata 490 // The pclntab slice 491 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0)) 492 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 493 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 494 // The ftab slice 495 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset)) 496 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 497 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 498 // The filetab slice 499 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset)) 500 adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)) 501 adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)) 502 // findfunctab 503 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0)) 504 // minpc, maxpc 505 Addaddr(Ctxt, moduledata, pclntabFirstFunc) 506 Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 507 // pointers to specific parts of the module 508 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0)) 509 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0)) 510 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0)) 511 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0)) 512 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0)) 513 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0)) 514 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0)) 515 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0)) 516 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0)) 517 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0)) 518 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0)) 519 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0)) 520 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0)) 521 // The typelinks slice 522 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0)) 523 adduint(Ctxt, moduledata, uint64(ntypelinks)) 524 adduint(Ctxt, moduledata, uint64(ntypelinks)) 525 if len(Ctxt.Shlibs) > 0 { 526 thismodulename := filepath.Base(outfile) 527 switch Buildmode { 528 case BuildmodeExe, BuildmodePIE: 529 // When linking an executable, outfile is just "a.out". Make 530 // it something slightly more comprehensible. 531 thismodulename = "the executable" 532 } 533 addgostring(moduledata, "go.link.thismodulename", thismodulename) 534 535 modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0) 536 modulehashes.Reachable = true 537 modulehashes.Local = true 538 modulehashes.Type = obj.SRODATA 539 540 for i, shlib := range Ctxt.Shlibs { 541 // modulehashes[i].modulename 542 modulename := filepath.Base(shlib.Path) 543 addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 544 545 // modulehashes[i].linktimehash 546 addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 547 548 // modulehashes[i].runtimehash 549 abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0) 550 abihash.Reachable = true 551 Addaddr(Ctxt, modulehashes, abihash) 552 } 553 554 Addaddr(Ctxt, moduledata, modulehashes) 555 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 556 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 557 } 558 // The rest of moduledata is zero initialized. 559 // When linking an object that does not contain the runtime we are 560 // creating the moduledata from scratch and it does not have a 561 // compiler-provided size, so read it from the type data. 562 moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0) 563 moduledata.Size = decodetype_size(moduledatatype) 564 Symgrow(Ctxt, moduledata, moduledata.Size) 565 566 lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0) 567 if lastmoduledatap.Type != obj.SDYNIMPORT { 568 lastmoduledatap.Type = obj.SNOPTRDATA 569 lastmoduledatap.Size = 0 // overwrite existing value 570 Addaddr(Ctxt, lastmoduledatap, moduledata) 571 } 572 }