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