github.com/bir3/gocompiler@v0.3.205/src/cmd/link/internal/ld/symtab.go (about) 1 // Inferno utils/6l/span.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/master/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 "github.com/bir3/gocompiler/src/cmd/internal/obj" 35 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 36 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 37 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 38 "debug/elf" 39 "fmt" 40 "github.com/bir3/gocompiler/src/internal/buildcfg" 41 "path/filepath" 42 "strings" 43 ) 44 45 // Symbol table. 46 47 func putelfstr(s string) int { 48 if len(Elfstrdat) == 0 && s != "" { 49 // first entry must be empty string 50 putelfstr("") 51 } 52 53 off := len(Elfstrdat) 54 Elfstrdat = append(Elfstrdat, s...) 55 Elfstrdat = append(Elfstrdat, 0) 56 return off 57 } 58 59 func putelfsyment(out *OutBuf, off int, addr int64, size int64, info uint8, shndx elf.SectionIndex, other int) { 60 if elf64 { 61 out.Write32(uint32(off)) 62 out.Write8(info) 63 out.Write8(uint8(other)) 64 out.Write16(uint16(shndx)) 65 out.Write64(uint64(addr)) 66 out.Write64(uint64(size)) 67 symSize += ELF64SYMSIZE 68 } else { 69 out.Write32(uint32(off)) 70 out.Write32(uint32(addr)) 71 out.Write32(uint32(size)) 72 out.Write8(info) 73 out.Write8(uint8(other)) 74 out.Write16(uint16(shndx)) 75 symSize += ELF32SYMSIZE 76 } 77 } 78 79 func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) { 80 ldr := ctxt.loader 81 addr := ldr.SymValue(x) 82 size := ldr.SymSize(x) 83 84 xo := x 85 if ldr.OuterSym(x) != 0 { 86 xo = ldr.OuterSym(x) 87 } 88 xot := ldr.SymType(xo) 89 xosect := ldr.SymSect(xo) 90 91 var elfshnum elf.SectionIndex 92 if xot == sym.SDYNIMPORT || xot == sym.SHOSTOBJ || xot == sym.SUNDEFEXT { 93 elfshnum = elf.SHN_UNDEF 94 size = 0 95 } else { 96 if xosect == nil { 97 ldr.Errorf(x, "missing section in putelfsym") 98 return 99 } 100 if xosect.Elfsect == nil { 101 ldr.Errorf(x, "missing ELF section in putelfsym") 102 return 103 } 104 elfshnum = xosect.Elfsect.(*ElfShdr).shnum 105 } 106 107 sname := ldr.SymExtname(x) 108 sname = mangleABIName(ctxt, ldr, x, sname) 109 110 // One pass for each binding: elf.STB_LOCAL, elf.STB_GLOBAL, 111 // maybe one day elf.STB_WEAK. 112 bind := elf.STB_GLOBAL 113 if ldr.IsFileLocal(x) && !isStaticTmp(sname) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) { 114 // Static tmp is package local, but a package can be shared among multiple DSOs. 115 // They need to have a single view of the static tmp that are writable. 116 bind = elf.STB_LOCAL 117 } 118 119 // In external linking mode, we have to invoke gcc with -rdynamic 120 // to get the exported symbols put into the dynamic symbol table. 121 // To avoid filling the dynamic table with lots of unnecessary symbols, 122 // mark all Go symbols local (not global) in the final executable. 123 // But when we're dynamically linking, we need all those global symbols. 124 if !ctxt.DynlinkingGo() && ctxt.IsExternal() && !ldr.AttrCgoExportStatic(x) && elfshnum != elf.SHN_UNDEF { 125 bind = elf.STB_LOCAL 126 } 127 128 if ctxt.LinkMode == LinkExternal && elfshnum != elf.SHN_UNDEF { 129 addr -= int64(xosect.Vaddr) 130 } 131 other := int(elf.STV_DEFAULT) 132 if ldr.AttrVisibilityHidden(x) { 133 // TODO(mwhudson): We only set AttrVisibilityHidden in ldelf, i.e. when 134 // internally linking. But STV_HIDDEN visibility only matters in object 135 // files and shared libraries, and as we are a long way from implementing 136 // internal linking for shared libraries and only create object files when 137 // externally linking, I don't think this makes a lot of sense. 138 other = int(elf.STV_HIDDEN) 139 } 140 if ctxt.IsPPC64() && typ == elf.STT_FUNC && ldr.AttrShared(x) && ldr.SymName(x) != "runtime.duffzero" && ldr.SymName(x) != "runtime.duffcopy" { 141 // On ppc64 the top three bits of the st_other field indicate how 142 // many instructions separate the global and local entry points. In 143 // our case it is two instructions, indicated by the value 3. 144 // The conditions here match those in preprocess in 145 // cmd/internal/obj/ppc64/obj9.go, which is where the 146 // instructions are inserted. 147 other |= 3 << 5 148 } 149 150 // When dynamically linking, we create Symbols by reading the names from 151 // the symbol tables of the shared libraries and so the names need to 152 // match exactly. Tools like DTrace will have to wait for now. 153 if !ctxt.DynlinkingGo() { 154 // Rewrite · to . for ASCII-only tools like DTrace (sigh) 155 sname = strings.Replace(sname, "·", ".", -1) 156 } 157 158 if ctxt.DynlinkingGo() && bind == elf.STB_GLOBAL && curbind == elf.STB_LOCAL && ldr.SymType(x) == sym.STEXT { 159 // When dynamically linking, we want references to functions defined 160 // in this module to always be to the function object, not to the 161 // PLT. We force this by writing an additional local symbol for every 162 // global function symbol and making all relocations against the 163 // global symbol refer to this local symbol instead (see 164 // (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the 165 // ELF linker -Bsymbolic-functions option, but that is buggy on 166 // several platforms. 167 putelfsyment(ctxt.Out, putelfstr("local."+sname), addr, size, elf.ST_INFO(elf.STB_LOCAL, typ), elfshnum, other) 168 ldr.SetSymLocalElfSym(x, int32(ctxt.numelfsym)) 169 ctxt.numelfsym++ 170 return 171 } else if bind != curbind { 172 return 173 } 174 175 putelfsyment(ctxt.Out, putelfstr(sname), addr, size, elf.ST_INFO(bind, typ), elfshnum, other) 176 ldr.SetSymElfSym(x, int32(ctxt.numelfsym)) 177 ctxt.numelfsym++ 178 } 179 180 func putelfsectionsym(ctxt *Link, out *OutBuf, s loader.Sym, shndx elf.SectionIndex) { 181 putelfsyment(out, 0, 0, 0, elf.ST_INFO(elf.STB_LOCAL, elf.STT_SECTION), shndx, 0) 182 ctxt.loader.SetSymElfSym(s, int32(ctxt.numelfsym)) 183 ctxt.numelfsym++ 184 } 185 186 func genelfsym(ctxt *Link, elfbind elf.SymBind) { 187 ldr := ctxt.loader 188 189 // runtime.text marker symbol(s). 190 s := ldr.Lookup("runtime.text", 0) 191 putelfsym(ctxt, s, elf.STT_FUNC, elfbind) 192 for k, sect := range Segtext.Sections[1:] { 193 n := k + 1 194 if sect.Name != ".text" || (ctxt.IsAIX() && ctxt.IsExternal()) { 195 // On AIX, runtime.text.X are symbols already in the symtab. 196 break 197 } 198 s = ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) 199 if s == 0 { 200 break 201 } 202 if ldr.SymType(s) != sym.STEXT { 203 panic("unexpected type for runtime.text symbol") 204 } 205 putelfsym(ctxt, s, elf.STT_FUNC, elfbind) 206 } 207 208 // Text symbols. 209 for _, s := range ctxt.Textp { 210 putelfsym(ctxt, s, elf.STT_FUNC, elfbind) 211 } 212 213 // runtime.etext marker symbol. 214 s = ldr.Lookup("runtime.etext", 0) 215 if ldr.SymType(s) == sym.STEXT { 216 putelfsym(ctxt, s, elf.STT_FUNC, elfbind) 217 } 218 219 shouldBeInSymbolTable := func(s loader.Sym) bool { 220 if ldr.AttrNotInSymbolTable(s) { 221 return false 222 } 223 // FIXME: avoid having to do name inspections here. 224 // NB: the restrictions below on file local symbols are a bit 225 // arbitrary -- if it turns out we need nameless static 226 // symbols they could be relaxed/removed. 227 sn := ldr.SymName(s) 228 if (sn == "" || sn[0] == '.') && ldr.IsFileLocal(s) { 229 panic(fmt.Sprintf("unexpected file local symbol %d %s<%d>\n", 230 s, sn, ldr.SymVersion(s))) 231 } 232 if (sn == "" || sn[0] == '.') && !ldr.IsFileLocal(s) { 233 return false 234 } 235 return true 236 } 237 238 // Data symbols. 239 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ { 240 if !ldr.AttrReachable(s) { 241 continue 242 } 243 st := ldr.SymType(s) 244 if st >= sym.SELFRXSECT && st < sym.SXREF { 245 typ := elf.STT_OBJECT 246 if st == sym.STLSBSS { 247 if ctxt.IsInternal() { 248 continue 249 } 250 typ = elf.STT_TLS 251 } 252 if !shouldBeInSymbolTable(s) { 253 continue 254 } 255 putelfsym(ctxt, s, typ, elfbind) 256 continue 257 } 258 if st == sym.SHOSTOBJ || st == sym.SDYNIMPORT || st == sym.SUNDEFEXT { 259 putelfsym(ctxt, s, ldr.SymElfType(s), elfbind) 260 } 261 } 262 } 263 264 func asmElfSym(ctxt *Link) { 265 266 // the first symbol entry is reserved 267 putelfsyment(ctxt.Out, 0, 0, 0, elf.ST_INFO(elf.STB_LOCAL, elf.STT_NOTYPE), 0, 0) 268 269 dwarfaddelfsectionsyms(ctxt) 270 271 // Some linkers will add a FILE sym if one is not present. 272 // Avoid having the working directory inserted into the symbol table. 273 // It is added with a name to avoid problems with external linking 274 // encountered on some versions of Solaris. See issue #14957. 275 putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, elf.ST_INFO(elf.STB_LOCAL, elf.STT_FILE), elf.SHN_ABS, 0) 276 ctxt.numelfsym++ 277 278 bindings := []elf.SymBind{elf.STB_LOCAL, elf.STB_GLOBAL} 279 for _, elfbind := range bindings { 280 if elfbind == elf.STB_GLOBAL { 281 elfglobalsymndx = ctxt.numelfsym 282 } 283 genelfsym(ctxt, elfbind) 284 } 285 } 286 287 func putplan9sym(ctxt *Link, ldr *loader.Loader, s loader.Sym, char SymbolType) { 288 t := int(char) 289 if ldr.IsFileLocal(s) { 290 t += 'a' - 'A' 291 } 292 l := 4 293 addr := ldr.SymValue(s) 294 if ctxt.IsAMD64() && !flag8 { 295 ctxt.Out.Write32b(uint32(addr >> 32)) 296 l = 8 297 } 298 299 ctxt.Out.Write32b(uint32(addr)) 300 ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */ 301 302 name := ldr.SymName(s) 303 name = mangleABIName(ctxt, ldr, s, name) 304 ctxt.Out.WriteString(name) 305 ctxt.Out.Write8(0) 306 307 symSize += int32(l) + 1 + int32(len(name)) + 1 308 } 309 310 func asmbPlan9Sym(ctxt *Link) { 311 ldr := ctxt.loader 312 313 // Add special runtime.text and runtime.etext symbols. 314 s := ldr.Lookup("runtime.text", 0) 315 if ldr.SymType(s) == sym.STEXT { 316 putplan9sym(ctxt, ldr, s, TextSym) 317 } 318 s = ldr.Lookup("runtime.etext", 0) 319 if ldr.SymType(s) == sym.STEXT { 320 putplan9sym(ctxt, ldr, s, TextSym) 321 } 322 323 // Add text symbols. 324 for _, s := range ctxt.Textp { 325 putplan9sym(ctxt, ldr, s, TextSym) 326 } 327 328 shouldBeInSymbolTable := func(s loader.Sym) bool { 329 if ldr.AttrNotInSymbolTable(s) { 330 return false 331 } 332 name := ldr.SymName(s) // TODO: try not to read the name 333 if name == "" || name[0] == '.' { 334 return false 335 } 336 return true 337 } 338 339 // Add data symbols and external references. 340 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ { 341 if !ldr.AttrReachable(s) { 342 continue 343 } 344 t := ldr.SymType(s) 345 if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata 346 if t == sym.STLSBSS { 347 continue 348 } 349 if !shouldBeInSymbolTable(s) { 350 continue 351 } 352 char := DataSym 353 if t == sym.SBSS || t == sym.SNOPTRBSS { 354 char = BSSSym 355 } 356 putplan9sym(ctxt, ldr, s, char) 357 } 358 } 359 } 360 361 type byPkg []*sym.Library 362 363 func (libs byPkg) Len() int { 364 return len(libs) 365 } 366 367 func (libs byPkg) Less(a, b int) bool { 368 return libs[a].Pkg < libs[b].Pkg 369 } 370 371 func (libs byPkg) Swap(a, b int) { 372 libs[a], libs[b] = libs[b], libs[a] 373 } 374 375 // Create a table with information on the text sections. 376 // Return the symbol of the table, and number of sections. 377 func textsectionmap(ctxt *Link) (loader.Sym, uint32) { 378 ldr := ctxt.loader 379 t := ldr.CreateSymForUpdate("runtime.textsectionmap", 0) 380 t.SetType(sym.SRODATA) 381 nsections := int64(0) 382 383 for _, sect := range Segtext.Sections { 384 if sect.Name == ".text" { 385 nsections++ 386 } else { 387 break 388 } 389 } 390 t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize)) 391 392 off := int64(0) 393 n := 0 394 395 // The vaddr for each text section is the difference between the section's 396 // Vaddr and the Vaddr for the first text section as determined at compile 397 // time. 398 399 // The symbol for the first text section is named runtime.text as before. 400 // Additional text sections are named runtime.text.n where n is the 401 // order of creation starting with 1. These symbols provide the section's 402 // address after relocation by the linker. 403 404 textbase := Segtext.Sections[0].Vaddr 405 for _, sect := range Segtext.Sections { 406 if sect.Name != ".text" { 407 break 408 } 409 // The fields written should match runtime/symtab.go:textsect. 410 // They are designed to minimize runtime calculations. 411 vaddr := sect.Vaddr - textbase 412 off = t.SetUint(ctxt.Arch, off, vaddr) // field vaddr 413 end := vaddr + sect.Length 414 off = t.SetUint(ctxt.Arch, off, end) // field end 415 name := "runtime.text" 416 if n != 0 { 417 name = fmt.Sprintf("runtime.text.%d", n) 418 } 419 s := ldr.Lookup(name, 0) 420 if s == 0 { 421 ctxt.Errorf(s, "Unable to find symbol %s\n", name) 422 } 423 off = t.SetAddr(ctxt.Arch, off, s) // field baseaddr 424 n++ 425 } 426 return t.Sym(), uint32(n) 427 } 428 429 func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { 430 ldr := ctxt.loader 431 432 if !ctxt.IsAIX() { 433 switch ctxt.BuildMode { 434 case BuildModeCArchive, BuildModeCShared: 435 s := ldr.Lookup(*flagEntrySymbol, sym.SymVerABI0) 436 if s != 0 { 437 addinitarrdata(ctxt, ldr, s) 438 } 439 } 440 } 441 442 // Define these so that they'll get put into the symbol table. 443 // data.c:/^address will provide the actual values. 444 ctxt.xdefine("runtime.rodata", sym.SRODATA, 0) 445 ctxt.xdefine("runtime.erodata", sym.SRODATA, 0) 446 ctxt.xdefine("runtime.types", sym.SRODATA, 0) 447 ctxt.xdefine("runtime.etypes", sym.SRODATA, 0) 448 ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0) 449 ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0) 450 ctxt.xdefine("runtime.data", sym.SDATA, 0) 451 ctxt.xdefine("runtime.edata", sym.SDATA, 0) 452 ctxt.xdefine("runtime.bss", sym.SBSS, 0) 453 ctxt.xdefine("runtime.ebss", sym.SBSS, 0) 454 ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0) 455 ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0) 456 ctxt.xdefine("runtime.covctrs", sym.SNOPTRBSS, 0) 457 ctxt.xdefine("runtime.ecovctrs", sym.SNOPTRBSS, 0) 458 ctxt.xdefine("runtime.end", sym.SBSS, 0) 459 ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0) 460 ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0) 461 462 // garbage collection symbols 463 s := ldr.CreateSymForUpdate("runtime.gcdata", 0) 464 s.SetType(sym.SRODATA) 465 s.SetSize(0) 466 ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0) 467 468 s = ldr.CreateSymForUpdate("runtime.gcbss", 0) 469 s.SetType(sym.SRODATA) 470 s.SetSize(0) 471 ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0) 472 473 // pseudo-symbols to mark locations of type, string, and go string data. 474 var symtype, symtyperel loader.Sym 475 if !ctxt.DynlinkingGo() { 476 if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) { 477 s = ldr.CreateSymForUpdate("type:*", 0) 478 s.SetType(sym.STYPE) 479 s.SetSize(0) 480 s.SetAlign(int32(ctxt.Arch.PtrSize)) 481 symtype = s.Sym() 482 483 s = ldr.CreateSymForUpdate("typerel.*", 0) 484 s.SetType(sym.STYPERELRO) 485 s.SetSize(0) 486 s.SetAlign(int32(ctxt.Arch.PtrSize)) 487 symtyperel = s.Sym() 488 } else { 489 s = ldr.CreateSymForUpdate("type:*", 0) 490 s.SetType(sym.STYPE) 491 s.SetSize(0) 492 s.SetAlign(int32(ctxt.Arch.PtrSize)) 493 symtype = s.Sym() 494 symtyperel = s.Sym() 495 } 496 setCarrierSym(sym.STYPE, symtype) 497 setCarrierSym(sym.STYPERELRO, symtyperel) 498 } 499 500 groupSym := func(name string, t sym.SymKind) loader.Sym { 501 s := ldr.CreateSymForUpdate(name, 0) 502 s.SetType(t) 503 s.SetSize(0) 504 s.SetAlign(int32(ctxt.Arch.PtrSize)) 505 s.SetLocal(true) 506 setCarrierSym(t, s.Sym()) 507 return s.Sym() 508 } 509 var ( 510 symgostring = groupSym("go:string.*", sym.SGOSTRING) 511 symgofunc = groupSym("go:func.*", sym.SGOFUNC) 512 symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) 513 ) 514 515 symgofuncrel := symgofunc 516 if ctxt.UseRelro() { 517 symgofuncrel = groupSym("go:funcrel.*", sym.SGOFUNCRELRO) 518 } 519 520 symt := ldr.CreateSymForUpdate("runtime.symtab", 0) 521 symt.SetType(sym.SSYMTAB) 522 symt.SetSize(0) 523 symt.SetLocal(true) 524 525 // assign specific types so that they sort together. 526 // within a type they sort by size, so the .* symbols 527 // just defined above will be first. 528 // hide the specific symbols. 529 // Some of these symbol section conditions are duplicated 530 // in cmd/internal/obj.contentHashSection. 531 nsym := loader.Sym(ldr.NSym()) 532 symGroupType := make([]sym.SymKind, nsym) 533 for s := loader.Sym(1); s < nsym; s++ { 534 if (!ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) && ldr.SymPkg(s) != "") || (ctxt.LinkMode == LinkInternal && ldr.SymType(s) == sym.SCOVERAGE_COUNTER) { 535 ldr.SetAttrNotInSymbolTable(s, true) 536 } 537 if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) { 538 continue 539 } 540 541 name := ldr.SymName(s) 542 switch { 543 case strings.HasPrefix(name, "go:string."): 544 symGroupType[s] = sym.SGOSTRING 545 ldr.SetAttrNotInSymbolTable(s, true) 546 ldr.SetCarrierSym(s, symgostring) 547 548 case strings.HasPrefix(name, "runtime.gcbits."), 549 strings.HasPrefix(name, "type:.gcprog."): 550 symGroupType[s] = sym.SGCBITS 551 ldr.SetAttrNotInSymbolTable(s, true) 552 ldr.SetCarrierSym(s, symgcbits) 553 554 case strings.HasSuffix(name, "·f"): 555 if !ctxt.DynlinkingGo() { 556 ldr.SetAttrNotInSymbolTable(s, true) 557 } 558 if ctxt.UseRelro() { 559 symGroupType[s] = sym.SGOFUNCRELRO 560 if !ctxt.DynlinkingGo() { 561 ldr.SetCarrierSym(s, symgofuncrel) 562 } 563 } else { 564 symGroupType[s] = sym.SGOFUNC 565 ldr.SetCarrierSym(s, symgofunc) 566 } 567 568 case strings.HasPrefix(name, "gcargs."), 569 strings.HasPrefix(name, "gclocals."), 570 strings.HasPrefix(name, "gclocals·"), 571 ldr.SymType(s) == sym.SGOFUNC && s != symgofunc, // inltree, see pcln.go 572 strings.HasSuffix(name, ".opendefer"), 573 strings.HasSuffix(name, ".arginfo0"), 574 strings.HasSuffix(name, ".arginfo1"), 575 strings.HasSuffix(name, ".argliveinfo"), 576 strings.HasSuffix(name, ".wrapinfo"), 577 strings.HasSuffix(name, ".args_stackmap"), 578 strings.HasSuffix(name, ".stkobj"): 579 ldr.SetAttrNotInSymbolTable(s, true) 580 symGroupType[s] = sym.SGOFUNC 581 ldr.SetCarrierSym(s, symgofunc) 582 if ctxt.Debugvlog != 0 { 583 align := ldr.SymAlign(s) 584 liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) 585 } 586 587 // Note: Check for "type:" prefix after checking for .arginfo1 suffix. 588 // That way symbols like "type:.eq.[2]interface {}.arginfo1" that belong 589 // in go:func.* end up there. 590 case strings.HasPrefix(name, "type:"): 591 if !ctxt.DynlinkingGo() { 592 ldr.SetAttrNotInSymbolTable(s, true) 593 } 594 if ctxt.UseRelro() { 595 symGroupType[s] = sym.STYPERELRO 596 if symtyperel != 0 { 597 ldr.SetCarrierSym(s, symtyperel) 598 } 599 } else { 600 symGroupType[s] = sym.STYPE 601 if symtyperel != 0 { 602 ldr.SetCarrierSym(s, symtype) 603 } 604 } 605 } 606 } 607 608 if ctxt.BuildMode == BuildModeShared { 609 abihashgostr := ldr.CreateSymForUpdate("go:link.abihash."+filepath.Base(*flagOutfile), 0) 610 abihashgostr.SetType(sym.SRODATA) 611 hashsym := ldr.LookupOrCreateSym("go:link.abihashbytes", 0) 612 abihashgostr.AddAddr(ctxt.Arch, hashsym) 613 abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym))) 614 } 615 if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() { 616 for _, l := range ctxt.Library { 617 s := ldr.CreateSymForUpdate("go:link.pkghashbytes."+l.Pkg, 0) 618 s.SetType(sym.SRODATA) 619 s.SetSize(int64(len(l.Fingerprint))) 620 s.SetData(l.Fingerprint[:]) 621 str := ldr.CreateSymForUpdate("go:link.pkghash."+l.Pkg, 0) 622 str.SetType(sym.SRODATA) 623 str.AddAddr(ctxt.Arch, s.Sym()) 624 str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint))) 625 } 626 } 627 628 textsectionmapSym, nsections := textsectionmap(ctxt) 629 630 // Information about the layout of the executable image for the 631 // runtime to use. Any changes here must be matched by changes to 632 // the definition of moduledata in runtime/symtab.go. 633 // This code uses several global variables that are set by pcln.go:pclntab. 634 moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata) 635 // The pcHeader 636 moduledata.AddAddr(ctxt.Arch, pcln.pcheader) 637 // The function name slice 638 moduledata.AddAddr(ctxt.Arch, pcln.funcnametab) 639 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.funcnametab))) 640 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.funcnametab))) 641 // The cutab slice 642 moduledata.AddAddr(ctxt.Arch, pcln.cutab) 643 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.cutab))) 644 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.cutab))) 645 // The filetab slice 646 moduledata.AddAddr(ctxt.Arch, pcln.filetab) 647 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab))) 648 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab))) 649 // The pctab slice 650 moduledata.AddAddr(ctxt.Arch, pcln.pctab) 651 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab))) 652 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab))) 653 // The pclntab slice 654 moduledata.AddAddr(ctxt.Arch, pcln.pclntab) 655 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pclntab))) 656 moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pclntab))) 657 // The ftab slice 658 moduledata.AddAddr(ctxt.Arch, pcln.pclntab) 659 moduledata.AddUint(ctxt.Arch, uint64(pcln.nfunc+1)) 660 moduledata.AddUint(ctxt.Arch, uint64(pcln.nfunc+1)) 661 // findfunctab 662 moduledata.AddAddr(ctxt.Arch, pcln.findfunctab) 663 // minpc, maxpc 664 moduledata.AddAddr(ctxt.Arch, pcln.firstFunc) 665 moduledata.AddAddrPlus(ctxt.Arch, pcln.lastFunc, ldr.SymSize(pcln.lastFunc)) 666 // pointers to specific parts of the module 667 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.text", 0)) 668 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etext", 0)) 669 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrdata", 0)) 670 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrdata", 0)) 671 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0)) 672 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.edata", 0)) 673 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.bss", 0)) 674 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0)) 675 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0)) 676 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0)) 677 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.covctrs", 0)) 678 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ecovctrs", 0)) 679 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0)) 680 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0)) 681 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0)) 682 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0)) 683 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0)) 684 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0)) 685 moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go:func.*", 0)) 686 687 if ctxt.IsAIX() && ctxt.IsExternal() { 688 // Add R_XCOFFREF relocation to prevent ld's garbage collection of 689 // the following symbols. They might not be referenced in the program. 690 addRef := func(name string) { 691 s := ldr.Lookup(name, 0) 692 if s == 0 { 693 return 694 } 695 r, _ := moduledata.AddRel(objabi.R_XCOFFREF) 696 r.SetSym(s) 697 r.SetSiz(uint8(ctxt.Arch.PtrSize)) 698 } 699 addRef("runtime.rodata") 700 addRef("runtime.erodata") 701 addRef("runtime.epclntab") 702 // As we use relative addressing for text symbols in functab, it is 703 // important that the offsets we computed stay unchanged by the external 704 // linker, i.e. all symbols in Textp should not be removed. 705 // Most of them are actually referenced (our deadcode pass ensures that), 706 // except go:buildid which is generated late and not used by the program. 707 addRef("go:buildid") 708 } 709 710 // text section information 711 moduledata.AddAddr(ctxt.Arch, textsectionmapSym) 712 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 713 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 714 715 // The typelinks slice 716 typelinkSym := ldr.Lookup("runtime.typelink", 0) 717 ntypelinks := uint64(ldr.SymSize(typelinkSym)) / 4 718 moduledata.AddAddr(ctxt.Arch, typelinkSym) 719 moduledata.AddUint(ctxt.Arch, ntypelinks) 720 moduledata.AddUint(ctxt.Arch, ntypelinks) 721 // The itablinks slice 722 itablinkSym := ldr.Lookup("runtime.itablink", 0) 723 nitablinks := uint64(ldr.SymSize(itablinkSym)) / uint64(ctxt.Arch.PtrSize) 724 moduledata.AddAddr(ctxt.Arch, itablinkSym) 725 moduledata.AddUint(ctxt.Arch, nitablinks) 726 moduledata.AddUint(ctxt.Arch, nitablinks) 727 // The ptab slice 728 if ptab := ldr.Lookup("go:plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) { 729 ldr.SetAttrLocal(ptab, true) 730 if ldr.SymType(ptab) != sym.SRODATA { 731 panic(fmt.Sprintf("go:plugin.tabs is %v, not SRODATA", ldr.SymType(ptab))) 732 } 733 nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff) 734 moduledata.AddAddr(ctxt.Arch, ptab) 735 moduledata.AddUint(ctxt.Arch, nentries) 736 moduledata.AddUint(ctxt.Arch, nentries) 737 } else { 738 moduledata.AddUint(ctxt.Arch, 0) 739 moduledata.AddUint(ctxt.Arch, 0) 740 moduledata.AddUint(ctxt.Arch, 0) 741 } 742 if ctxt.BuildMode == BuildModePlugin { 743 addgostring(ctxt, ldr, moduledata, "go:link.thispluginpath", objabi.PathToPrefix(*flagPluginPath)) 744 745 pkghashes := ldr.CreateSymForUpdate("go:link.pkghashes", 0) 746 pkghashes.SetLocal(true) 747 pkghashes.SetType(sym.SRODATA) 748 749 for i, l := range ctxt.Library { 750 // pkghashes[i].name 751 addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkgname.%d", i), l.Pkg) 752 // pkghashes[i].linktimehash 753 addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkglinkhash.%d", i), string(l.Fingerprint[:])) 754 // pkghashes[i].runtimehash 755 hash := ldr.Lookup("go:link.pkghash."+l.Pkg, 0) 756 pkghashes.AddAddr(ctxt.Arch, hash) 757 } 758 moduledata.AddAddr(ctxt.Arch, pkghashes.Sym()) 759 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 760 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 761 } else { 762 moduledata.AddUint(ctxt.Arch, 0) // pluginpath 763 moduledata.AddUint(ctxt.Arch, 0) 764 moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice 765 moduledata.AddUint(ctxt.Arch, 0) 766 moduledata.AddUint(ctxt.Arch, 0) 767 } 768 if len(ctxt.Shlibs) > 0 { 769 thismodulename := filepath.Base(*flagOutfile) 770 switch ctxt.BuildMode { 771 case BuildModeExe, BuildModePIE: 772 // When linking an executable, outfile is just "a.out". Make 773 // it something slightly more comprehensible. 774 thismodulename = "the executable" 775 } 776 addgostring(ctxt, ldr, moduledata, "go:link.thismodulename", thismodulename) 777 778 modulehashes := ldr.CreateSymForUpdate("go:link.abihashes", 0) 779 modulehashes.SetLocal(true) 780 modulehashes.SetType(sym.SRODATA) 781 782 for i, shlib := range ctxt.Shlibs { 783 // modulehashes[i].modulename 784 modulename := filepath.Base(shlib.Path) 785 addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.libname.%d", i), modulename) 786 787 // modulehashes[i].linktimehash 788 addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.linkhash.%d", i), string(shlib.Hash)) 789 790 // modulehashes[i].runtimehash 791 abihash := ldr.LookupOrCreateSym("go:link.abihash."+modulename, 0) 792 ldr.SetAttrReachable(abihash, true) 793 modulehashes.AddAddr(ctxt.Arch, abihash) 794 } 795 796 moduledata.AddAddr(ctxt.Arch, modulehashes.Sym()) 797 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 798 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 799 } else { 800 moduledata.AddUint(ctxt.Arch, 0) // modulename 801 moduledata.AddUint(ctxt.Arch, 0) 802 moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice 803 moduledata.AddUint(ctxt.Arch, 0) 804 moduledata.AddUint(ctxt.Arch, 0) 805 } 806 807 hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE 808 if hasmain { 809 moduledata.AddUint8(1) 810 } else { 811 moduledata.AddUint8(0) 812 } 813 814 // The rest of moduledata is zero initialized. 815 // When linking an object that does not contain the runtime we are 816 // creating the moduledata from scratch and it does not have a 817 // compiler-provided size, so read it from the type data. 818 moduledatatype := ldr.Lookup("type:runtime.moduledata", 0) 819 moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype))) 820 moduledata.Grow(moduledata.Size()) 821 822 lastmoduledatap := ldr.CreateSymForUpdate("runtime.lastmoduledatap", 0) 823 if lastmoduledatap.Type() != sym.SDYNIMPORT { 824 lastmoduledatap.SetType(sym.SNOPTRDATA) 825 lastmoduledatap.SetSize(0) // overwrite existing value 826 lastmoduledatap.SetData(nil) 827 lastmoduledatap.AddAddr(ctxt.Arch, moduledata.Sym()) 828 } 829 return symGroupType 830 } 831 832 // CarrierSymByType tracks carrier symbols and their sizes. 833 var CarrierSymByType [sym.SXREF]struct { 834 Sym loader.Sym 835 Size int64 836 } 837 838 func setCarrierSym(typ sym.SymKind, s loader.Sym) { 839 if CarrierSymByType[typ].Sym != 0 { 840 panic(fmt.Sprintf("carrier symbol for type %v already set", typ)) 841 } 842 CarrierSymByType[typ].Sym = s 843 } 844 845 func setCarrierSize(typ sym.SymKind, sz int64) { 846 if CarrierSymByType[typ].Size != 0 { 847 panic(fmt.Sprintf("carrier symbol size for type %v already set", typ)) 848 } 849 CarrierSymByType[typ].Size = sz 850 } 851 852 func isStaticTmp(name string) bool { 853 return strings.Contains(name, "."+obj.StaticNamePref) 854 } 855 856 // Mangle function name with ABI information. 857 func mangleABIName(ctxt *Link, ldr *loader.Loader, x loader.Sym, name string) string { 858 // For functions with ABI wrappers, we have to make sure that we 859 // don't wind up with two symbol table entries with the same 860 // name (since this will generated an error from the external 861 // linker). If we have wrappers, keep the ABIInternal name 862 // unmangled since we want cross-load-module calls to target 863 // ABIInternal, and rename other symbols. 864 // 865 // TODO: avoid the ldr.Lookup calls below by instead using an aux 866 // sym or marker relocation to associate the wrapper with the 867 // wrapped function. 868 if !buildcfg.Experiment.RegabiWrappers { 869 return name 870 } 871 872 if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) != sym.SymVerABIInternal && ldr.SymVersion(x) < sym.SymVerStatic { 873 if s2 := ldr.Lookup(name, sym.SymVerABIInternal); s2 != 0 && ldr.SymType(s2) == sym.STEXT { 874 name = fmt.Sprintf("%s.abi%d", name, ldr.SymVersion(x)) 875 } 876 } 877 878 // When loading a shared library, if a symbol has only one ABI, 879 // and the name is not mangled, we don't know what ABI it is. 880 // So we always mangle ABIInternal function name in shared linkage, 881 // except symbols that are exported to C. Type symbols are always 882 // ABIInternal so they are not mangled. 883 if ctxt.IsShared() { 884 if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) == sym.SymVerABIInternal && !ldr.AttrCgoExport(x) && !strings.HasPrefix(name, "type:") { 885 name = fmt.Sprintf("%s.abiinternal", name) 886 } 887 } 888 889 return name 890 }