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