github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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, FileSym, 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 238 /* skip the '<' in filenames */ 239 if t == FileSym { 240 s = s[1:] 241 } 242 for i = 0; i < len(s); i++ { 243 Cput(s[i]) 244 } 245 Cput(0) 246 247 Symsize += int32(l) + 1 + int32(i) + 1 248 249 default: 250 return 251 } 252 } 253 254 func Asmplan9sym(ctxt *Link) { 255 genasmsym(ctxt, putplan9sym) 256 } 257 258 var symt *Symbol 259 260 var encbuf [10]byte 261 262 func Wputb(w uint16) { Cwrite(Append16b(encbuf[:0], w)) } 263 func Lputb(l uint32) { Cwrite(Append32b(encbuf[:0], l)) } 264 func Vputb(v uint64) { Cwrite(Append64b(encbuf[:0], v)) } 265 266 func Wputl(w uint16) { Cwrite(Append16l(encbuf[:0], w)) } 267 func Lputl(l uint32) { Cwrite(Append32l(encbuf[:0], l)) } 268 func Vputl(v uint64) { Cwrite(Append64l(encbuf[:0], v)) } 269 270 func Append16b(b []byte, v uint16) []byte { 271 return append(b, uint8(v>>8), uint8(v)) 272 } 273 func Append16l(b []byte, v uint16) []byte { 274 return append(b, uint8(v), uint8(v>>8)) 275 } 276 277 func Append32b(b []byte, v uint32) []byte { 278 return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 279 } 280 func Append32l(b []byte, v uint32) []byte { 281 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24)) 282 } 283 284 func Append64b(b []byte, v uint64) []byte { 285 return append(b, uint8(v>>56), uint8(v>>48), uint8(v>>40), uint8(v>>32), 286 uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 287 } 288 289 func Append64l(b []byte, v uint64) []byte { 290 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24), 291 uint8(v>>32), uint8(v>>40), uint8(v>>48), uint8(v>>56)) 292 } 293 294 type byPkg []*Library 295 296 func (libs byPkg) Len() int { 297 return len(libs) 298 } 299 300 func (libs byPkg) Less(a, b int) bool { 301 return libs[a].Pkg < libs[b].Pkg 302 } 303 304 func (libs byPkg) Swap(a, b int) { 305 libs[a], libs[b] = libs[b], libs[a] 306 } 307 308 // Create a table with information on the text sections. 309 310 func textsectionmap(ctxt *Link) uint32 { 311 312 t := ctxt.Syms.Lookup("runtime.textsectionmap", 0) 313 t.Type = SRODATA 314 t.Attr |= AttrReachable 315 nsections := int64(0) 316 317 for _, sect := range Segtext.Sections { 318 if sect.Name == ".text" { 319 nsections++ 320 } else { 321 break 322 } 323 } 324 Symgrow(t, 3*nsections*int64(SysArch.PtrSize)) 325 326 off := int64(0) 327 n := 0 328 329 // The vaddr for each text section is the difference between the section's 330 // Vaddr and the Vaddr for the first text section as determined at compile 331 // time. 332 333 // The symbol for the first text section is named runtime.text as before. 334 // Additional text sections are named runtime.text.n where n is the 335 // order of creation starting with 1. These symbols provide the section's 336 // address after relocation by the linker. 337 338 textbase := Segtext.Sections[0].Vaddr 339 for _, sect := range Segtext.Sections { 340 if sect.Name != ".text" { 341 break 342 } 343 off = setuint(ctxt, t, off, sect.Vaddr-textbase) 344 off = setuint(ctxt, t, off, sect.Length) 345 if n == 0 { 346 s := ctxt.Syms.ROLookup("runtime.text", 0) 347 if s == nil { 348 Errorf(nil, "Unable to find symbol runtime.text\n") 349 } 350 off = setaddr(ctxt, t, off, s) 351 352 } else { 353 s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) 354 if s == nil { 355 Errorf(nil, "Unable to find symbol runtime.text.%d\n", n) 356 } 357 off = setaddr(ctxt, t, off, s) 358 } 359 n++ 360 } 361 return uint32(n) 362 } 363 364 func (ctxt *Link) symtab() { 365 dosymtype(ctxt) 366 367 // Define these so that they'll get put into the symbol table. 368 // data.c:/^address will provide the actual values. 369 ctxt.xdefine("runtime.text", STEXT, 0) 370 371 ctxt.xdefine("runtime.etext", STEXT, 0) 372 ctxt.xdefine("runtime.itablink", SRODATA, 0) 373 ctxt.xdefine("runtime.eitablink", SRODATA, 0) 374 ctxt.xdefine("runtime.rodata", SRODATA, 0) 375 ctxt.xdefine("runtime.erodata", SRODATA, 0) 376 ctxt.xdefine("runtime.types", SRODATA, 0) 377 ctxt.xdefine("runtime.etypes", SRODATA, 0) 378 ctxt.xdefine("runtime.noptrdata", SNOPTRDATA, 0) 379 ctxt.xdefine("runtime.enoptrdata", SNOPTRDATA, 0) 380 ctxt.xdefine("runtime.data", SDATA, 0) 381 ctxt.xdefine("runtime.edata", SDATA, 0) 382 ctxt.xdefine("runtime.bss", SBSS, 0) 383 ctxt.xdefine("runtime.ebss", SBSS, 0) 384 ctxt.xdefine("runtime.noptrbss", SNOPTRBSS, 0) 385 ctxt.xdefine("runtime.enoptrbss", SNOPTRBSS, 0) 386 ctxt.xdefine("runtime.end", SBSS, 0) 387 ctxt.xdefine("runtime.epclntab", SRODATA, 0) 388 ctxt.xdefine("runtime.esymtab", SRODATA, 0) 389 390 // garbage collection symbols 391 s := ctxt.Syms.Lookup("runtime.gcdata", 0) 392 393 s.Type = SRODATA 394 s.Size = 0 395 s.Attr |= AttrReachable 396 ctxt.xdefine("runtime.egcdata", SRODATA, 0) 397 398 s = ctxt.Syms.Lookup("runtime.gcbss", 0) 399 s.Type = SRODATA 400 s.Size = 0 401 s.Attr |= AttrReachable 402 ctxt.xdefine("runtime.egcbss", SRODATA, 0) 403 404 // pseudo-symbols to mark locations of type, string, and go string data. 405 var symtype *Symbol 406 var symtyperel *Symbol 407 if UseRelro() && (Buildmode == BuildmodeCArchive || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) { 408 s = ctxt.Syms.Lookup("type.*", 0) 409 410 s.Type = STYPE 411 s.Size = 0 412 s.Attr |= AttrReachable 413 symtype = s 414 415 s = ctxt.Syms.Lookup("typerel.*", 0) 416 417 s.Type = STYPERELRO 418 s.Size = 0 419 s.Attr |= AttrReachable 420 symtyperel = s 421 } else if !ctxt.DynlinkingGo() { 422 s = ctxt.Syms.Lookup("type.*", 0) 423 424 s.Type = STYPE 425 s.Size = 0 426 s.Attr |= AttrReachable 427 symtype = s 428 symtyperel = s 429 } 430 431 groupSym := func(name string, t SymKind) *Symbol { 432 s := ctxt.Syms.Lookup(name, 0) 433 s.Type = t 434 s.Size = 0 435 s.Attr |= AttrLocal | AttrReachable 436 return s 437 } 438 var ( 439 symgostring = groupSym("go.string.*", SGOSTRING) 440 symgofunc = groupSym("go.func.*", SGOFUNC) 441 symgcbits = groupSym("runtime.gcbits.*", SGCBITS) 442 ) 443 444 var symgofuncrel *Symbol 445 if !ctxt.DynlinkingGo() { 446 if UseRelro() { 447 symgofuncrel = groupSym("go.funcrel.*", SGOFUNCRELRO) 448 } else { 449 symgofuncrel = symgofunc 450 } 451 } 452 453 symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) 454 symitablink.Type = SITABLINK 455 456 symt = ctxt.Syms.Lookup("runtime.symtab", 0) 457 symt.Attr |= AttrLocal 458 symt.Type = SSYMTAB 459 symt.Size = 0 460 symt.Attr |= AttrReachable 461 462 nitablinks := 0 463 464 // assign specific types so that they sort together. 465 // within a type they sort by size, so the .* symbols 466 // just defined above will be first. 467 // hide the specific symbols. 468 for _, s := range ctxt.Syms.Allsym { 469 if !s.Attr.Reachable() || s.Attr.Special() || s.Type != SRODATA { 470 continue 471 } 472 473 switch { 474 case strings.HasPrefix(s.Name, "type."): 475 if !ctxt.DynlinkingGo() { 476 s.Attr |= AttrNotInSymbolTable 477 } 478 if UseRelro() { 479 s.Type = STYPERELRO 480 s.Outer = symtyperel 481 } else { 482 s.Type = STYPE 483 s.Outer = symtype 484 } 485 486 case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro(): 487 // Keep go.importpath symbols in the same section as types and 488 // names, as they can be referred to by a section offset. 489 s.Type = STYPERELRO 490 491 case strings.HasPrefix(s.Name, "go.itablink."): 492 nitablinks++ 493 s.Type = SITABLINK 494 s.Attr |= AttrNotInSymbolTable 495 s.Outer = symitablink 496 497 case strings.HasPrefix(s.Name, "go.string."): 498 s.Type = SGOSTRING 499 s.Attr |= AttrNotInSymbolTable 500 s.Outer = symgostring 501 502 case strings.HasPrefix(s.Name, "runtime.gcbits."): 503 s.Type = SGCBITS 504 s.Attr |= AttrNotInSymbolTable 505 s.Outer = symgcbits 506 507 case strings.HasSuffix(s.Name, "·f"): 508 if !ctxt.DynlinkingGo() { 509 s.Attr |= AttrNotInSymbolTable 510 } 511 if UseRelro() { 512 s.Type = SGOFUNCRELRO 513 s.Outer = symgofuncrel 514 } else { 515 s.Type = SGOFUNC 516 s.Outer = symgofunc 517 } 518 519 case strings.HasPrefix(s.Name, "gcargs."), 520 strings.HasPrefix(s.Name, "gclocals."), 521 strings.HasPrefix(s.Name, "gclocals·"), 522 strings.HasPrefix(s.Name, "inltree."): 523 s.Type = SGOFUNC 524 s.Attr |= AttrNotInSymbolTable 525 s.Outer = symgofunc 526 s.Align = 4 527 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 528 } 529 } 530 531 if Buildmode == BuildmodeShared { 532 abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) 533 abihashgostr.Attr |= AttrReachable 534 abihashgostr.Type = SRODATA 535 hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) 536 Addaddr(ctxt, abihashgostr, hashsym) 537 adduint(ctxt, abihashgostr, uint64(hashsym.Size)) 538 } 539 if Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil { 540 for _, l := range ctxt.Library { 541 s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) 542 s.Attr |= AttrReachable 543 s.Type = SRODATA 544 s.Size = int64(len(l.hash)) 545 s.P = []byte(l.hash) 546 str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) 547 str.Attr |= AttrReachable 548 str.Type = SRODATA 549 Addaddr(ctxt, str, s) 550 adduint(ctxt, str, uint64(len(l.hash))) 551 } 552 } 553 554 nsections := textsectionmap(ctxt) 555 556 // Information about the layout of the executable image for the 557 // runtime to use. Any changes here must be matched by changes to 558 // the definition of moduledata in runtime/symtab.go. 559 // This code uses several global variables that are set by pcln.go:pclntab. 560 moduledata := ctxt.Moduledata 561 // The pclntab slice 562 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0)) 563 adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 564 adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) 565 // The ftab slice 566 Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) 567 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 568 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 569 // The filetab slice 570 Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) 571 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 572 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 573 // findfunctab 574 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.findfunctab", 0)) 575 // minpc, maxpc 576 Addaddr(ctxt, moduledata, pclntabFirstFunc) 577 Addaddrplus(ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 578 // pointers to specific parts of the module 579 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.text", 0)) 580 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etext", 0)) 581 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrdata", 0)) 582 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) 583 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.data", 0)) 584 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.edata", 0)) 585 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.bss", 0)) 586 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.ebss", 0)) 587 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrbss", 0)) 588 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) 589 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.end", 0)) 590 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcdata", 0)) 591 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcbss", 0)) 592 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.types", 0)) 593 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etypes", 0)) 594 595 // text section information 596 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) 597 adduint(ctxt, moduledata, uint64(nsections)) 598 adduint(ctxt, moduledata, uint64(nsections)) 599 600 // The typelinks slice 601 typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) 602 ntypelinks := uint64(typelinkSym.Size) / 4 603 Addaddr(ctxt, moduledata, typelinkSym) 604 adduint(ctxt, moduledata, ntypelinks) 605 adduint(ctxt, moduledata, ntypelinks) 606 // The itablinks slice 607 Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.itablink", 0)) 608 adduint(ctxt, moduledata, uint64(nitablinks)) 609 adduint(ctxt, moduledata, uint64(nitablinks)) 610 // The ptab slice 611 if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { 612 ptab.Attr |= AttrLocal 613 ptab.Type = SRODATA 614 615 nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) 616 Addaddr(ctxt, moduledata, ptab) 617 adduint(ctxt, moduledata, nentries) 618 adduint(ctxt, moduledata, nentries) 619 } else { 620 adduint(ctxt, moduledata, 0) 621 adduint(ctxt, moduledata, 0) 622 adduint(ctxt, moduledata, 0) 623 } 624 if Buildmode == BuildmodePlugin { 625 addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath) 626 627 pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) 628 pkghashes.Attr |= AttrReachable 629 pkghashes.Attr |= AttrLocal 630 pkghashes.Type = SRODATA 631 632 for i, l := range ctxt.Library { 633 // pkghashes[i].name 634 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) 635 // pkghashes[i].linktimehash 636 addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), string(l.hash)) 637 // pkghashes[i].runtimehash 638 hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0) 639 Addaddr(ctxt, pkghashes, hash) 640 } 641 Addaddr(ctxt, moduledata, pkghashes) 642 adduint(ctxt, moduledata, uint64(len(ctxt.Library))) 643 adduint(ctxt, moduledata, uint64(len(ctxt.Library))) 644 } else { 645 adduint(ctxt, moduledata, 0) // pluginpath 646 adduint(ctxt, moduledata, 0) 647 adduint(ctxt, moduledata, 0) // pkghashes slice 648 adduint(ctxt, moduledata, 0) 649 adduint(ctxt, moduledata, 0) 650 } 651 if len(ctxt.Shlibs) > 0 { 652 thismodulename := filepath.Base(*flagOutfile) 653 switch Buildmode { 654 case BuildmodeExe, BuildmodePIE: 655 // When linking an executable, outfile is just "a.out". Make 656 // it something slightly more comprehensible. 657 thismodulename = "the executable" 658 } 659 addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) 660 661 modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) 662 modulehashes.Attr |= AttrReachable 663 modulehashes.Attr |= AttrLocal 664 modulehashes.Type = SRODATA 665 666 for i, shlib := range ctxt.Shlibs { 667 // modulehashes[i].modulename 668 modulename := filepath.Base(shlib.Path) 669 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 670 671 // modulehashes[i].linktimehash 672 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 673 674 // modulehashes[i].runtimehash 675 abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) 676 abihash.Attr |= AttrReachable 677 Addaddr(ctxt, modulehashes, abihash) 678 } 679 680 Addaddr(ctxt, moduledata, modulehashes) 681 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 682 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 683 } 684 685 // The rest of moduledata is zero initialized. 686 // When linking an object that does not contain the runtime we are 687 // creating the moduledata from scratch and it does not have a 688 // compiler-provided size, so read it from the type data. 689 moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) 690 moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype) 691 Symgrow(moduledata, moduledata.Size) 692 693 lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) 694 if lastmoduledatap.Type != SDYNIMPORT { 695 lastmoduledatap.Type = SNOPTRDATA 696 lastmoduledatap.Size = 0 // overwrite existing value 697 Addaddr(ctxt, lastmoduledatap, moduledata) 698 } 699 }