github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/internal/ld/symtab.go (about) 1 // Inferno utils/6l/span.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/default/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/gagliardetto/golang-go/cmd/internal/objabi" 35 "github.com/gagliardetto/golang-go/cmd/internal/sys" 36 "github.com/gagliardetto/golang-go/cmd/link/internal/sym" 37 "fmt" 38 "path/filepath" 39 "strings" 40 ) 41 42 // Symbol table. 43 44 func putelfstr(s string) int { 45 if len(Elfstrdat) == 0 && s != "" { 46 // first entry must be empty string 47 putelfstr("") 48 } 49 50 off := len(Elfstrdat) 51 Elfstrdat = append(Elfstrdat, s...) 52 Elfstrdat = append(Elfstrdat, 0) 53 return off 54 } 55 56 func putelfsyment(out *OutBuf, off int, addr int64, size int64, info int, shndx int, other int) { 57 if elf64 { 58 out.Write32(uint32(off)) 59 out.Write8(uint8(info)) 60 out.Write8(uint8(other)) 61 out.Write16(uint16(shndx)) 62 out.Write64(uint64(addr)) 63 out.Write64(uint64(size)) 64 Symsize += ELF64SYMSIZE 65 } else { 66 out.Write32(uint32(off)) 67 out.Write32(uint32(addr)) 68 out.Write32(uint32(size)) 69 out.Write8(uint8(info)) 70 out.Write8(uint8(other)) 71 out.Write16(uint16(shndx)) 72 Symsize += ELF32SYMSIZE 73 } 74 } 75 76 var numelfsym = 1 // 0 is reserved 77 78 var elfbind int 79 80 func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go_ *sym.Symbol) { 81 var typ int 82 83 switch t { 84 default: 85 return 86 87 case TextSym: 88 typ = STT_FUNC 89 90 case DataSym, BSSSym: 91 typ = STT_OBJECT 92 93 case UndefinedSym: 94 // ElfType is only set for symbols read from Go shared libraries, but 95 // for other symbols it is left as STT_NOTYPE which is fine. 96 typ = int(x.ElfType()) 97 98 case TLSSym: 99 typ = STT_TLS 100 } 101 102 size := x.Size 103 if t == UndefinedSym { 104 size = 0 105 } 106 107 xo := x 108 for xo.Outer != nil { 109 xo = xo.Outer 110 } 111 112 var elfshnum int 113 if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ || xo.Type == sym.SUNDEFEXT { 114 elfshnum = SHN_UNDEF 115 } else { 116 if xo.Sect == nil { 117 Errorf(x, "missing section in putelfsym") 118 return 119 } 120 if xo.Sect.Elfsect == nil { 121 Errorf(x, "missing ELF section in putelfsym") 122 return 123 } 124 elfshnum = xo.Sect.Elfsect.(*ElfShdr).shnum 125 } 126 127 // One pass for each binding: STB_LOCAL, STB_GLOBAL, 128 // maybe one day STB_WEAK. 129 bind := STB_GLOBAL 130 131 if x.IsFileLocal() || x.Attr.VisibilityHidden() || x.Attr.Local() { 132 bind = STB_LOCAL 133 } 134 135 // In external linking mode, we have to invoke gcc with -rdynamic 136 // to get the exported symbols put into the dynamic symbol table. 137 // To avoid filling the dynamic table with lots of unnecessary symbols, 138 // mark all Go symbols local (not global) in the final executable. 139 // But when we're dynamically linking, we need all those global symbols. 140 if !ctxt.DynlinkingGo() && ctxt.LinkMode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF { 141 bind = STB_LOCAL 142 } 143 144 if ctxt.LinkMode == LinkExternal && elfshnum != SHN_UNDEF { 145 addr -= int64(xo.Sect.Vaddr) 146 } 147 other := STV_DEFAULT 148 if x.Attr.VisibilityHidden() { 149 // TODO(mwhudson): We only set AttrVisibilityHidden in ldelf, i.e. when 150 // internally linking. But STV_HIDDEN visibility only matters in object 151 // files and shared libraries, and as we are a long way from implementing 152 // internal linking for shared libraries and only create object files when 153 // externally linking, I don't think this makes a lot of sense. 154 other = STV_HIDDEN 155 } 156 if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { 157 // On ppc64 the top three bits of the st_other field indicate how 158 // many instructions separate the global and local entry points. In 159 // our case it is two instructions, indicated by the value 3. 160 // The conditions here match those in preprocess in 161 // cmd/internal/obj/ppc64/obj9.go, which is where the 162 // instructions are inserted. 163 other |= 3 << 5 164 } 165 166 // When dynamically linking, we create Symbols by reading the names from 167 // the symbol tables of the shared libraries and so the names need to 168 // match exactly. Tools like DTrace will have to wait for now. 169 if !ctxt.DynlinkingGo() { 170 // Rewrite · to . for ASCII-only tools like DTrace (sigh) 171 s = strings.Replace(s, "·", ".", -1) 172 } 173 174 if ctxt.DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == sym.STEXT { 175 // When dynamically linking, we want references to functions defined 176 // in this module to always be to the function object, not to the 177 // PLT. We force this by writing an additional local symbol for every 178 // global function symbol and making all relocations against the 179 // global symbol refer to this local symbol instead (see 180 // (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the 181 // ELF linker -Bsymbolic-functions option, but that is buggy on 182 // several platforms. 183 putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other) 184 x.LocalElfsym = int32(numelfsym) 185 numelfsym++ 186 return 187 } else if bind != elfbind { 188 return 189 } 190 191 putelfsyment(ctxt.Out, putelfstr(s), addr, size, bind<<4|typ&0xf, elfshnum, other) 192 x.Elfsym = int32(numelfsym) 193 numelfsym++ 194 } 195 196 func putelfsectionsym(out *OutBuf, s *sym.Symbol, shndx int) { 197 putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0) 198 s.Elfsym = int32(numelfsym) 199 numelfsym++ 200 } 201 202 func Asmelfsym(ctxt *Link) { 203 // the first symbol entry is reserved 204 putelfsyment(ctxt.Out, 0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) 205 206 dwarfaddelfsectionsyms(ctxt) 207 208 // Some linkers will add a FILE sym if one is not present. 209 // Avoid having the working directory inserted into the symbol table. 210 // It is added with a name to avoid problems with external linking 211 // encountered on some versions of Solaris. See issue #14957. 212 putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0) 213 numelfsym++ 214 215 elfbind = STB_LOCAL 216 genasmsym(ctxt, putelfsym) 217 218 elfbind = STB_GLOBAL 219 elfglobalsymndx = numelfsym 220 genasmsym(ctxt, putelfsym) 221 } 222 223 func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64, go_ *sym.Symbol) { 224 t := int(typ) 225 switch typ { 226 case TextSym, DataSym, BSSSym: 227 if x.IsFileLocal() { 228 t += 'a' - 'A' 229 } 230 fallthrough 231 232 case AutoSym, ParamSym, FrameSym: 233 l := 4 234 if ctxt.HeadType == objabi.Hplan9 && ctxt.Arch.Family == sys.AMD64 && !Flag8 { 235 ctxt.Out.Write32b(uint32(addr >> 32)) 236 l = 8 237 } 238 239 ctxt.Out.Write32b(uint32(addr)) 240 ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */ 241 242 ctxt.Out.WriteString(s) 243 ctxt.Out.Write8(0) 244 245 Symsize += int32(l) + 1 + int32(len(s)) + 1 246 247 default: 248 return 249 } 250 } 251 252 func Asmplan9sym(ctxt *Link) { 253 genasmsym(ctxt, putplan9sym) 254 } 255 256 var symt *sym.Symbol 257 258 type byPkg []*sym.Library 259 260 func (libs byPkg) Len() int { 261 return len(libs) 262 } 263 264 func (libs byPkg) Less(a, b int) bool { 265 return libs[a].Pkg < libs[b].Pkg 266 } 267 268 func (libs byPkg) Swap(a, b int) { 269 libs[a], libs[b] = libs[b], libs[a] 270 } 271 272 // Create a table with information on the text sections. 273 274 func textsectionmap(ctxt *Link) uint32 { 275 276 t := ctxt.Syms.Lookup("runtime.textsectionmap", 0) 277 t.Type = sym.SRODATA 278 t.Attr |= sym.AttrReachable 279 nsections := int64(0) 280 281 for _, sect := range Segtext.Sections { 282 if sect.Name == ".text" { 283 nsections++ 284 } else { 285 break 286 } 287 } 288 t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize)) 289 290 off := int64(0) 291 n := 0 292 293 // The vaddr for each text section is the difference between the section's 294 // Vaddr and the Vaddr for the first text section as determined at compile 295 // time. 296 297 // The symbol for the first text section is named runtime.text as before. 298 // Additional text sections are named runtime.text.n where n is the 299 // order of creation starting with 1. These symbols provide the section's 300 // address after relocation by the linker. 301 302 textbase := Segtext.Sections[0].Vaddr 303 for _, sect := range Segtext.Sections { 304 if sect.Name != ".text" { 305 break 306 } 307 off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase) 308 off = t.SetUint(ctxt.Arch, off, sect.Length) 309 if n == 0 { 310 s := ctxt.Syms.ROLookup("runtime.text", 0) 311 if s == nil { 312 Errorf(nil, "Unable to find symbol runtime.text\n") 313 } 314 off = t.SetAddr(ctxt.Arch, off, s) 315 316 } else { 317 s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) 318 if s == nil { 319 Errorf(nil, "Unable to find symbol runtime.text.%d\n", n) 320 } 321 off = t.SetAddr(ctxt.Arch, off, s) 322 } 323 n++ 324 } 325 return uint32(n) 326 } 327 328 func (ctxt *Link) symtab() { 329 switch ctxt.BuildMode { 330 case BuildModeCArchive, BuildModeCShared: 331 for _, s := range ctxt.Syms.Allsym { 332 // Create a new entry in the .init_array section that points to the 333 // library initializer function. 334 if s.Name == *flagEntrySymbol && ctxt.HeadType != objabi.Haix { 335 addinitarrdata(ctxt, s) 336 } 337 } 338 } 339 340 // Define these so that they'll get put into the symbol table. 341 // data.c:/^address will provide the actual values. 342 ctxt.xdefine("runtime.text", sym.STEXT, 0) 343 344 ctxt.xdefine("runtime.etext", sym.STEXT, 0) 345 ctxt.xdefine("runtime.itablink", sym.SRODATA, 0) 346 ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0) 347 ctxt.xdefine("runtime.rodata", sym.SRODATA, 0) 348 ctxt.xdefine("runtime.erodata", sym.SRODATA, 0) 349 ctxt.xdefine("runtime.types", sym.SRODATA, 0) 350 ctxt.xdefine("runtime.etypes", sym.SRODATA, 0) 351 ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0) 352 ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0) 353 ctxt.xdefine("runtime.data", sym.SDATA, 0) 354 ctxt.xdefine("runtime.edata", sym.SDATA, 0) 355 ctxt.xdefine("runtime.bss", sym.SBSS, 0) 356 ctxt.xdefine("runtime.ebss", sym.SBSS, 0) 357 ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0) 358 ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0) 359 ctxt.xdefine("runtime.end", sym.SBSS, 0) 360 ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0) 361 ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0) 362 363 // garbage collection symbols 364 s := ctxt.Syms.Lookup("runtime.gcdata", 0) 365 366 s.Type = sym.SRODATA 367 s.Size = 0 368 s.Attr |= sym.AttrReachable 369 ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0) 370 371 s = ctxt.Syms.Lookup("runtime.gcbss", 0) 372 s.Type = sym.SRODATA 373 s.Size = 0 374 s.Attr |= sym.AttrReachable 375 ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0) 376 377 // pseudo-symbols to mark locations of type, string, and go string data. 378 var symtype *sym.Symbol 379 var symtyperel *sym.Symbol 380 if !ctxt.DynlinkingGo() { 381 if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) { 382 s = ctxt.Syms.Lookup("type.*", 0) 383 384 s.Type = sym.STYPE 385 s.Size = 0 386 s.Attr |= sym.AttrReachable 387 symtype = s 388 389 s = ctxt.Syms.Lookup("typerel.*", 0) 390 391 s.Type = sym.STYPERELRO 392 s.Size = 0 393 s.Attr |= sym.AttrReachable 394 symtyperel = s 395 } else { 396 s = ctxt.Syms.Lookup("type.*", 0) 397 398 s.Type = sym.STYPE 399 s.Size = 0 400 s.Attr |= sym.AttrReachable 401 symtype = s 402 symtyperel = s 403 } 404 } 405 406 groupSym := func(name string, t sym.SymKind) *sym.Symbol { 407 s := ctxt.Syms.Lookup(name, 0) 408 s.Type = t 409 s.Size = 0 410 s.Attr |= sym.AttrLocal | sym.AttrReachable 411 return s 412 } 413 var ( 414 symgostring = groupSym("go.string.*", sym.SGOSTRING) 415 symgofunc = groupSym("go.func.*", sym.SGOFUNC) 416 symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) 417 ) 418 419 var symgofuncrel *sym.Symbol 420 if !ctxt.DynlinkingGo() { 421 if ctxt.UseRelro() { 422 symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) 423 } else { 424 symgofuncrel = symgofunc 425 } 426 } 427 428 symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) 429 symitablink.Type = sym.SITABLINK 430 431 symt = ctxt.Syms.Lookup("runtime.symtab", 0) 432 symt.Attr |= sym.AttrLocal 433 symt.Type = sym.SSYMTAB 434 symt.Size = 0 435 symt.Attr |= sym.AttrReachable 436 437 nitablinks := 0 438 439 // assign specific types so that they sort together. 440 // within a type they sort by size, so the .* symbols 441 // just defined above will be first. 442 // hide the specific symbols. 443 for _, s := range ctxt.Syms.Allsym { 444 if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) { 445 s.Attr |= sym.AttrNotInSymbolTable 446 } 447 448 if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA { 449 continue 450 } 451 452 switch { 453 case strings.HasPrefix(s.Name, "type."): 454 if !ctxt.DynlinkingGo() { 455 s.Attr |= sym.AttrNotInSymbolTable 456 } 457 if ctxt.UseRelro() { 458 s.Type = sym.STYPERELRO 459 s.Outer = symtyperel 460 } else { 461 s.Type = sym.STYPE 462 s.Outer = symtype 463 } 464 465 case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro(): 466 // Keep go.importpath symbols in the same section as types and 467 // names, as they can be referred to by a section offset. 468 s.Type = sym.STYPERELRO 469 470 case strings.HasPrefix(s.Name, "go.itablink."): 471 nitablinks++ 472 s.Type = sym.SITABLINK 473 s.Attr |= sym.AttrNotInSymbolTable 474 s.Outer = symitablink 475 476 case strings.HasPrefix(s.Name, "go.string."): 477 s.Type = sym.SGOSTRING 478 s.Attr |= sym.AttrNotInSymbolTable 479 s.Outer = symgostring 480 481 case strings.HasPrefix(s.Name, "runtime.gcbits."): 482 s.Type = sym.SGCBITS 483 s.Attr |= sym.AttrNotInSymbolTable 484 s.Outer = symgcbits 485 486 case strings.HasSuffix(s.Name, "·f"): 487 if !ctxt.DynlinkingGo() { 488 s.Attr |= sym.AttrNotInSymbolTable 489 } 490 if ctxt.UseRelro() { 491 s.Type = sym.SGOFUNCRELRO 492 s.Outer = symgofuncrel 493 } else { 494 s.Type = sym.SGOFUNC 495 s.Outer = symgofunc 496 } 497 498 case strings.HasPrefix(s.Name, "gcargs."), 499 strings.HasPrefix(s.Name, "gclocals."), 500 strings.HasPrefix(s.Name, "gclocals·"), 501 strings.HasPrefix(s.Name, "inltree."), 502 strings.HasSuffix(s.Name, ".opendefer"): 503 s.Type = sym.SGOFUNC 504 s.Attr |= sym.AttrNotInSymbolTable 505 s.Outer = symgofunc 506 s.Align = 4 507 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 508 } 509 } 510 511 if ctxt.BuildMode == BuildModeShared { 512 abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) 513 abihashgostr.Attr |= sym.AttrReachable 514 abihashgostr.Type = sym.SRODATA 515 hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) 516 abihashgostr.AddAddr(ctxt.Arch, hashsym) 517 abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size)) 518 } 519 if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() { 520 for _, l := range ctxt.Library { 521 s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) 522 s.Attr |= sym.AttrReachable 523 s.Type = sym.SRODATA 524 s.Size = int64(len(l.Hash)) 525 s.P = []byte(l.Hash) 526 str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) 527 str.Attr |= sym.AttrReachable 528 str.Type = sym.SRODATA 529 str.AddAddr(ctxt.Arch, s) 530 str.AddUint(ctxt.Arch, uint64(len(l.Hash))) 531 } 532 } 533 534 nsections := textsectionmap(ctxt) 535 536 // Information about the layout of the executable image for the 537 // runtime to use. Any changes here must be matched by changes to 538 // the definition of moduledata in runtime/symtab.go. 539 // This code uses several global variables that are set by pcln.go:pclntab. 540 moduledata := ctxt.Moduledata 541 // The pclntab slice 542 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0)) 543 moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 544 moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 545 // The ftab slice 546 moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) 547 moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) 548 moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) 549 // The filetab slice 550 moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) 551 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1) 552 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1) 553 // findfunctab 554 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0)) 555 // minpc, maxpc 556 moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc) 557 moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size) 558 // pointers to specific parts of the module 559 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0)) 560 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0)) 561 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0)) 562 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) 563 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0)) 564 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0)) 565 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0)) 566 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0)) 567 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0)) 568 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) 569 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0)) 570 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0)) 571 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0)) 572 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0)) 573 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0)) 574 575 if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal { 576 // Add R_REF relocation to prevent ld's garbage collection of 577 // runtime.rodata, runtime.erodata and runtime.epclntab. 578 addRef := func(name string) { 579 r := moduledata.AddRel() 580 r.Sym = ctxt.Syms.Lookup(name, 0) 581 r.Type = objabi.R_XCOFFREF 582 r.Siz = uint8(ctxt.Arch.PtrSize) 583 } 584 addRef("runtime.rodata") 585 addRef("runtime.erodata") 586 addRef("runtime.epclntab") 587 } 588 589 // text section information 590 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) 591 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 592 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 593 594 // The typelinks slice 595 typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) 596 ntypelinks := uint64(typelinkSym.Size) / 4 597 moduledata.AddAddr(ctxt.Arch, typelinkSym) 598 moduledata.AddUint(ctxt.Arch, ntypelinks) 599 moduledata.AddUint(ctxt.Arch, ntypelinks) 600 // The itablinks slice 601 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0)) 602 moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) 603 moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) 604 // The ptab slice 605 if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { 606 ptab.Attr |= sym.AttrLocal 607 ptab.Type = sym.SRODATA 608 609 nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) 610 moduledata.AddAddr(ctxt.Arch, ptab) 611 moduledata.AddUint(ctxt.Arch, nentries) 612 moduledata.AddUint(ctxt.Arch, nentries) 613 } else { 614 moduledata.AddUint(ctxt.Arch, 0) 615 moduledata.AddUint(ctxt.Arch, 0) 616 moduledata.AddUint(ctxt.Arch, 0) 617 } 618 if ctxt.BuildMode == BuildModePlugin { 619 addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath)) 620 621 pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) 622 pkghashes.Attr |= sym.AttrReachable 623 pkghashes.Attr |= sym.AttrLocal 624 pkghashes.Type = sym.SRODATA 625 626 for i, l := range ctxt.Library { 627 // pkghashes[i].name 628 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) 629 // pkghashes[i].linktimehash 630 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash) 631 // pkghashes[i].runtimehash 632 hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0) 633 pkghashes.AddAddr(ctxt.Arch, hash) 634 } 635 moduledata.AddAddr(ctxt.Arch, pkghashes) 636 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 637 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 638 } else { 639 moduledata.AddUint(ctxt.Arch, 0) // pluginpath 640 moduledata.AddUint(ctxt.Arch, 0) 641 moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice 642 moduledata.AddUint(ctxt.Arch, 0) 643 moduledata.AddUint(ctxt.Arch, 0) 644 } 645 if len(ctxt.Shlibs) > 0 { 646 thismodulename := filepath.Base(*flagOutfile) 647 switch ctxt.BuildMode { 648 case BuildModeExe, BuildModePIE: 649 // When linking an executable, outfile is just "a.out". Make 650 // it something slightly more comprehensible. 651 thismodulename = "the executable" 652 } 653 addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) 654 655 modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) 656 modulehashes.Attr |= sym.AttrReachable 657 modulehashes.Attr |= sym.AttrLocal 658 modulehashes.Type = sym.SRODATA 659 660 for i, shlib := range ctxt.Shlibs { 661 // modulehashes[i].modulename 662 modulename := filepath.Base(shlib.Path) 663 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 664 665 // modulehashes[i].linktimehash 666 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 667 668 // modulehashes[i].runtimehash 669 abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) 670 abihash.Attr |= sym.AttrReachable 671 modulehashes.AddAddr(ctxt.Arch, abihash) 672 } 673 674 moduledata.AddAddr(ctxt.Arch, modulehashes) 675 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 676 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 677 } else { 678 moduledata.AddUint(ctxt.Arch, 0) // modulename 679 moduledata.AddUint(ctxt.Arch, 0) 680 moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice 681 moduledata.AddUint(ctxt.Arch, 0) 682 moduledata.AddUint(ctxt.Arch, 0) 683 } 684 685 hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE 686 if hasmain { 687 moduledata.AddUint8(1) 688 } else { 689 moduledata.AddUint8(0) 690 } 691 692 // The rest of moduledata is zero initialized. 693 // When linking an object that does not contain the runtime we are 694 // creating the moduledata from scratch and it does not have a 695 // compiler-provided size, so read it from the type data. 696 moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) 697 moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype.P) 698 moduledata.Grow(moduledata.Size) 699 700 lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) 701 if lastmoduledatap.Type != sym.SDYNIMPORT { 702 lastmoduledatap.Type = sym.SNOPTRDATA 703 lastmoduledatap.Size = 0 // overwrite existing value 704 lastmoduledatap.AddAddr(ctxt.Arch, moduledata) 705 } 706 } 707 708 func isStaticTemp(name string) bool { 709 if i := strings.LastIndex(name, "/"); i >= 0 { 710 name = name[i:] 711 } 712 return strings.Contains(name, "..stmp_") 713 }