1 // Inferno utils/6l/span.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
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.
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:
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
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
43 func putelfstr(s string) int {
44 if len(Elfstrdat) == 0 && s != "" {
45 // first entry must be empty string
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.
53 // Rewrite · to . for ASCII-only tools like DTrace (sigh)
54 s = strings.Replace(s, "·", ".", -1)
58 Elfstrdat = append(Elfstrdat, s...)
59 Elfstrdat = append(Elfstrdat, 0)
63 func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
65 Thearch.Lput(uint32(off))
68 Thearch.Wput(uint16(shndx))
69 Thearch.Vput(uint64(addr))
70 Thearch.Vput(uint64(size))
71 Symsize += ELF64SYMSIZE
73 Thearch.Lput(uint32(off))
74 Thearch.Lput(uint32(addr))
75 Thearch.Lput(uint32(size))
78 Thearch.Wput(uint16(shndx))
79 Symsize += ELF32SYMSIZE
83 var numelfsym int = 1 // 0 is reserved
87 func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
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)
113 for xo.Outer != nil {
118 if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ {
123 Diag("missing section in putelfsym")
126 if xo.Sect.Elfsect == nil {
128 Diag("missing ELF section in putelfsym")
131 elfshnum = xo.Sect.Elfsect.shnum
134 // One pass for each binding: STB_LOCAL, STB_GLOBAL,
135 // maybe one day STB_WEAK.
138 if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Attr.Local() {
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 {
151 if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
152 addr -= int64(xo.Sect.Vaddr)
155 if x.Type&obj.SHIDDEN != 0 {
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.
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)
178 } else if bind != elfbind {
182 putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other)
183 x.Elfsym = int32(numelfsym)
187 func putelfsectionsym(s *LSym, shndx int) {
188 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
189 s.Elfsym = int32(numelfsym)
194 // the first symbol entry is reserved
195 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
197 dwarfaddelfsectionsyms()
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)
210 elfglobalsymndx = numelfsym
214 func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
216 case 'T', 'L', 'D', 'B':
229 if HEADTYPE == obj.Hplan9 && SysArch.Family == sys.AMD64 && Debug['8'] == 0 {
230 Lputb(uint32(addr >> 32))
235 Cput(uint8(t + 0x80)) /* 0x80 is variable length */
238 if t == 'z' || t == 'Z' {
240 for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 {
249 /* skip the '<' in filenames */
253 for i = 0; i < len(s); i++ {
259 Symsize += int32(l) + 1 + int32(i) + 1
267 genasmsym(putplan9sym)
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)) }
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)) }
280 func Append16b(b []byte, v uint16) []byte {
281 return append(b, uint8(v>>8), uint8(v))
283 func Append16l(b []byte, v uint16) []byte {
284 return append(b, uint8(v), uint8(v>>8))
287 func Append32b(b []byte, v uint32) []byte {
288 return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v))
290 func Append32l(b []byte, v uint32) []byte {
291 return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24))
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))
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))
304 type byPkg []*Library
306 func (libs byPkg) Len() int {
310 func (libs byPkg) Less(a, b int) bool {
311 return libs[a].Pkg < libs[b].Pkg
314 func (libs byPkg) Swap(a, b int) {
315 libs[a], libs[b] = libs[b], libs[a]
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)
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)
346 // garbage collection symbols
347 s := Linklookup(Ctxt, "runtime.gcdata", 0)
351 s.Attr |= AttrReachable
352 xdefine("runtime.egcdata", obj.SRODATA, 0)
354 s = Linklookup(Ctxt, "runtime.gcbss", 0)
357 s.Attr |= AttrReachable
358 xdefine("runtime.egcbss", obj.SRODATA, 0)
360 // pseudo-symbols to mark locations of type, string, and go string data.
363 if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) {
364 s = Linklookup(Ctxt, "type.*", 0)
368 s.Attr |= AttrReachable
371 s = Linklookup(Ctxt, "typerel.*", 0)
373 s.Type = obj.STYPERELRO
375 s.Attr |= AttrReachable
377 } else if !DynlinkingGo() {
378 s = Linklookup(Ctxt, "type.*", 0)
382 s.Attr |= AttrReachable
387 groupSym := func(name string, t int16) *LSym {
388 s := Linklookup(Ctxt, name, 0)
391 s.Attr |= AttrLocal | AttrReachable
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)
401 symtypelink := Linklookup(Ctxt, "runtime.typelink", 0)
402 symtypelink.Type = obj.STYPELINK
404 symitablink := Linklookup(Ctxt, "runtime.itablink", 0)
405 symitablink.Type = obj.SITABLINK
407 symt = Linklookup(Ctxt, "runtime.symtab", 0)
408 symt.Attr |= AttrLocal
409 symt.Type = obj.SSYMTAB
411 symt.Attr |= AttrReachable
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 {
426 case strings.HasPrefix(s.Name, "type."):
431 s.Type = obj.STYPERELRO
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
443 case strings.HasPrefix(s.Name, "go.typelink."):
445 s.Type = obj.STYPELINK
447 s.Outer = symtypelink
449 case strings.HasPrefix(s.Name, "go.itablink."):
451 s.Type = obj.SITABLINK
453 s.Outer = symitablink
455 case strings.HasPrefix(s.Name, "go.string."):
456 s.Type = obj.SGOSTRING
458 s.Outer = symgostring
459 if strings.HasPrefix(s.Name, "go.string.hdr.") {
460 s.Type = obj.SGOSTRINGHDR
461 s.Outer = symgostringhdr
464 case strings.HasPrefix(s.Name, "runtime.gcbits."):
469 case strings.HasPrefix(s.Name, "go.func."):
474 case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"):
479 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
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))
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
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))
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))
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)
510 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
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)
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"
546 addgostring(moduledata, "go.link.thismodulename", thismodulename)
548 modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0)
549 modulehashes.Attr |= AttrReachable
550 modulehashes.Attr |= AttrLocal
551 modulehashes.Type = obj.SRODATA
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)
558 // modulehashes[i].linktimehash
559 addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
561 // modulehashes[i].runtimehash
562 abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0)
563 abihash.Attr |= AttrReachable
564 Addaddr(Ctxt, modulehashes, abihash)
567 Addaddr(Ctxt, moduledata, modulehashes)
568 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
569 adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
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)
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)