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