github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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/obj" 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 == obj.SDYNIMPORT || xo.Type == obj.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&obj.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&obj.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 == obj.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 == obj.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 = obj.SRODATA 311 t.Attr |= AttrReachable 312 nsections := int64(0) 313 314 for sect := Segtext.Sect; sect != nil; sect = sect.Next { 315 if sect.Name == ".text" { 316 nsections++ 317 } else { 318 break 319 } 320 } 321 Symgrow(t, nsections*(2*int64(SysArch.IntSize)+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.Sect.Vaddr 336 for sect := Segtext.Sect; sect != nil; sect = sect.Next { 337 if sect.Name != ".text" { 338 break 339 } 340 off = setuintxx(ctxt, t, off, sect.Vaddr-textbase, int64(SysArch.IntSize)) 341 off = setuintxx(ctxt, t, off, sect.Length, int64(SysArch.IntSize)) 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", obj.STEXT, 0) 367 368 ctxt.xdefine("runtime.etext", obj.STEXT, 0) 369 ctxt.xdefine("runtime.itablink", obj.SRODATA, 0) 370 ctxt.xdefine("runtime.eitablink", obj.SRODATA, 0) 371 ctxt.xdefine("runtime.rodata", obj.SRODATA, 0) 372 ctxt.xdefine("runtime.erodata", obj.SRODATA, 0) 373 ctxt.xdefine("runtime.types", obj.SRODATA, 0) 374 ctxt.xdefine("runtime.etypes", obj.SRODATA, 0) 375 ctxt.xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) 376 ctxt.xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) 377 ctxt.xdefine("runtime.data", obj.SDATA, 0) 378 ctxt.xdefine("runtime.edata", obj.SDATA, 0) 379 ctxt.xdefine("runtime.bss", obj.SBSS, 0) 380 ctxt.xdefine("runtime.ebss", obj.SBSS, 0) 381 ctxt.xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0) 382 ctxt.xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0) 383 ctxt.xdefine("runtime.end", obj.SBSS, 0) 384 ctxt.xdefine("runtime.epclntab", obj.SRODATA, 0) 385 ctxt.xdefine("runtime.esymtab", obj.SRODATA, 0) 386 387 // garbage collection symbols 388 s := ctxt.Syms.Lookup("runtime.gcdata", 0) 389 390 s.Type = obj.SRODATA 391 s.Size = 0 392 s.Attr |= AttrReachable 393 ctxt.xdefine("runtime.egcdata", obj.SRODATA, 0) 394 395 s = ctxt.Syms.Lookup("runtime.gcbss", 0) 396 s.Type = obj.SRODATA 397 s.Size = 0 398 s.Attr |= AttrReachable 399 ctxt.xdefine("runtime.egcbss", obj.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 = obj.STYPE 408 s.Size = 0 409 s.Attr |= AttrReachable 410 symtype = s 411 412 s = ctxt.Syms.Lookup("typerel.*", 0) 413 414 s.Type = obj.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 = obj.STYPE 422 s.Size = 0 423 s.Attr |= AttrReachable 424 symtype = s 425 symtyperel = s 426 } 427 428 groupSym := func(name string, t obj.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.*", obj.SGOSTRING) 437 symgofunc = groupSym("go.func.*", obj.SGOFUNC) 438 symgcbits = groupSym("runtime.gcbits.*", obj.SGCBITS) 439 ) 440 441 var symgofuncrel *Symbol 442 if !ctxt.DynlinkingGo() { 443 if UseRelro() { 444 symgofuncrel = groupSym("go.funcrel.*", obj.SGOFUNCRELRO) 445 } else { 446 symgofuncrel = symgofunc 447 } 448 } 449 450 symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) 451 symitablink.Type = obj.SITABLINK 452 453 symt = ctxt.Syms.Lookup("runtime.symtab", 0) 454 symt.Attr |= AttrLocal 455 symt.Type = obj.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 != obj.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 = obj.STYPERELRO 477 s.Outer = symtyperel 478 } else { 479 s.Type = obj.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 = obj.STYPERELRO 487 488 case strings.HasPrefix(s.Name, "go.itablink."): 489 nitablinks++ 490 s.Type = obj.SITABLINK 491 s.Attr |= AttrHidden 492 s.Outer = symitablink 493 494 case strings.HasPrefix(s.Name, "go.string."): 495 s.Type = obj.SGOSTRING 496 s.Attr |= AttrHidden 497 s.Outer = symgostring 498 499 case strings.HasPrefix(s.Name, "runtime.gcbits."): 500 s.Type = obj.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 = obj.SGOFUNCRELRO 510 s.Outer = symgofuncrel 511 } else { 512 s.Type = obj.SGOFUNC 513 s.Outer = symgofunc 514 } 515 516 case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"): 517 s.Type = obj.SGOFUNC 518 s.Attr |= AttrHidden 519 s.Outer = symgofunc 520 s.Align = 4 521 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 522 } 523 } 524 525 if Buildmode == BuildmodeShared { 526 abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) 527 abihashgostr.Attr |= AttrReachable 528 abihashgostr.Type = obj.SRODATA 529 hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) 530 Addaddr(ctxt, abihashgostr, hashsym) 531 adduint(ctxt, abihashgostr, uint64(hashsym.Size)) 532 } 533 534 nsections := textsectionmap(ctxt) 535 536 // Information about the layout of the executable image for the 537 // runtime to use. Any changes here must be matched by changes to 538 // the definition of moduledata in runtime/symtab.go. 539 // This code uses several global variables that are set by pcln.go:pclntab. 540 moduledata := ctxt.Moduledata 541 // The pclntab slice 542 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0)) 543 adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 544 adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 545 // The ftab slice 546 Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) 547 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 548 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 549 // The filetab slice 550 Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) 551 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 552 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 553 // findfunctab 554 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.findfunctab", 0)) 555 // minpc, maxpc 556 Addaddr(ctxt, moduledata, pclntabFirstFunc) 557 Addaddrplus(ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 558 // pointers to specific parts of the module 559 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.text", 0)) 560 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etext", 0)) 561 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrdata", 0)) 562 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) 563 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.data", 0)) 564 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.edata", 0)) 565 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.bss", 0)) 566 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.ebss", 0)) 567 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrbss", 0)) 568 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) 569 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.end", 0)) 570 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcdata", 0)) 571 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcbss", 0)) 572 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.types", 0)) 573 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etypes", 0)) 574 575 // text section information 576 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) 577 adduint(ctxt, moduledata, uint64(nsections)) 578 adduint(ctxt, moduledata, uint64(nsections)) 579 580 // The typelinks slice 581 typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) 582 ntypelinks := uint64(typelinkSym.Size) / 4 583 Addaddr(ctxt, moduledata, typelinkSym) 584 adduint(ctxt, moduledata, ntypelinks) 585 adduint(ctxt, moduledata, ntypelinks) 586 // The itablinks slice 587 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.itablink", 0)) 588 adduint(ctxt, moduledata, uint64(nitablinks)) 589 adduint(ctxt, moduledata, uint64(nitablinks)) 590 // The ptab slice 591 if Buildmode == BuildmodePlugin { 592 ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0) 593 ptab.Attr |= AttrReachable 594 ptab.Attr |= AttrLocal 595 ptab.Type = obj.SRODATA 596 597 nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) 598 Addaddr(ctxt, moduledata, ptab) 599 adduint(ctxt, moduledata, nentries) 600 adduint(ctxt, moduledata, nentries) 601 } else { 602 adduint(ctxt, moduledata, 0) 603 adduint(ctxt, moduledata, 0) 604 adduint(ctxt, moduledata, 0) 605 } 606 if Buildmode == BuildmodePlugin { 607 addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath) 608 } else { 609 adduint(ctxt, moduledata, 0) 610 adduint(ctxt, moduledata, 0) 611 } 612 if len(ctxt.Shlibs) > 0 { 613 thismodulename := filepath.Base(*flagOutfile) 614 switch Buildmode { 615 case BuildmodeExe, BuildmodePIE: 616 // When linking an executable, outfile is just "a.out". Make 617 // it something slightly more comprehensible. 618 thismodulename = "the executable" 619 } 620 addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) 621 622 modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) 623 modulehashes.Attr |= AttrReachable 624 modulehashes.Attr |= AttrLocal 625 modulehashes.Type = obj.SRODATA 626 627 for i, shlib := range ctxt.Shlibs { 628 // modulehashes[i].modulename 629 modulename := filepath.Base(shlib.Path) 630 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 631 632 // modulehashes[i].linktimehash 633 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 634 635 // modulehashes[i].runtimehash 636 abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) 637 abihash.Attr |= AttrReachable 638 Addaddr(ctxt, modulehashes, abihash) 639 } 640 641 Addaddr(ctxt, moduledata, modulehashes) 642 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 643 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 644 } 645 646 // The rest of moduledata is zero initialized. 647 // When linking an object that does not contain the runtime we are 648 // creating the moduledata from scratch and it does not have a 649 // compiler-provided size, so read it from the type data. 650 moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) 651 moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype) 652 Symgrow(moduledata, moduledata.Size) 653 654 lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) 655 if lastmoduledatap.Type != obj.SDYNIMPORT { 656 lastmoduledatap.Type = obj.SNOPTRDATA 657 lastmoduledatap.Size = 0 // overwrite existing value 658 Addaddr(ctxt, lastmoduledatap, moduledata) 659 } 660 }