github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/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 "cmd/internal/objabi" 35 "cmd/internal/sys" 36 "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 { 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 dosymtype(ctxt) 330 331 // Define these so that they'll get put into the symbol table. 332 // data.c:/^address will provide the actual values. 333 ctxt.xdefine("runtime.text", sym.STEXT, 0) 334 335 ctxt.xdefine("runtime.etext", sym.STEXT, 0) 336 ctxt.xdefine("runtime.itablink", sym.SRODATA, 0) 337 ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0) 338 ctxt.xdefine("runtime.rodata", sym.SRODATA, 0) 339 ctxt.xdefine("runtime.erodata", sym.SRODATA, 0) 340 ctxt.xdefine("runtime.types", sym.SRODATA, 0) 341 ctxt.xdefine("runtime.etypes", sym.SRODATA, 0) 342 ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0) 343 ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0) 344 ctxt.xdefine("runtime.data", sym.SDATA, 0) 345 ctxt.xdefine("runtime.edata", sym.SDATA, 0) 346 ctxt.xdefine("runtime.bss", sym.SBSS, 0) 347 ctxt.xdefine("runtime.ebss", sym.SBSS, 0) 348 ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0) 349 ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0) 350 ctxt.xdefine("runtime.end", sym.SBSS, 0) 351 ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0) 352 ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0) 353 354 // garbage collection symbols 355 s := ctxt.Syms.Lookup("runtime.gcdata", 0) 356 357 s.Type = sym.SRODATA 358 s.Size = 0 359 s.Attr |= sym.AttrReachable 360 ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0) 361 362 s = ctxt.Syms.Lookup("runtime.gcbss", 0) 363 s.Type = sym.SRODATA 364 s.Size = 0 365 s.Attr |= sym.AttrReachable 366 ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0) 367 368 // pseudo-symbols to mark locations of type, string, and go string data. 369 var symtype *sym.Symbol 370 var symtyperel *sym.Symbol 371 if !ctxt.DynlinkingGo() { 372 if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) { 373 s = ctxt.Syms.Lookup("type.*", 0) 374 375 s.Type = sym.STYPE 376 s.Size = 0 377 s.Attr |= sym.AttrReachable 378 symtype = s 379 380 s = ctxt.Syms.Lookup("typerel.*", 0) 381 382 s.Type = sym.STYPERELRO 383 s.Size = 0 384 s.Attr |= sym.AttrReachable 385 symtyperel = s 386 } else { 387 s = ctxt.Syms.Lookup("type.*", 0) 388 389 s.Type = sym.STYPE 390 s.Size = 0 391 s.Attr |= sym.AttrReachable 392 symtype = s 393 symtyperel = s 394 } 395 } 396 397 groupSym := func(name string, t sym.SymKind) *sym.Symbol { 398 s := ctxt.Syms.Lookup(name, 0) 399 s.Type = t 400 s.Size = 0 401 s.Attr |= sym.AttrLocal | sym.AttrReachable 402 return s 403 } 404 var ( 405 symgostring = groupSym("go.string.*", sym.SGOSTRING) 406 symgofunc = groupSym("go.func.*", sym.SGOFUNC) 407 symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) 408 ) 409 410 var symgofuncrel *sym.Symbol 411 if !ctxt.DynlinkingGo() { 412 if ctxt.UseRelro() { 413 symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) 414 } else { 415 symgofuncrel = symgofunc 416 } 417 } 418 419 symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) 420 symitablink.Type = sym.SITABLINK 421 422 symt = ctxt.Syms.Lookup("runtime.symtab", 0) 423 symt.Attr |= sym.AttrLocal 424 symt.Type = sym.SSYMTAB 425 symt.Size = 0 426 symt.Attr |= sym.AttrReachable 427 428 nitablinks := 0 429 430 // assign specific types so that they sort together. 431 // within a type they sort by size, so the .* symbols 432 // just defined above will be first. 433 // hide the specific symbols. 434 for _, s := range ctxt.Syms.Allsym { 435 if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) { 436 s.Attr |= sym.AttrNotInSymbolTable 437 } 438 439 if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA { 440 continue 441 } 442 443 switch { 444 case strings.HasPrefix(s.Name, "type."): 445 if !ctxt.DynlinkingGo() { 446 s.Attr |= sym.AttrNotInSymbolTable 447 } 448 if ctxt.UseRelro() { 449 s.Type = sym.STYPERELRO 450 s.Outer = symtyperel 451 } else { 452 s.Type = sym.STYPE 453 s.Outer = symtype 454 } 455 456 case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro(): 457 // Keep go.importpath symbols in the same section as types and 458 // names, as they can be referred to by a section offset. 459 s.Type = sym.STYPERELRO 460 461 case strings.HasPrefix(s.Name, "go.itablink."): 462 nitablinks++ 463 s.Type = sym.SITABLINK 464 s.Attr |= sym.AttrNotInSymbolTable 465 s.Outer = symitablink 466 467 case strings.HasPrefix(s.Name, "go.string."): 468 s.Type = sym.SGOSTRING 469 s.Attr |= sym.AttrNotInSymbolTable 470 s.Outer = symgostring 471 472 case strings.HasPrefix(s.Name, "runtime.gcbits."): 473 s.Type = sym.SGCBITS 474 s.Attr |= sym.AttrNotInSymbolTable 475 s.Outer = symgcbits 476 477 case strings.HasSuffix(s.Name, "·f"): 478 if !ctxt.DynlinkingGo() { 479 s.Attr |= sym.AttrNotInSymbolTable 480 } 481 if ctxt.UseRelro() { 482 s.Type = sym.SGOFUNCRELRO 483 s.Outer = symgofuncrel 484 } else { 485 s.Type = sym.SGOFUNC 486 s.Outer = symgofunc 487 } 488 489 case strings.HasPrefix(s.Name, "gcargs."), 490 strings.HasPrefix(s.Name, "gclocals."), 491 strings.HasPrefix(s.Name, "gclocals·"), 492 strings.HasPrefix(s.Name, "inltree."): 493 s.Type = sym.SGOFUNC 494 s.Attr |= sym.AttrNotInSymbolTable 495 s.Outer = symgofunc 496 s.Align = 4 497 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 498 } 499 } 500 501 if ctxt.BuildMode == BuildModeShared { 502 abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) 503 abihashgostr.Attr |= sym.AttrReachable 504 abihashgostr.Type = sym.SRODATA 505 hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) 506 abihashgostr.AddAddr(ctxt.Arch, hashsym) 507 abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size)) 508 } 509 if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() { 510 for _, l := range ctxt.Library { 511 s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) 512 s.Attr |= sym.AttrReachable 513 s.Type = sym.SRODATA 514 s.Size = int64(len(l.Hash)) 515 s.P = []byte(l.Hash) 516 str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) 517 str.Attr |= sym.AttrReachable 518 str.Type = sym.SRODATA 519 str.AddAddr(ctxt.Arch, s) 520 str.AddUint(ctxt.Arch, uint64(len(l.Hash))) 521 } 522 } 523 524 nsections := textsectionmap(ctxt) 525 526 // Information about the layout of the executable image for the 527 // runtime to use. Any changes here must be matched by changes to 528 // the definition of moduledata in runtime/symtab.go. 529 // This code uses several global variables that are set by pcln.go:pclntab. 530 moduledata := ctxt.Moduledata 531 // The pclntab slice 532 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0)) 533 moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 534 moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 535 // The ftab slice 536 moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) 537 moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) 538 moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) 539 // The filetab slice 540 moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) 541 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1) 542 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1) 543 // findfunctab 544 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0)) 545 // minpc, maxpc 546 moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc) 547 moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size) 548 // pointers to specific parts of the module 549 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0)) 550 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0)) 551 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0)) 552 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) 553 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0)) 554 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0)) 555 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0)) 556 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0)) 557 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0)) 558 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) 559 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0)) 560 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0)) 561 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0)) 562 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0)) 563 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0)) 564 565 // text section information 566 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) 567 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 568 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 569 570 // The typelinks slice 571 typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) 572 ntypelinks := uint64(typelinkSym.Size) / 4 573 moduledata.AddAddr(ctxt.Arch, typelinkSym) 574 moduledata.AddUint(ctxt.Arch, ntypelinks) 575 moduledata.AddUint(ctxt.Arch, ntypelinks) 576 // The itablinks slice 577 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0)) 578 moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) 579 moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) 580 // The ptab slice 581 if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { 582 ptab.Attr |= sym.AttrLocal 583 ptab.Type = sym.SRODATA 584 585 nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) 586 moduledata.AddAddr(ctxt.Arch, ptab) 587 moduledata.AddUint(ctxt.Arch, nentries) 588 moduledata.AddUint(ctxt.Arch, nentries) 589 } else { 590 moduledata.AddUint(ctxt.Arch, 0) 591 moduledata.AddUint(ctxt.Arch, 0) 592 moduledata.AddUint(ctxt.Arch, 0) 593 } 594 if ctxt.BuildMode == BuildModePlugin { 595 addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath)) 596 597 pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) 598 pkghashes.Attr |= sym.AttrReachable 599 pkghashes.Attr |= sym.AttrLocal 600 pkghashes.Type = sym.SRODATA 601 602 for i, l := range ctxt.Library { 603 // pkghashes[i].name 604 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) 605 // pkghashes[i].linktimehash 606 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash) 607 // pkghashes[i].runtimehash 608 hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0) 609 pkghashes.AddAddr(ctxt.Arch, hash) 610 } 611 moduledata.AddAddr(ctxt.Arch, pkghashes) 612 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 613 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 614 } else { 615 moduledata.AddUint(ctxt.Arch, 0) // pluginpath 616 moduledata.AddUint(ctxt.Arch, 0) 617 moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice 618 moduledata.AddUint(ctxt.Arch, 0) 619 moduledata.AddUint(ctxt.Arch, 0) 620 } 621 if len(ctxt.Shlibs) > 0 { 622 thismodulename := filepath.Base(*flagOutfile) 623 switch ctxt.BuildMode { 624 case BuildModeExe, BuildModePIE: 625 // When linking an executable, outfile is just "a.out". Make 626 // it something slightly more comprehensible. 627 thismodulename = "the executable" 628 } 629 addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) 630 631 modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) 632 modulehashes.Attr |= sym.AttrReachable 633 modulehashes.Attr |= sym.AttrLocal 634 modulehashes.Type = sym.SRODATA 635 636 for i, shlib := range ctxt.Shlibs { 637 // modulehashes[i].modulename 638 modulename := filepath.Base(shlib.Path) 639 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 640 641 // modulehashes[i].linktimehash 642 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 643 644 // modulehashes[i].runtimehash 645 abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) 646 abihash.Attr |= sym.AttrReachable 647 modulehashes.AddAddr(ctxt.Arch, abihash) 648 } 649 650 moduledata.AddAddr(ctxt.Arch, modulehashes) 651 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 652 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 653 } else { 654 moduledata.AddUint(ctxt.Arch, 0) // modulename 655 moduledata.AddUint(ctxt.Arch, 0) 656 moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice 657 moduledata.AddUint(ctxt.Arch, 0) 658 moduledata.AddUint(ctxt.Arch, 0) 659 } 660 661 hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE 662 if hasmain { 663 moduledata.AddUint8(1) 664 } else { 665 moduledata.AddUint8(0) 666 } 667 668 // The rest of moduledata is zero initialized. 669 // When linking an object that does not contain the runtime we are 670 // creating the moduledata from scratch and it does not have a 671 // compiler-provided size, so read it from the type data. 672 moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) 673 moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype) 674 moduledata.Grow(moduledata.Size) 675 676 lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) 677 if lastmoduledatap.Type != sym.SDYNIMPORT { 678 lastmoduledatap.Type = sym.SNOPTRDATA 679 lastmoduledatap.Size = 0 // overwrite existing value 680 lastmoduledatap.AddAddr(ctxt.Arch, moduledata) 681 } 682 } 683 684 func isStaticTemp(name string) bool { 685 if i := strings.LastIndex(name, "/"); i >= 0 { 686 name = name[i:] 687 } 688 return strings.Contains(name, "..stmp_") 689 }