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