github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/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 // When dynamically linking, we create LSym's by reading the names from 50 // the symbol tables of the shared libraries and so the names need to 51 // match exactly. Tools like DTrace will have to wait for now. 52 if !DynlinkingGo() { 53 // Rewrite · to . for ASCII-only tools like DTrace (sigh) 54 s = strings.Replace(s, "·", ".", -1) 55 } 56 57 off := len(Elfstrdat) 58 Elfstrdat = append(Elfstrdat, s...) 59 Elfstrdat = append(Elfstrdat, 0) 60 return off 61 } 62 63 func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) { 64 if elf64 { 65 Thearch.Lput(uint32(off)) 66 Cput(uint8(info)) 67 Cput(uint8(other)) 68 Thearch.Wput(uint16(shndx)) 69 Thearch.Vput(uint64(addr)) 70 Thearch.Vput(uint64(size)) 71 Symsize += ELF64SYMSIZE 72 } else { 73 Thearch.Lput(uint32(off)) 74 Thearch.Lput(uint32(addr)) 75 Thearch.Lput(uint32(size)) 76 Cput(uint8(info)) 77 Cput(uint8(other)) 78 Thearch.Wput(uint16(shndx)) 79 Symsize += ELF32SYMSIZE 80 } 81 } 82 83 var numelfsym int = 1 // 0 is reserved 84 85 var elfbind int 86 87 func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) { 88 var type_ int 89 90 switch t { 91 default: 92 return 93 94 case 'T': 95 type_ = STT_FUNC 96 97 case 'D': 98 type_ = STT_OBJECT 99 100 case 'B': 101 type_ = STT_OBJECT 102 103 case 'U': 104 // ElfType is only set for symbols read from Go shared libraries, but 105 // for other symbols it is left as STT_NOTYPE which is fine. 106 type_ = int(x.ElfType) 107 108 case 't': 109 type_ = STT_TLS 110 } 111 112 xo := x 113 for xo.Outer != nil { 114 xo = xo.Outer 115 } 116 117 var elfshnum int 118 if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ { 119 elfshnum = SHN_UNDEF 120 } else { 121 if xo.Sect == nil { 122 Ctxt.Cursym = x 123 Diag("missing section in putelfsym") 124 return 125 } 126 if xo.Sect.Elfsect == nil { 127 Ctxt.Cursym = x 128 Diag("missing ELF section in putelfsym") 129 return 130 } 131 elfshnum = xo.Sect.Elfsect.shnum 132 } 133 134 // One pass for each binding: STB_LOCAL, STB_GLOBAL, 135 // maybe one day STB_WEAK. 136 bind := STB_GLOBAL 137 138 if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Attr.Local() { 139 bind = STB_LOCAL 140 } 141 142 // In external linking mode, we have to invoke gcc with -rdynamic 143 // to get the exported symbols put into the dynamic symbol table. 144 // To avoid filling the dynamic table with lots of unnecessary symbols, 145 // mark all Go symbols local (not global) in the final executable. 146 // But when we're dynamically linking, we need all those global symbols. 147 if !DynlinkingGo() && Linkmode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF { 148 bind = STB_LOCAL 149 } 150 151 if Linkmode == LinkExternal && elfshnum != SHN_UNDEF { 152 addr -= int64(xo.Sect.Vaddr) 153 } 154 other := STV_DEFAULT 155 if x.Type&obj.SHIDDEN != 0 { 156 other = STV_HIDDEN 157 } 158 if (Buildmode == BuildmodePIE || DynlinkingGo()) && SysArch.Family == sys.PPC64 && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { 159 // On ppc64 the top three bits of the st_other field indicate how 160 // many instructions separate the global and local entry points. In 161 // our case it is two instructions, indicated by the value 3. 162 other |= 3 << 5 163 } 164 165 if 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 // (*LSym).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 *LSym, 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() { 194 // the first symbol entry is reserved 195 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) 196 197 dwarfaddelfsectionsyms() 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(putelfsym) 208 209 elfbind = STB_GLOBAL 210 elfglobalsymndx = numelfsym 211 genasmsym(putelfsym) 212 } 213 214 func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) { 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 && Debug['8'] == 0 { 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() { 267 genasmsym(putplan9sym) 268 } 269 270 var symt *LSym 271 272 func Wputb(w uint16) { Cwrite(Append16b(encbuf[:0], w)) } 273 func Lputb(l uint32) { Cwrite(Append32b(encbuf[:0], l)) } 274 func Vputb(v uint64) { Cwrite(Append64b(encbuf[:0], v)) } 275 276 func Wputl(w uint16) { Cwrite(Append16l(encbuf[:0], w)) } 277 func Lputl(l uint32) { Cwrite(Append32l(encbuf[:0], l)) } 278 func Vputl(v uint64) { Cwrite(Append64l(encbuf[:0], v)) } 279 280 func Append16b(b []byte, v uint16) []byte { 281 return append(b, uint8(v>>8), uint8(v)) 282 } 283 func Append16l(b []byte, v uint16) []byte { 284 return append(b, uint8(v), uint8(v>>8)) 285 } 286 287 func Append32b(b []byte, v uint32) []byte { 288 return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 289 } 290 func Append32l(b []byte, v uint32) []byte { 291 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24)) 292 } 293 294 func Append64b(b []byte, v uint64) []byte { 295 return append(b, uint8(v>>56), uint8(v>>48), uint8(v>>40), uint8(v>>32), 296 uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 297 } 298 299 func Append64l(b []byte, v uint64) []byte { 300 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24), 301 uint8(v>>32), uint8(v>>40), uint8(v>>48), uint8(v>>56)) 302 } 303 304 type byPkg []*Library 305 306 func (libs byPkg) Len() int { 307 return len(libs) 308 } 309 310 func (libs byPkg) Less(a, b int) bool { 311 return libs[a].Pkg < libs[b].Pkg 312 } 313 314 func (libs byPkg) Swap(a, b int) { 315 libs[a], libs[b] = libs[b], libs[a] 316 } 317 318 func symtab() { 319 dosymtype() 320 321 // Define these so that they'll get put into the symbol table. 322 // data.c:/^address will provide the actual values. 323 xdefine("runtime.text", obj.STEXT, 0) 324 325 xdefine("runtime.etext", obj.STEXT, 0) 326 xdefine("runtime.typelink", obj.SRODATA, 0) 327 xdefine("runtime.etypelink", obj.SRODATA, 0) 328 xdefine("runtime.itablink", obj.SRODATA, 0) 329 xdefine("runtime.eitablink", obj.SRODATA, 0) 330 xdefine("runtime.rodata", obj.SRODATA, 0) 331 xdefine("runtime.erodata", obj.SRODATA, 0) 332 xdefine("runtime.types", obj.SRODATA, 0) 333 xdefine("runtime.etypes", obj.SRODATA, 0) 334 xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) 335 xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) 336 xdefine("runtime.data", obj.SDATA, 0) 337 xdefine("runtime.edata", obj.SDATA, 0) 338 xdefine("runtime.bss", obj.SBSS, 0) 339 xdefine("runtime.ebss", obj.SBSS, 0) 340 xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0) 341 xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0) 342 xdefine("runtime.end", obj.SBSS, 0) 343 xdefine("runtime.epclntab", obj.SRODATA, 0) 344 xdefine("runtime.esymtab", obj.SRODATA, 0) 345 346 // garbage collection symbols 347 s := Linklookup(Ctxt, "runtime.gcdata", 0) 348 349 s.Type = obj.SRODATA 350 s.Size = 0 351 s.Attr |= AttrReachable 352 xdefine("runtime.egcdata", obj.SRODATA, 0) 353 354 s = Linklookup(Ctxt, "runtime.gcbss", 0) 355 s.Type = obj.SRODATA 356 s.Size = 0 357 s.Attr |= AttrReachable 358 xdefine("runtime.egcbss", obj.SRODATA, 0) 359 360 // pseudo-symbols to mark locations of type, string, and go string data. 361 var symtype *LSym 362 var symtyperel *LSym 363 if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) { 364 s = Linklookup(Ctxt, "type.*", 0) 365 366 s.Type = obj.STYPE 367 s.Size = 0 368 s.Attr |= AttrReachable 369 symtype = s 370 371 s = Linklookup(Ctxt, "typerel.*", 0) 372 373 s.Type = obj.STYPERELRO 374 s.Size = 0 375 s.Attr |= AttrReachable 376 symtyperel = s 377 } else if !DynlinkingGo() { 378 s = Linklookup(Ctxt, "type.*", 0) 379 380 s.Type = obj.STYPE 381 s.Size = 0 382 s.Attr |= AttrReachable 383 symtype = s 384 symtyperel = s 385 } 386 387 groupSym := func(name string, t int16) *LSym { 388 s := Linklookup(Ctxt, name, 0) 389 s.Type = t 390 s.Size = 0 391 s.Attr |= AttrLocal | AttrReachable 392 return s 393 } 394 var ( 395 symgostring = groupSym("go.string.*", obj.SGOSTRING) 396 symgostringhdr = groupSym("go.string.hdr.*", obj.SGOSTRINGHDR) 397 symgofunc = groupSym("go.func.*", obj.SGOFUNC) 398 symgcbits = groupSym("runtime.gcbits.*", obj.SGCBITS) 399 ) 400 401 symtypelink := Linklookup(Ctxt, "runtime.typelink", 0) 402 symtypelink.Type = obj.STYPELINK 403 404 symitablink := Linklookup(Ctxt, "runtime.itablink", 0) 405 symitablink.Type = obj.SITABLINK 406 407 symt = Linklookup(Ctxt, "runtime.symtab", 0) 408 symt.Attr |= AttrLocal 409 symt.Type = obj.SSYMTAB 410 symt.Size = 0 411 symt.Attr |= AttrReachable 412 413 ntypelinks := 0 414 nitablinks := 0 415 416 // assign specific types so that they sort together. 417 // within a type they sort by size, so the .* symbols 418 // just defined above will be first. 419 // hide the specific symbols. 420 for _, s := range Ctxt.Allsym { 421 if !s.Attr.Reachable() || s.Attr.Special() || s.Type != obj.SRODATA { 422 continue 423 } 424 425 switch { 426 case strings.HasPrefix(s.Name, "type."): 427 if !DynlinkingGo() { 428 s.Attr |= AttrHidden 429 } 430 if UseRelro() { 431 s.Type = obj.STYPERELRO 432 s.Outer = symtyperel 433 } else { 434 s.Type = obj.STYPE 435 s.Outer = symtype 436 } 437 438 case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro(): 439 // Keep go.importpath symbols in the same section as types and 440 // names, as they can be referred to by a section offset. 441 s.Type = obj.STYPERELRO 442 443 case strings.HasPrefix(s.Name, "go.typelink."): 444 ntypelinks++ 445 s.Type = obj.STYPELINK 446 s.Attr |= AttrHidden 447 s.Outer = symtypelink 448 449 case strings.HasPrefix(s.Name, "go.itablink."): 450 nitablinks++ 451 s.Type = obj.SITABLINK 452 s.Attr |= AttrHidden 453 s.Outer = symitablink 454 455 case strings.HasPrefix(s.Name, "go.string."): 456 s.Type = obj.SGOSTRING 457 s.Attr |= AttrHidden 458 s.Outer = symgostring 459 if strings.HasPrefix(s.Name, "go.string.hdr.") { 460 s.Type = obj.SGOSTRINGHDR 461 s.Outer = symgostringhdr 462 } 463 464 case strings.HasPrefix(s.Name, "runtime.gcbits."): 465 s.Type = obj.SGCBITS 466 s.Attr |= AttrHidden 467 s.Outer = symgcbits 468 469 case strings.HasPrefix(s.Name, "go.func."): 470 s.Type = obj.SGOFUNC 471 s.Attr |= AttrHidden 472 s.Outer = symgofunc 473 474 case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"): 475 s.Type = obj.SGOFUNC 476 s.Attr |= AttrHidden 477 s.Outer = symgofunc 478 s.Align = 4 479 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 480 } 481 } 482 483 if Buildmode == BuildmodeShared { 484 abihashgostr := Linklookup(Ctxt, "go.link.abihash."+filepath.Base(outfile), 0) 485 abihashgostr.Attr |= AttrReachable 486 abihashgostr.Type = obj.SRODATA 487 hashsym := Linklookup(Ctxt, "go.link.abihashbytes", 0) 488 Addaddr(Ctxt, abihashgostr, hashsym) 489 adduint(Ctxt, abihashgostr, uint64(hashsym.Size)) 490 } 491 492 // Information about the layout of the executable image for the 493 // runtime to use. Any changes here must be matched by changes to 494 // the definition of moduledata in runtime/symtab.go. 495 // This code uses several global variables that are set by pcln.go:pclntab. 496 moduledata := Ctxt.Moduledata 497 // The pclntab slice 498 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0)) 499 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 500 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 501 // The ftab slice 502 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset)) 503 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 504 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 505 // The filetab slice 506 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset)) 507 adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1) 508 adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1) 509 // findfunctab 510 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0)) 511 // minpc, maxpc 512 Addaddr(Ctxt, moduledata, pclntabFirstFunc) 513 Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 514 // pointers to specific parts of the module 515 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0)) 516 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0)) 517 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0)) 518 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0)) 519 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0)) 520 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0)) 521 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0)) 522 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0)) 523 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0)) 524 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0)) 525 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0)) 526 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0)) 527 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0)) 528 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.types", 0)) 529 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypes", 0)) 530 // The typelinks slice 531 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0)) 532 adduint(Ctxt, moduledata, uint64(ntypelinks)) 533 adduint(Ctxt, moduledata, uint64(ntypelinks)) 534 // The itablinks slice 535 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.itablink", 0)) 536 adduint(Ctxt, moduledata, uint64(nitablinks)) 537 adduint(Ctxt, moduledata, uint64(nitablinks)) 538 if len(Ctxt.Shlibs) > 0 { 539 thismodulename := filepath.Base(outfile) 540 switch Buildmode { 541 case BuildmodeExe, BuildmodePIE: 542 // When linking an executable, outfile is just "a.out". Make 543 // it something slightly more comprehensible. 544 thismodulename = "the executable" 545 } 546 addgostring(moduledata, "go.link.thismodulename", thismodulename) 547 548 modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0) 549 modulehashes.Attr |= AttrReachable 550 modulehashes.Attr |= AttrLocal 551 modulehashes.Type = obj.SRODATA 552 553 for i, shlib := range Ctxt.Shlibs { 554 // modulehashes[i].modulename 555 modulename := filepath.Base(shlib.Path) 556 addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 557 558 // modulehashes[i].linktimehash 559 addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 560 561 // modulehashes[i].runtimehash 562 abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0) 563 abihash.Attr |= AttrReachable 564 Addaddr(Ctxt, modulehashes, abihash) 565 } 566 567 Addaddr(Ctxt, moduledata, modulehashes) 568 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 569 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 570 } 571 572 // The rest of moduledata is zero initialized. 573 // When linking an object that does not contain the runtime we are 574 // creating the moduledata from scratch and it does not have a 575 // compiler-provided size, so read it from the type data. 576 moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0) 577 moduledata.Size = decodetype_size(moduledatatype) 578 Symgrow(Ctxt, moduledata, moduledata.Size) 579 580 lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0) 581 if lastmoduledatap.Type != obj.SDYNIMPORT { 582 lastmoduledatap.Type = obj.SNOPTRDATA 583 lastmoduledatap.Size = 0 // overwrite existing value 584 Addaddr(Ctxt, lastmoduledatap, moduledata) 585 } 586 }