github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/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 // TODO(aram): re-enable 149 //bind = STB_LOCAL 150 } 151 152 if Linkmode == LinkExternal && elfshnum != SHN_UNDEF { 153 addr -= int64(xo.Sect.Vaddr) 154 } 155 other := STV_DEFAULT 156 if x.Type&obj.SHIDDEN != 0 { 157 other = STV_HIDDEN 158 } 159 if (Buildmode == BuildmodePIE || DynlinkingGo()) && SysArch.Family == sys.PPC64 && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { 160 // On ppc64 the top three bits of the st_other field indicate how 161 // many instructions separate the global and local entry points. In 162 // our case it is two instructions, indicated by the value 3. 163 other |= 3 << 5 164 } 165 166 if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT { 167 // When dynamically linking, we want references to functions defined 168 // in this module to always be to the function object, not to the 169 // PLT. We force this by writing an additional local symbol for every 170 // global function symbol and making all relocations against the 171 // global symbol refer to this local symbol instead (see 172 // (*LSym).ElfsymForReloc). This is approximately equivalent to the 173 // ELF linker -Bsymbolic-functions option, but that is buggy on 174 // several platforms. 175 putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other) 176 x.LocalElfsym = int32(numelfsym) 177 numelfsym++ 178 return 179 } else if bind != elfbind { 180 return 181 } 182 183 putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other) 184 x.Elfsym = int32(numelfsym) 185 numelfsym++ 186 } 187 188 func putelfsectionsym(s *LSym, shndx int) { 189 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0) 190 s.Elfsym = int32(numelfsym) 191 numelfsym++ 192 } 193 194 func Asmelfsym() { 195 // the first symbol entry is reserved 196 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) 197 198 dwarfaddelfsectionsyms() 199 200 // Some linkers will add a FILE sym if one is not present. 201 // Avoid having the working directory inserted into the symbol table. 202 // It is added with a name to avoid problems with external linking 203 // encountered on some versions of Solaris. See issue #14957. 204 putelfsyment(putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0) 205 numelfsym++ 206 207 elfbind = STB_LOCAL 208 genasmsym(putelfsym) 209 210 elfbind = STB_GLOBAL 211 elfglobalsymndx = numelfsym 212 genasmsym(putelfsym) 213 } 214 215 func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) { 216 switch t { 217 case 'T', 'L', 'D', 'B': 218 if ver != 0 { 219 t += 'a' - 'A' 220 } 221 fallthrough 222 223 case 'a', 224 'p', 225 'f', 226 'z', 227 'Z', 228 'm': 229 l := 4 230 if HEADTYPE == obj.Hplan9 && SysArch.Family == sys.AMD64 && Debug['8'] == 0 { 231 Lputb(uint32(addr >> 32)) 232 l = 8 233 } 234 235 Lputb(uint32(addr)) 236 Cput(uint8(t + 0x80)) /* 0x80 is variable length */ 237 238 var i int 239 if t == 'z' || t == 'Z' { 240 Cput(s[0]) 241 for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 { 242 Cput(s[i]) 243 Cput(s[i+1]) 244 } 245 246 Cput(0) 247 Cput(0) 248 i++ 249 } else { 250 /* skip the '<' in filenames */ 251 if t == 'f' { 252 s = s[1:] 253 } 254 for i = 0; i < len(s); i++ { 255 Cput(s[i]) 256 } 257 Cput(0) 258 } 259 260 Symsize += int32(l) + 1 + int32(i) + 1 261 262 default: 263 return 264 } 265 } 266 267 func Asmplan9sym() { 268 genasmsym(putplan9sym) 269 } 270 271 var symt *LSym 272 273 func Wputb(w uint16) { Cwrite(Append16b(encbuf[:0], w)) } 274 func Lputb(l uint32) { Cwrite(Append32b(encbuf[:0], l)) } 275 func Vputb(v uint64) { Cwrite(Append64b(encbuf[:0], v)) } 276 277 func Wputl(w uint16) { Cwrite(Append16l(encbuf[:0], w)) } 278 func Lputl(l uint32) { Cwrite(Append32l(encbuf[:0], l)) } 279 func Vputl(v uint64) { Cwrite(Append64l(encbuf[:0], v)) } 280 281 func Append16b(b []byte, v uint16) []byte { 282 return append(b, uint8(v>>8), uint8(v)) 283 } 284 func Append16l(b []byte, v uint16) []byte { 285 return append(b, uint8(v), uint8(v>>8)) 286 } 287 288 func Append32b(b []byte, v uint32) []byte { 289 return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 290 } 291 func Append32l(b []byte, v uint32) []byte { 292 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24)) 293 } 294 295 func Append64b(b []byte, v uint64) []byte { 296 return append(b, uint8(v>>56), uint8(v>>48), uint8(v>>40), uint8(v>>32), 297 uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v)) 298 } 299 300 func Append64l(b []byte, v uint64) []byte { 301 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24), 302 uint8(v>>32), uint8(v>>40), uint8(v>>48), uint8(v>>56)) 303 } 304 305 type byPkg []*Library 306 307 func (libs byPkg) Len() int { 308 return len(libs) 309 } 310 311 func (libs byPkg) Less(a, b int) bool { 312 return libs[a].Pkg < libs[b].Pkg 313 } 314 315 func (libs byPkg) Swap(a, b int) { 316 libs[a], libs[b] = libs[b], libs[a] 317 } 318 319 func symtab() { 320 dosymtype() 321 322 // Define these so that they'll get put into the symbol table. 323 // data.go:/^address will provide the actual values. 324 xdefine("runtime.text", obj.STEXT, 0) 325 326 xdefine("runtime.etext", obj.STEXT, 0) 327 xdefine("runtime.typelink", obj.SRODATA, 0) 328 xdefine("runtime.etypelink", obj.SRODATA, 0) 329 xdefine("runtime.itablink", obj.SRODATA, 0) 330 xdefine("runtime.eitablink", obj.SRODATA, 0) 331 xdefine("runtime.rodata", obj.SRODATA, 0) 332 xdefine("runtime.erodata", obj.SRODATA, 0) 333 xdefine("runtime.types", obj.SRODATA, 0) 334 xdefine("runtime.etypes", obj.SRODATA, 0) 335 xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) 336 xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) 337 xdefine("runtime.data", obj.SDATA, 0) 338 xdefine("runtime.edata", obj.SDATA, 0) 339 xdefine("runtime.bss", obj.SBSS, 0) 340 xdefine("runtime.ebss", obj.SBSS, 0) 341 xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0) 342 xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0) 343 xdefine("runtime.end", obj.SBSS, 0) 344 xdefine("runtime.epclntab", obj.SRODATA, 0) 345 xdefine("runtime.esymtab", obj.SRODATA, 0) 346 347 // garbage collection symbols 348 s := Linklookup(Ctxt, "runtime.gcdata", 0) 349 350 s.Type = obj.SRODATA 351 s.Size = 0 352 s.Attr |= AttrReachable 353 xdefine("runtime.egcdata", obj.SRODATA, 0) 354 355 s = Linklookup(Ctxt, "runtime.gcbss", 0) 356 s.Type = obj.SRODATA 357 s.Size = 0 358 s.Attr |= AttrReachable 359 xdefine("runtime.egcbss", obj.SRODATA, 0) 360 361 // pseudo-symbols to mark locations of type, string, and go string data. 362 var symtype *LSym 363 var symtyperel *LSym 364 if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) { 365 s = Linklookup(Ctxt, "type.*", 0) 366 367 s.Type = obj.STYPE 368 s.Size = 0 369 s.Attr |= AttrReachable 370 symtype = s 371 372 s = Linklookup(Ctxt, "typerel.*", 0) 373 374 s.Type = obj.STYPERELRO 375 s.Size = 0 376 s.Attr |= AttrReachable 377 symtyperel = s 378 } else if !DynlinkingGo() { 379 s = Linklookup(Ctxt, "type.*", 0) 380 381 s.Type = obj.STYPE 382 s.Size = 0 383 s.Attr |= AttrReachable 384 symtype = s 385 symtyperel = s 386 } 387 388 groupSym := func(name string, t int16) *LSym { 389 s := Linklookup(Ctxt, name, 0) 390 s.Type = t 391 s.Size = 0 392 s.Attr |= AttrLocal | AttrReachable 393 return s 394 } 395 var ( 396 symgostring = groupSym("go.string.*", obj.SGOSTRING) 397 symgostringhdr = groupSym("go.string.hdr.*", obj.SGOSTRINGHDR) 398 symgofunc = groupSym("go.func.*", obj.SGOFUNC) 399 symgcbits = groupSym("runtime.gcbits.*", obj.SGCBITS) 400 ) 401 402 symtypelink := Linklookup(Ctxt, "runtime.typelink", 0) 403 symtypelink.Type = obj.STYPELINK 404 405 symitablink := Linklookup(Ctxt, "runtime.itablink", 0) 406 symitablink.Type = obj.SITABLINK 407 408 symt = Linklookup(Ctxt, "runtime.symtab", 0) 409 symt.Attr |= AttrLocal 410 symt.Type = obj.SSYMTAB 411 symt.Size = 0 412 symt.Attr |= AttrReachable 413 414 ntypelinks := 0 415 nitablinks := 0 416 417 // assign specific types so that they sort together. 418 // within a type they sort by size, so the .* symbols 419 // just defined above will be first. 420 // hide the specific symbols. 421 for _, s := range Ctxt.Allsym { 422 if !s.Attr.Reachable() || s.Attr.Special() || s.Type != obj.SRODATA { 423 continue 424 } 425 426 switch { 427 case strings.HasPrefix(s.Name, "type."): 428 if !DynlinkingGo() { 429 s.Attr |= AttrHidden 430 } 431 if UseRelro() { 432 s.Type = obj.STYPERELRO 433 s.Outer = symtyperel 434 } else { 435 s.Type = obj.STYPE 436 s.Outer = symtype 437 } 438 439 case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro(): 440 // Keep go.importpath symbols in the same section as types and 441 // names, as they can be referred to by a section offset. 442 s.Type = obj.STYPERELRO 443 444 case strings.HasPrefix(s.Name, "go.typelink."): 445 ntypelinks++ 446 s.Type = obj.STYPELINK 447 s.Attr |= AttrHidden 448 s.Outer = symtypelink 449 450 case strings.HasPrefix(s.Name, "go.itablink."): 451 nitablinks++ 452 s.Type = obj.SITABLINK 453 s.Attr |= AttrHidden 454 s.Outer = symitablink 455 456 case strings.HasPrefix(s.Name, "go.string."): 457 s.Type = obj.SGOSTRING 458 s.Attr |= AttrHidden 459 s.Outer = symgostring 460 if strings.HasPrefix(s.Name, "go.string.hdr.") { 461 s.Type = obj.SGOSTRINGHDR 462 s.Outer = symgostringhdr 463 } 464 465 case strings.HasPrefix(s.Name, "runtime.gcbits."): 466 s.Type = obj.SGCBITS 467 s.Attr |= AttrHidden 468 s.Outer = symgcbits 469 470 case strings.HasPrefix(s.Name, "go.func."): 471 s.Type = obj.SGOFUNC 472 s.Attr |= AttrHidden 473 s.Outer = symgofunc 474 475 case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"): 476 s.Type = obj.SGOFUNC 477 s.Attr |= AttrHidden 478 s.Outer = symgofunc 479 s.Align = 4 480 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 481 } 482 } 483 484 if Buildmode == BuildmodeShared { 485 abihashgostr := Linklookup(Ctxt, "go.link.abihash."+filepath.Base(outfile), 0) 486 abihashgostr.Attr |= AttrReachable 487 abihashgostr.Type = obj.SRODATA 488 hashsym := Linklookup(Ctxt, "go.link.abihashbytes", 0) 489 Addaddr(Ctxt, abihashgostr, hashsym) 490 adduint(Ctxt, abihashgostr, uint64(hashsym.Size)) 491 } 492 493 // Information about the layout of the executable image for the 494 // runtime to use. Any changes here must be matched by changes to 495 // the definition of moduledata in runtime/symtab.go. 496 // This code uses several global variables that are set by pcln.go:pclntab. 497 moduledata := Ctxt.Moduledata 498 // The pclntab slice 499 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0)) 500 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 501 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 502 // The ftab slice 503 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset)) 504 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 505 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 506 // The filetab slice 507 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset)) 508 adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1) 509 adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1) 510 // findfunctab 511 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0)) 512 // minpc, maxpc 513 Addaddr(Ctxt, moduledata, pclntabFirstFunc) 514 Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 515 // pointers to specific parts of the module 516 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0)) 517 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0)) 518 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0)) 519 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0)) 520 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0)) 521 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0)) 522 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0)) 523 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0)) 524 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0)) 525 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0)) 526 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0)) 527 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0)) 528 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0)) 529 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.types", 0)) 530 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypes", 0)) 531 // The typelinks slice 532 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0)) 533 adduint(Ctxt, moduledata, uint64(ntypelinks)) 534 adduint(Ctxt, moduledata, uint64(ntypelinks)) 535 // The itablinks slice 536 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.itablink", 0)) 537 adduint(Ctxt, moduledata, uint64(nitablinks)) 538 adduint(Ctxt, moduledata, uint64(nitablinks)) 539 if len(Ctxt.Shlibs) > 0 { 540 thismodulename := filepath.Base(outfile) 541 switch Buildmode { 542 case BuildmodeExe, BuildmodePIE: 543 // When linking an executable, outfile is just "a.out". Make 544 // it something slightly more comprehensible. 545 thismodulename = "the executable" 546 } 547 addgostring(moduledata, "go.link.thismodulename", thismodulename) 548 549 modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0) 550 modulehashes.Attr |= AttrReachable 551 modulehashes.Attr |= AttrLocal 552 modulehashes.Type = obj.SRODATA 553 554 for i, shlib := range Ctxt.Shlibs { 555 // modulehashes[i].modulename 556 modulename := filepath.Base(shlib.Path) 557 addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) 558 559 // modulehashes[i].linktimehash 560 addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) 561 562 // modulehashes[i].runtimehash 563 abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0) 564 abihash.Attr |= AttrReachable 565 Addaddr(Ctxt, modulehashes, abihash) 566 } 567 568 Addaddr(Ctxt, moduledata, modulehashes) 569 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 570 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs))) 571 } 572 573 // The rest of moduledata is zero initialized. 574 // When linking an object that does not contain the runtime we are 575 // creating the moduledata from scratch and it does not have a 576 // compiler-provided size, so read it from the type data. 577 moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0) 578 moduledata.Size = decodetype_size(moduledatatype) 579 Symgrow(Ctxt, moduledata, moduledata.Size) 580 581 lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0) 582 if lastmoduledatap.Type != obj.SDYNIMPORT { 583 lastmoduledatap.Type = obj.SNOPTRDATA 584 lastmoduledatap.Size = 0 // overwrite existing value 585 Addaddr(Ctxt, lastmoduledatap, moduledata) 586 } 587 }