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