github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/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 if Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil { 534 for _, l := range ctxt.Library { 535 s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) 536 s.Attr |= AttrReachable 537 s.Type = obj.SRODATA 538 s.Size = int64(len(l.hash)) 539 s.P = []byte(l.hash) 540 str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) 541 str.Attr |= AttrReachable 542 str.Type = obj.SRODATA 543 Addaddr(ctxt, str, s) 544 adduint(ctxt, str, uint64(len(l.hash))) 545 } 546 } 547 548 nsections := textsectionmap(ctxt) 549 550 // Information about the layout of the executable image for the 551 // runtime to use. Any changes here must be matched by changes to 552 // the definition of moduledata in runtime/symtab.go. 553 // This code uses several global variables that are set by pcln.go:pclntab. 554 moduledata := ctxt.Moduledata 555 // The pclntab slice 556 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0)) 557 adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 558 adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 559 // The ftab slice 560 Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) 561 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 562 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 563 // The filetab slice 564 Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) 565 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 566 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 567 // findfunctab 568 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.findfunctab", 0)) 569 // minpc, maxpc 570 Addaddr(ctxt, moduledata, pclntabFirstFunc) 571 Addaddrplus(ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 572 // pointers to specific parts of the module 573 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.text", 0)) 574 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etext", 0)) 575 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrdata", 0)) 576 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) 577 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.data", 0)) 578 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.edata", 0)) 579 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.bss", 0)) 580 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.ebss", 0)) 581 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrbss", 0)) 582 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) 583 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.end", 0)) 584 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcdata", 0)) 585 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcbss", 0)) 586 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.types", 0)) 587 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etypes", 0)) 588 589 // text section information 590 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) 591 adduint(ctxt, moduledata, uint64(nsections)) 592 adduint(ctxt, moduledata, uint64(nsections)) 593 594 // The typelinks slice 595 typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) 596 ntypelinks := uint64(typelinkSym.Size) / 4 597 Addaddr(ctxt, moduledata, typelinkSym) 598 adduint(ctxt, moduledata, ntypelinks) 599 adduint(ctxt, moduledata, ntypelinks) 600 // The itablinks slice 601 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.itablink", 0)) 602 adduint(ctxt, moduledata, uint64(nitablinks)) 603 adduint(ctxt, moduledata, uint64(nitablinks)) 604 // The ptab slice 605 if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { 606 ptab.Attr |= AttrLocal 607 ptab.Type = obj.SRODATA 608 609 nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) 610 Addaddr(ctxt, moduledata, ptab) 611 adduint(ctxt, moduledata, nentries) 612 adduint(ctxt, moduledata, nentries) 613 } else { 614 adduint(ctxt, moduledata, 0) 615 adduint(ctxt, moduledata, 0) 616 adduint(ctxt, moduledata, 0) 617 } 618 if Buildmode == BuildmodePlugin { 619 addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath) 620 621 pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) 622 pkghashes.Attr |= AttrReachable 623 pkghashes.Attr |= AttrLocal 624 pkghashes.Type = obj.SRODATA 625 626 for i, l := range ctxt.Library { 627 // pkghashes[i].name 628 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) 629 // pkghashes[i].linktimehash 630 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), string(l.hash)) 631 // pkghashes[i].runtimehash 632 hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0) 633 Addaddr(ctxt, pkghashes, hash) 634 } 635 Addaddr(ctxt, moduledata, pkghashes) 636 adduint(ctxt, moduledata, uint64(len(ctxt.Library))) 637 adduint(ctxt, moduledata, uint64(len(ctxt.Library))) 638 } else { 639 adduint(ctxt, moduledata, 0) // pluginpath 640 adduint(ctxt, moduledata, 0) 641 adduint(ctxt, moduledata, 0) // pkghashes slice 642 adduint(ctxt, moduledata, 0) 643 adduint(ctxt, moduledata, 0) 644 } 645 if len(ctxt.Shlibs) > 0 { 646 thismodulename := filepath.Base(*flagOutfile) 647 switch Buildmode { 648 case BuildmodeExe, BuildmodePIE: 649 // When linking an executable, outfile is just "a.out". Make 650 // it something slightly more comprehensible. 651 thismodulename = "the executable" 652 } 653 addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) 654 655 modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) 656 modulehashes.Attr |= AttrReachable 657 modulehashes.Attr |= AttrLocal 658 modulehashes.Type = obj.SRODATA 659 660 for i, shlib := range ctxt.Shlibs { 661 // modulehashes[i].modulename 662 modulename := filepath.Base(shlib.Path) 663 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 664 665 // modulehashes[i].linktimehash 666 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 667 668 // modulehashes[i].runtimehash 669 abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) 670 abihash.Attr |= AttrReachable 671 Addaddr(ctxt, modulehashes, abihash) 672 } 673 674 Addaddr(ctxt, moduledata, modulehashes) 675 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 676 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 677 } 678 679 // The rest of moduledata is zero initialized. 680 // When linking an object that does not contain the runtime we are 681 // creating the moduledata from scratch and it does not have a 682 // compiler-provided size, so read it from the type data. 683 moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) 684 moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype) 685 Symgrow(moduledata, moduledata.Size) 686 687 lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) 688 if lastmoduledatap.Type != obj.SDYNIMPORT { 689 lastmoduledatap.Type = obj.SNOPTRDATA 690 lastmoduledatap.Size = 0 // overwrite existing value 691 Addaddr(ctxt, lastmoduledatap, moduledata) 692 } 693 }