github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/cmd/link/internal/ld/symtab.go (about) 1 // Inferno utils/6l/span.c 2 // http://code.google.com/p/inferno-os/source/browse/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 int, addr int64, size int64, ver int, go_ *Symbol) { 80 var type_ int 81 82 switch t { 83 default: 84 return 85 86 case 'T': 87 type_ = STT_FUNC 88 89 case 'D': 90 type_ = STT_OBJECT 91 92 case 'B': 93 type_ = STT_OBJECT 94 95 case 'U': 96 // ElfType is only set for symbols read from Go shared libraries, but 97 // for other symbols it is left as STT_NOTYPE which is fine. 98 type_ = int(x.ElfType) 99 100 case 't': 101 type_ = STT_TLS 102 } 103 104 xo := x 105 for xo.Outer != nil { 106 xo = xo.Outer 107 } 108 109 var elfshnum int 110 if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ { 111 elfshnum = SHN_UNDEF 112 } else { 113 if xo.Sect == nil { 114 ctxt.Cursym = x 115 ctxt.Diag("missing section in putelfsym") 116 return 117 } 118 if xo.Sect.Elfsect == nil { 119 ctxt.Cursym = x 120 ctxt.Diag("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 ver != 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 && type_ == 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|type_&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|type_&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, t int, addr int64, size int64, ver int, go_ *Symbol) { 215 switch t { 216 case 'T', 'L', 'D', 'B': 217 if ver != 0 { 218 t += 'a' - 'A' 219 } 220 fallthrough 221 222 case 'a', 223 'p', 224 'f', 225 'z', 226 'Z', 227 'm': 228 l := 4 229 if HEADTYPE == obj.Hplan9 && SysArch.Family == sys.AMD64 && !Flag8 { 230 Lputb(uint32(addr >> 32)) 231 l = 8 232 } 233 234 Lputb(uint32(addr)) 235 Cput(uint8(t + 0x80)) /* 0x80 is variable length */ 236 237 var i int 238 if t == 'z' || t == 'Z' { 239 Cput(s[0]) 240 for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 { 241 Cput(s[i]) 242 Cput(s[i+1]) 243 } 244 245 Cput(0) 246 Cput(0) 247 i++ 248 } else { 249 /* skip the '<' in filenames */ 250 if t == 'f' { 251 s = s[1:] 252 } 253 for i = 0; i < len(s); i++ { 254 Cput(s[i]) 255 } 256 Cput(0) 257 } 258 259 Symsize += int32(l) + 1 + int32(i) + 1 260 261 default: 262 return 263 } 264 } 265 266 func Asmplan9sym(ctxt *Link) { 267 genasmsym(ctxt, putplan9sym) 268 } 269 270 var symt *Symbol 271 272 var encbuf [10]byte 273 274 func Wputb(w uint16) { Cwrite(Append16b(encbuf[:0], w)) } 275 func Lputb(l uint32) { Cwrite(Append32b(encbuf[:0], l)) } 276 func Vputb(v uint64) { Cwrite(Append64b(encbuf[:0], v)) } 277 278 func Wputl(w uint16) { Cwrite(Append16l(encbuf[:0], w)) } 279 func Lputl(l uint32) { Cwrite(Append32l(encbuf[:0], l)) } 280 func Vputl(v uint64) { Cwrite(Append64l(encbuf[:0], v)) } 281 282 func Append16b(b []byte, v uint16) []byte { 283 return append(b, uint8(v>>8), uint8(v)) 284 } 285 func Append16l(b []byte, v uint16) []byte { 286 return append(b, uint8(v), uint8(v>>8)) 287 } 288 289 func Append32b(b []byte, v uint32) []byte { 290 return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 291 } 292 func Append32l(b []byte, v uint32) []byte { 293 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24)) 294 } 295 296 func Append64b(b []byte, v uint64) []byte { 297 return append(b, uint8(v>>56), uint8(v>>48), uint8(v>>40), uint8(v>>32), 298 uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 299 } 300 301 func Append64l(b []byte, v uint64) []byte { 302 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24), 303 uint8(v>>32), uint8(v>>40), uint8(v>>48), uint8(v>>56)) 304 } 305 306 type byPkg []*Library 307 308 func (libs byPkg) Len() int { 309 return len(libs) 310 } 311 312 func (libs byPkg) Less(a, b int) bool { 313 return libs[a].Pkg < libs[b].Pkg 314 } 315 316 func (libs byPkg) Swap(a, b int) { 317 libs[a], libs[b] = libs[b], libs[a] 318 } 319 320 func (ctxt *Link) symtab() { 321 dosymtype(ctxt) 322 323 // Define these so that they'll get put into the symbol table. 324 // data.c:/^address will provide the actual values. 325 ctxt.xdefine("runtime.text", obj.STEXT, 0) 326 327 ctxt.xdefine("runtime.etext", obj.STEXT, 0) 328 ctxt.xdefine("runtime.typelink", obj.SRODATA, 0) 329 ctxt.xdefine("runtime.etypelink", obj.SRODATA, 0) 330 ctxt.xdefine("runtime.itablink", obj.SRODATA, 0) 331 ctxt.xdefine("runtime.eitablink", obj.SRODATA, 0) 332 ctxt.xdefine("runtime.rodata", obj.SRODATA, 0) 333 ctxt.xdefine("runtime.erodata", obj.SRODATA, 0) 334 ctxt.xdefine("runtime.types", obj.SRODATA, 0) 335 ctxt.xdefine("runtime.etypes", obj.SRODATA, 0) 336 ctxt.xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) 337 ctxt.xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) 338 ctxt.xdefine("runtime.data", obj.SDATA, 0) 339 ctxt.xdefine("runtime.edata", obj.SDATA, 0) 340 ctxt.xdefine("runtime.bss", obj.SBSS, 0) 341 ctxt.xdefine("runtime.ebss", obj.SBSS, 0) 342 ctxt.xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0) 343 ctxt.xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0) 344 ctxt.xdefine("runtime.end", obj.SBSS, 0) 345 ctxt.xdefine("runtime.epclntab", obj.SRODATA, 0) 346 ctxt.xdefine("runtime.esymtab", obj.SRODATA, 0) 347 348 // garbage collection symbols 349 s := Linklookup(ctxt, "runtime.gcdata", 0) 350 351 s.Type = obj.SRODATA 352 s.Size = 0 353 s.Attr |= AttrReachable 354 ctxt.xdefine("runtime.egcdata", obj.SRODATA, 0) 355 356 s = Linklookup(ctxt, "runtime.gcbss", 0) 357 s.Type = obj.SRODATA 358 s.Size = 0 359 s.Attr |= AttrReachable 360 ctxt.xdefine("runtime.egcbss", obj.SRODATA, 0) 361 362 // pseudo-symbols to mark locations of type, string, and go string data. 363 var symtype *Symbol 364 var symtyperel *Symbol 365 if UseRelro() && (Buildmode == BuildmodeCArchive || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) { 366 s = Linklookup(ctxt, "type.*", 0) 367 368 s.Type = obj.STYPE 369 s.Size = 0 370 s.Attr |= AttrReachable 371 symtype = s 372 373 s = Linklookup(ctxt, "typerel.*", 0) 374 375 s.Type = obj.STYPERELRO 376 s.Size = 0 377 s.Attr |= AttrReachable 378 symtyperel = s 379 } else if !ctxt.DynlinkingGo() { 380 s = Linklookup(ctxt, "type.*", 0) 381 382 s.Type = obj.STYPE 383 s.Size = 0 384 s.Attr |= AttrReachable 385 symtype = s 386 symtyperel = s 387 } 388 389 groupSym := func(name string, t int16) *Symbol { 390 s := Linklookup(ctxt, name, 0) 391 s.Type = t 392 s.Size = 0 393 s.Attr |= AttrLocal | AttrReachable 394 return s 395 } 396 var ( 397 symgostring = groupSym("go.string.*", obj.SGOSTRING) 398 symgostringhdr = groupSym("go.string.hdr.*", obj.SGOSTRINGHDR) 399 symgofunc = groupSym("go.func.*", obj.SGOFUNC) 400 symgcbits = groupSym("runtime.gcbits.*", obj.SGCBITS) 401 ) 402 403 var symgofuncrel *Symbol 404 if !ctxt.DynlinkingGo() { 405 if UseRelro() { 406 symgofuncrel = groupSym("go.funcrel.*", obj.SGOFUNCRELRO) 407 } else { 408 symgofuncrel = symgofunc 409 } 410 } 411 412 symtypelink := Linklookup(ctxt, "runtime.typelink", 0) 413 symtypelink.Type = obj.STYPELINK 414 415 symitablink := Linklookup(ctxt, "runtime.itablink", 0) 416 symitablink.Type = obj.SITABLINK 417 418 symt = Linklookup(ctxt, "runtime.symtab", 0) 419 symt.Attr |= AttrLocal 420 symt.Type = obj.SSYMTAB 421 symt.Size = 0 422 symt.Attr |= AttrReachable 423 424 ntypelinks := 0 425 nitablinks := 0 426 427 // assign specific types so that they sort together. 428 // within a type they sort by size, so the .* symbols 429 // just defined above will be first. 430 // hide the specific symbols. 431 for _, s := range ctxt.Allsym { 432 if !s.Attr.Reachable() || s.Attr.Special() || s.Type != obj.SRODATA { 433 continue 434 } 435 436 switch { 437 case strings.HasPrefix(s.Name, "type."): 438 if !ctxt.DynlinkingGo() { 439 s.Attr |= AttrHidden 440 } 441 if UseRelro() { 442 s.Type = obj.STYPERELRO 443 s.Outer = symtyperel 444 } else { 445 s.Type = obj.STYPE 446 s.Outer = symtype 447 } 448 449 case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro(): 450 // Keep go.importpath symbols in the same section as types and 451 // names, as they can be referred to by a section offset. 452 s.Type = obj.STYPERELRO 453 454 case strings.HasPrefix(s.Name, "go.typelink."): 455 ntypelinks++ 456 s.Type = obj.STYPELINK 457 s.Attr |= AttrHidden 458 s.Outer = symtypelink 459 460 case strings.HasPrefix(s.Name, "go.itablink."): 461 nitablinks++ 462 s.Type = obj.SITABLINK 463 s.Attr |= AttrHidden 464 s.Outer = symitablink 465 466 case strings.HasPrefix(s.Name, "go.string."): 467 s.Type = obj.SGOSTRING 468 s.Attr |= AttrHidden 469 s.Outer = symgostring 470 if strings.HasPrefix(s.Name, "go.string.hdr.") { 471 s.Type = obj.SGOSTRINGHDR 472 s.Outer = symgostringhdr 473 } 474 475 case strings.HasPrefix(s.Name, "runtime.gcbits."): 476 s.Type = obj.SGCBITS 477 s.Attr |= AttrHidden 478 s.Outer = symgcbits 479 480 case strings.HasSuffix(s.Name, "·f"): 481 if !ctxt.DynlinkingGo() { 482 s.Attr |= AttrHidden 483 } 484 if UseRelro() { 485 s.Type = obj.SGOFUNCRELRO 486 s.Outer = symgofuncrel 487 } else { 488 s.Type = obj.SGOFUNC 489 s.Outer = symgofunc 490 } 491 492 case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"): 493 s.Type = obj.SGOFUNC 494 s.Attr |= AttrHidden 495 s.Outer = symgofunc 496 s.Align = 4 497 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 498 } 499 } 500 501 if Buildmode == BuildmodeShared { 502 abihashgostr := Linklookup(ctxt, "go.link.abihash."+filepath.Base(*flagOutfile), 0) 503 abihashgostr.Attr |= AttrReachable 504 abihashgostr.Type = obj.SRODATA 505 hashsym := Linklookup(ctxt, "go.link.abihashbytes", 0) 506 Addaddr(ctxt, abihashgostr, hashsym) 507 adduint(ctxt, abihashgostr, uint64(hashsym.Size)) 508 } 509 510 // Information about the layout of the executable image for the 511 // runtime to use. Any changes here must be matched by changes to 512 // the definition of moduledata in runtime/symtab.go. 513 // This code uses several global variables that are set by pcln.go:pclntab. 514 moduledata := ctxt.Moduledata 515 // The pclntab slice 516 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.pclntab", 0)) 517 adduint(ctxt, moduledata, uint64(Linklookup(ctxt, "runtime.pclntab", 0).Size)) 518 adduint(ctxt, moduledata, uint64(Linklookup(ctxt, "runtime.pclntab", 0).Size)) 519 // The ftab slice 520 Addaddrplus(ctxt, moduledata, Linklookup(ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset)) 521 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 522 adduint(ctxt, moduledata, uint64(pclntabNfunc+1)) 523 // The filetab slice 524 Addaddrplus(ctxt, moduledata, Linklookup(ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset)) 525 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 526 adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1) 527 // findfunctab 528 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.findfunctab", 0)) 529 // minpc, maxpc 530 Addaddr(ctxt, moduledata, pclntabFirstFunc) 531 Addaddrplus(ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 532 // pointers to specific parts of the module 533 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.text", 0)) 534 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.etext", 0)) 535 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.noptrdata", 0)) 536 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.enoptrdata", 0)) 537 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.data", 0)) 538 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.edata", 0)) 539 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.bss", 0)) 540 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.ebss", 0)) 541 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.noptrbss", 0)) 542 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.enoptrbss", 0)) 543 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.end", 0)) 544 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.gcdata", 0)) 545 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.gcbss", 0)) 546 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.types", 0)) 547 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.etypes", 0)) 548 // The typelinks slice 549 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.typelink", 0)) 550 adduint(ctxt, moduledata, uint64(ntypelinks)) 551 adduint(ctxt, moduledata, uint64(ntypelinks)) 552 // The itablinks slice 553 Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.itablink", 0)) 554 adduint(ctxt, moduledata, uint64(nitablinks)) 555 adduint(ctxt, moduledata, uint64(nitablinks)) 556 if len(ctxt.Shlibs) > 0 { 557 thismodulename := filepath.Base(*flagOutfile) 558 switch Buildmode { 559 case BuildmodeExe, BuildmodePIE: 560 // When linking an executable, outfile is just "a.out". Make 561 // it something slightly more comprehensible. 562 thismodulename = "the executable" 563 } 564 addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) 565 566 modulehashes := Linklookup(ctxt, "go.link.abihashes", 0) 567 modulehashes.Attr |= AttrReachable 568 modulehashes.Attr |= AttrLocal 569 modulehashes.Type = obj.SRODATA 570 571 for i, shlib := range ctxt.Shlibs { 572 // modulehashes[i].modulename 573 modulename := filepath.Base(shlib.Path) 574 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 575 576 // modulehashes[i].linktimehash 577 addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 578 579 // modulehashes[i].runtimehash 580 abihash := Linklookup(ctxt, "go.link.abihash."+modulename, 0) 581 abihash.Attr |= AttrReachable 582 Addaddr(ctxt, modulehashes, abihash) 583 } 584 585 Addaddr(ctxt, moduledata, modulehashes) 586 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 587 adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs))) 588 } 589 590 // The rest of moduledata is zero initialized. 591 // When linking an object that does not contain the runtime we are 592 // creating the moduledata from scratch and it does not have a 593 // compiler-provided size, so read it from the type data. 594 moduledatatype := Linkrlookup(ctxt, "type.runtime.moduledata", 0) 595 moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype) 596 Symgrow(ctxt, moduledata, moduledata.Size) 597 598 lastmoduledatap := Linklookup(ctxt, "runtime.lastmoduledatap", 0) 599 if lastmoduledatap.Type != obj.SDYNIMPORT { 600 lastmoduledatap.Type = obj.SNOPTRDATA 601 lastmoduledatap.Size = 0 // overwrite existing value 602 Addaddr(ctxt, lastmoduledatap, moduledata) 603 } 604 }