github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/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.Version != 0 || (x.Type&sym.SHIDDEN != 0) || 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.Type&sym.SHIDDEN != 0 { 149 other = STV_HIDDEN 150 } 151 if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { 152 // On ppc64 the top three bits of the st_other field indicate how 153 // many instructions separate the global and local entry points. In 154 // our case it is two instructions, indicated by the value 3. 155 // The conditions here match those in preprocess in 156 // cmd/internal/obj/ppc64/obj9.go, which is where the 157 // instructions are inserted. 158 other |= 3 << 5 159 } 160 161 // When dynamically linking, we create Symbols by reading the names from 162 // the symbol tables of the shared libraries and so the names need to 163 // match exactly. Tools like DTrace will have to wait for now. 164 if !ctxt.DynlinkingGo() { 165 // Rewrite · to . for ASCII-only tools like DTrace (sigh) 166 s = strings.Replace(s, "·", ".", -1) 167 } 168 169 if ctxt.DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == sym.STEXT { 170 // When dynamically linking, we want references to functions defined 171 // in this module to always be to the function object, not to the 172 // PLT. We force this by writing an additional local symbol for every 173 // global function symbol and making all relocations against the 174 // global symbol refer to this local symbol instead (see 175 // (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the 176 // ELF linker -Bsymbolic-functions option, but that is buggy on 177 // several platforms. 178 putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other) 179 x.LocalElfsym = int32(numelfsym) 180 numelfsym++ 181 return 182 } else if bind != elfbind { 183 return 184 } 185 186 putelfsyment(ctxt.Out, putelfstr(s), addr, size, bind<<4|typ&0xf, elfshnum, other) 187 x.Elfsym = int32(numelfsym) 188 numelfsym++ 189 } 190 191 func putelfsectionsym(out *OutBuf, s *sym.Symbol, shndx int) { 192 putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0) 193 s.Elfsym = int32(numelfsym) 194 numelfsym++ 195 } 196 197 func Asmelfsym(ctxt *Link) { 198 // the first symbol entry is reserved 199 putelfsyment(ctxt.Out, 0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) 200 201 dwarfaddelfsectionsyms(ctxt) 202 203 // Some linkers will add a FILE sym if one is not present. 204 // Avoid having the working directory inserted into the symbol table. 205 // It is added with a name to avoid problems with external linking 206 // encountered on some versions of Solaris. See issue #14957. 207 putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0) 208 numelfsym++ 209 210 elfbind = STB_LOCAL 211 genasmsym(ctxt, putelfsym) 212 213 elfbind = STB_GLOBAL 214 elfglobalsymndx = numelfsym 215 genasmsym(ctxt, putelfsym) 216 } 217 218 func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64, go_ *sym.Symbol) { 219 t := int(typ) 220 switch typ { 221 case TextSym, DataSym, BSSSym: 222 if x.Version != 0 { 223 t += 'a' - 'A' 224 } 225 fallthrough 226 227 case AutoSym, ParamSym, FrameSym: 228 l := 4 229 if Headtype == objabi.Hplan9 && ctxt.Arch.Family == sys.AMD64 && !Flag8 { 230 ctxt.Out.Write32b(uint32(addr >> 32)) 231 l = 8 232 } 233 234 ctxt.Out.Write32b(uint32(addr)) 235 ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */ 236 237 ctxt.Out.WriteString(s) 238 ctxt.Out.Write8(0) 239 240 Symsize += int32(l) + 1 + int32(len(s)) + 1 241 242 default: 243 return 244 } 245 } 246 247 func Asmplan9sym(ctxt *Link) { 248 genasmsym(ctxt, putplan9sym) 249 } 250 251 var symt *sym.Symbol 252 253 type byPkg []*sym.Library 254 255 func (libs byPkg) Len() int { 256 return len(libs) 257 } 258 259 func (libs byPkg) Less(a, b int) bool { 260 return libs[a].Pkg < libs[b].Pkg 261 } 262 263 func (libs byPkg) Swap(a, b int) { 264 libs[a], libs[b] = libs[b], libs[a] 265 } 266 267 // Create a table with information on the text sections. 268 269 func textsectionmap(ctxt *Link) uint32 { 270 271 t := ctxt.Syms.Lookup("runtime.textsectionmap", 0) 272 t.Type = sym.SRODATA 273 t.Attr |= sym.AttrReachable 274 nsections := int64(0) 275 276 for _, sect := range Segtext.Sections { 277 if sect.Name == ".text" { 278 nsections++ 279 } else { 280 break 281 } 282 } 283 t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize)) 284 285 off := int64(0) 286 n := 0 287 288 // The vaddr for each text section is the difference between the section's 289 // Vaddr and the Vaddr for the first text section as determined at compile 290 // time. 291 292 // The symbol for the first text section is named runtime.text as before. 293 // Additional text sections are named runtime.text.n where n is the 294 // order of creation starting with 1. These symbols provide the section's 295 // address after relocation by the linker. 296 297 textbase := Segtext.Sections[0].Vaddr 298 for _, sect := range Segtext.Sections { 299 if sect.Name != ".text" { 300 break 301 } 302 off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase) 303 off = t.SetUint(ctxt.Arch, off, sect.Length) 304 if n == 0 { 305 s := ctxt.Syms.ROLookup("runtime.text", 0) 306 if s == nil { 307 Errorf(nil, "Unable to find symbol runtime.text\n") 308 } 309 off = t.SetAddr(ctxt.Arch, off, s) 310 311 } else { 312 s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) 313 if s == nil { 314 Errorf(nil, "Unable to find symbol runtime.text.%d\n", n) 315 } 316 off = t.SetAddr(ctxt.Arch, off, s) 317 } 318 n++ 319 } 320 return uint32(n) 321 } 322 323 func (ctxt *Link) symtab() { 324 dosymtype(ctxt) 325 326 // Define these so that they'll get put into the symbol table. 327 // data.c:/^address will provide the actual values. 328 ctxt.xdefine("runtime.text", sym.STEXT, 0) 329 330 ctxt.xdefine("runtime.etext", sym.STEXT, 0) 331 ctxt.xdefine("runtime.itablink", sym.SRODATA, 0) 332 ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0) 333 ctxt.xdefine("runtime.rodata", sym.SRODATA, 0) 334 ctxt.xdefine("runtime.erodata", sym.SRODATA, 0) 335 ctxt.xdefine("runtime.types", sym.SRODATA, 0) 336 ctxt.xdefine("runtime.etypes", sym.SRODATA, 0) 337 ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0) 338 ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0) 339 ctxt.xdefine("runtime.data", sym.SDATA, 0) 340 ctxt.xdefine("runtime.edata", sym.SDATA, 0) 341 ctxt.xdefine("runtime.bss", sym.SBSS, 0) 342 ctxt.xdefine("runtime.ebss", sym.SBSS, 0) 343 ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0) 344 ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0) 345 ctxt.xdefine("runtime.end", sym.SBSS, 0) 346 ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0) 347 ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0) 348 349 // garbage collection symbols 350 s := ctxt.Syms.Lookup("runtime.gcdata", 0) 351 352 s.Type = sym.SRODATA 353 s.Size = 0 354 s.Attr |= sym.AttrReachable 355 ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0) 356 357 s = ctxt.Syms.Lookup("runtime.gcbss", 0) 358 s.Type = sym.SRODATA 359 s.Size = 0 360 s.Attr |= sym.AttrReachable 361 ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0) 362 363 // pseudo-symbols to mark locations of type, string, and go string data. 364 var symtype *sym.Symbol 365 var symtyperel *sym.Symbol 366 if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) { 367 s = ctxt.Syms.Lookup("type.*", 0) 368 369 s.Type = sym.STYPE 370 s.Size = 0 371 s.Attr |= sym.AttrReachable 372 symtype = s 373 374 s = ctxt.Syms.Lookup("typerel.*", 0) 375 376 s.Type = sym.STYPERELRO 377 s.Size = 0 378 s.Attr |= sym.AttrReachable 379 symtyperel = s 380 } else if !ctxt.DynlinkingGo() { 381 s = ctxt.Syms.Lookup("type.*", 0) 382 383 s.Type = sym.STYPE 384 s.Size = 0 385 s.Attr |= sym.AttrReachable 386 symtype = s 387 symtyperel = s 388 } 389 390 groupSym := func(name string, t sym.SymKind) *sym.Symbol { 391 s := ctxt.Syms.Lookup(name, 0) 392 s.Type = t 393 s.Size = 0 394 s.Attr |= sym.AttrLocal | sym.AttrReachable 395 return s 396 } 397 var ( 398 symgostring = groupSym("go.string.*", sym.SGOSTRING) 399 symgofunc = groupSym("go.func.*", sym.SGOFUNC) 400 symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) 401 ) 402 403 var symgofuncrel *sym.Symbol 404 if !ctxt.DynlinkingGo() { 405 if ctxt.UseRelro() { 406 symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) 407 } else { 408 symgofuncrel = symgofunc 409 } 410 } 411 412 symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) 413 symitablink.Type = sym.SITABLINK 414 415 symt = ctxt.Syms.Lookup("runtime.symtab", 0) 416 symt.Attr |= sym.AttrLocal 417 symt.Type = sym.SSYMTAB 418 symt.Size = 0 419 symt.Attr |= sym.AttrReachable 420 421 nitablinks := 0 422 423 // assign specific types so that they sort together. 424 // within a type they sort by size, so the .* symbols 425 // just defined above will be first. 426 // hide the specific symbols. 427 for _, s := range ctxt.Syms.Allsym { 428 if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA { 429 continue 430 } 431 432 switch { 433 case strings.HasPrefix(s.Name, "type."): 434 if !ctxt.DynlinkingGo() { 435 s.Attr |= sym.AttrNotInSymbolTable 436 } 437 if ctxt.UseRelro() { 438 s.Type = sym.STYPERELRO 439 s.Outer = symtyperel 440 } else { 441 s.Type = sym.STYPE 442 s.Outer = symtype 443 } 444 445 case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro(): 446 // Keep go.importpath symbols in the same section as types and 447 // names, as they can be referred to by a section offset. 448 s.Type = sym.STYPERELRO 449 450 case strings.HasPrefix(s.Name, "go.itablink."): 451 nitablinks++ 452 s.Type = sym.SITABLINK 453 s.Attr |= sym.AttrNotInSymbolTable 454 s.Outer = symitablink 455 456 case strings.HasPrefix(s.Name, "go.string."): 457 s.Type = sym.SGOSTRING 458 s.Attr |= sym.AttrNotInSymbolTable 459 s.Outer = symgostring 460 461 case strings.HasPrefix(s.Name, "runtime.gcbits."): 462 s.Type = sym.SGCBITS 463 s.Attr |= sym.AttrNotInSymbolTable 464 s.Outer = symgcbits 465 466 case strings.HasSuffix(s.Name, "·f"): 467 if !ctxt.DynlinkingGo() { 468 s.Attr |= sym.AttrNotInSymbolTable 469 } 470 if ctxt.UseRelro() { 471 s.Type = sym.SGOFUNCRELRO 472 s.Outer = symgofuncrel 473 } else { 474 s.Type = sym.SGOFUNC 475 s.Outer = symgofunc 476 } 477 478 case strings.HasPrefix(s.Name, "gcargs."), 479 strings.HasPrefix(s.Name, "gclocals."), 480 strings.HasPrefix(s.Name, "gclocals·"), 481 strings.HasPrefix(s.Name, "inltree."): 482 s.Type = sym.SGOFUNC 483 s.Attr |= sym.AttrNotInSymbolTable 484 s.Outer = symgofunc 485 s.Align = 4 486 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 487 } 488 } 489 490 if ctxt.BuildMode == BuildModeShared { 491 abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) 492 abihashgostr.Attr |= sym.AttrReachable 493 abihashgostr.Type = sym.SRODATA 494 hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) 495 abihashgostr.AddAddr(ctxt.Arch, hashsym) 496 abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size)) 497 } 498 if ctxt.BuildMode == BuildModePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil { 499 for _, l := range ctxt.Library { 500 s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) 501 s.Attr |= sym.AttrReachable 502 s.Type = sym.SRODATA 503 s.Size = int64(len(l.Hash)) 504 s.P = []byte(l.Hash) 505 str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) 506 str.Attr |= sym.AttrReachable 507 str.Type = sym.SRODATA 508 str.AddAddr(ctxt.Arch, s) 509 str.AddUint(ctxt.Arch, uint64(len(l.Hash))) 510 } 511 } 512 513 nsections := textsectionmap(ctxt) 514 515 // Information about the layout of the executable image for the 516 // runtime to use. Any changes here must be matched by changes to 517 // the definition of moduledata in runtime/symtab.go. 518 // This code uses several global variables that are set by pcln.go:pclntab. 519 moduledata := ctxt.Moduledata 520 // The pclntab slice 521 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0)) 522 moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 523 moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 524 // The ftab slice 525 moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) 526 moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) 527 moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) 528 // The filetab slice 529 moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) 530 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1) 531 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1) 532 // findfunctab 533 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0)) 534 // minpc, maxpc 535 moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc) 536 moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size) 537 // pointers to specific parts of the module 538 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0)) 539 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0)) 540 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0)) 541 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) 542 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0)) 543 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0)) 544 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0)) 545 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0)) 546 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0)) 547 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) 548 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0)) 549 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0)) 550 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0)) 551 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0)) 552 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0)) 553 554 // text section information 555 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) 556 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 557 moduledata.AddUint(ctxt.Arch, uint64(nsections)) 558 559 // The typelinks slice 560 typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) 561 ntypelinks := uint64(typelinkSym.Size) / 4 562 moduledata.AddAddr(ctxt.Arch, typelinkSym) 563 moduledata.AddUint(ctxt.Arch, ntypelinks) 564 moduledata.AddUint(ctxt.Arch, ntypelinks) 565 // The itablinks slice 566 moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0)) 567 moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) 568 moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) 569 // The ptab slice 570 if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { 571 ptab.Attr |= sym.AttrLocal 572 ptab.Type = sym.SRODATA 573 574 nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) 575 moduledata.AddAddr(ctxt.Arch, ptab) 576 moduledata.AddUint(ctxt.Arch, nentries) 577 moduledata.AddUint(ctxt.Arch, nentries) 578 } else { 579 moduledata.AddUint(ctxt.Arch, 0) 580 moduledata.AddUint(ctxt.Arch, 0) 581 moduledata.AddUint(ctxt.Arch, 0) 582 } 583 if ctxt.BuildMode == BuildModePlugin { 584 addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath) 585 586 pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) 587 pkghashes.Attr |= sym.AttrReachable 588 pkghashes.Attr |= sym.AttrLocal 589 pkghashes.Type = sym.SRODATA 590 591 for i, l := range ctxt.Library { 592 // pkghashes[i].name 593 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) 594 // pkghashes[i].linktimehash 595 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash) 596 // pkghashes[i].runtimehash 597 hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0) 598 pkghashes.AddAddr(ctxt.Arch, hash) 599 } 600 moduledata.AddAddr(ctxt.Arch, pkghashes) 601 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 602 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) 603 } else { 604 moduledata.AddUint(ctxt.Arch, 0) // pluginpath 605 moduledata.AddUint(ctxt.Arch, 0) 606 moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice 607 moduledata.AddUint(ctxt.Arch, 0) 608 moduledata.AddUint(ctxt.Arch, 0) 609 } 610 if len(ctxt.Shlibs) > 0 { 611 thismodulename := filepath.Base(*flagOutfile) 612 switch ctxt.BuildMode { 613 case BuildModeExe, BuildModePIE: 614 // When linking an executable, outfile is just "a.out". Make 615 // it something slightly more comprehensible. 616 thismodulename = "the executable" 617 } 618 addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) 619 620 modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) 621 modulehashes.Attr |= sym.AttrReachable 622 modulehashes.Attr |= sym.AttrLocal 623 modulehashes.Type = sym.SRODATA 624 625 for i, shlib := range ctxt.Shlibs { 626 // modulehashes[i].modulename 627 modulename := filepath.Base(shlib.Path) 628 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 629 630 // modulehashes[i].linktimehash 631 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 632 633 // modulehashes[i].runtimehash 634 abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) 635 abihash.Attr |= sym.AttrReachable 636 modulehashes.AddAddr(ctxt.Arch, abihash) 637 } 638 639 moduledata.AddAddr(ctxt.Arch, modulehashes) 640 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 641 moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 642 } 643 644 // The rest of moduledata is zero initialized. 645 // When linking an object that does not contain the runtime we are 646 // creating the moduledata from scratch and it does not have a 647 // compiler-provided size, so read it from the type data. 648 moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) 649 moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype) 650 moduledata.Grow(moduledata.Size) 651 652 lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) 653 if lastmoduledatap.Type != sym.SDYNIMPORT { 654 lastmoduledatap.Type = sym.SNOPTRDATA 655 lastmoduledatap.Size = 0 // overwrite existing value 656 lastmoduledatap.AddAddr(ctxt.Arch, moduledata) 657 } 658 }