]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/ld/symtab.go
94a6d0ab290087ef979693d394f73b36d2eb0576
[gostls13.git] / src / cmd / link / internal / ld / symtab.go
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 }