github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/symtab.go (about)

     1  // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/ld/symtab.go
     2  
     3  // Inferno utils/6l/span.c
     4  // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
     5  //
     6  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     7  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     8  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     9  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
    10  //	Portions Copyright © 2004,2006 Bruce Ellis
    11  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    12  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    13  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    14  //
    15  // Permission is hereby granted, free of charge, to any person obtaining a copy
    16  // of this software and associated documentation files (the "Software"), to deal
    17  // in the Software without restriction, including without limitation the rights
    18  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    19  // copies of the Software, and to permit persons to whom the Software is
    20  // furnished to do so, subject to the following conditions:
    21  //
    22  // The above copyright notice and this permission notice shall be included in
    23  // all copies or substantial portions of the Software.
    24  //
    25  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    26  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    27  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    28  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    29  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    30  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    31  // THE SOFTWARE.
    32  
    33  package ld
    34  
    35  import (
    36  	"rsc.io/tmp/bootstrap/internal/obj"
    37  	"strings"
    38  )
    39  
    40  // Symbol table.
    41  
    42  func putelfstr(s string) int {
    43  	if len(Elfstrdat) == 0 && s != "" {
    44  		// first entry must be empty string
    45  		putelfstr("")
    46  	}
    47  
    48  	// When dynamically linking, we create LSym's by reading the names from
    49  	// the symbol tables of the shared libraries and so the names need to
    50  	// match exactly.  Tools like DTrace will have to wait for now.
    51  	if !DynlinkingGo() {
    52  		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
    53  		s = strings.Replace(s, "·", ".", -1)
    54  	}
    55  
    56  	n := len(s) + 1
    57  	for len(Elfstrdat)+n > cap(Elfstrdat) {
    58  		Elfstrdat = append(Elfstrdat[:cap(Elfstrdat)], 0)[:len(Elfstrdat)]
    59  	}
    60  
    61  	off := len(Elfstrdat)
    62  	Elfstrdat = Elfstrdat[:off+n]
    63  	copy(Elfstrdat[off:], s)
    64  
    65  	return off
    66  }
    67  
    68  func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
    69  	switch Thearch.Thechar {
    70  	case '6', '7', '9':
    71  		Thearch.Lput(uint32(off))
    72  		Cput(uint8(info))
    73  		Cput(uint8(other))
    74  		Thearch.Wput(uint16(shndx))
    75  		Thearch.Vput(uint64(addr))
    76  		Thearch.Vput(uint64(size))
    77  		Symsize += ELF64SYMSIZE
    78  
    79  	default:
    80  		Thearch.Lput(uint32(off))
    81  		Thearch.Lput(uint32(addr))
    82  		Thearch.Lput(uint32(size))
    83  		Cput(uint8(info))
    84  		Cput(uint8(other))
    85  		Thearch.Wput(uint16(shndx))
    86  		Symsize += ELF32SYMSIZE
    87  	}
    88  }
    89  
    90  var numelfsym int = 1 // 0 is reserved
    91  
    92  var elfbind int
    93  
    94  func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
    95  	var type_ int
    96  
    97  	switch t {
    98  	default:
    99  		return
   100  
   101  	case 'T':
   102  		type_ = STT_FUNC
   103  
   104  	case 'D':
   105  		type_ = STT_OBJECT
   106  
   107  	case 'B':
   108  		type_ = STT_OBJECT
   109  
   110  	case 'U':
   111  		type_ = STT_NOTYPE
   112  		if x == Ctxt.Tlsg {
   113  			type_ = STT_TLS
   114  		}
   115  
   116  	case 't':
   117  		type_ = STT_TLS
   118  	}
   119  
   120  	xo := x
   121  	for xo.Outer != nil {
   122  		xo = xo.Outer
   123  	}
   124  
   125  	var elfshnum int
   126  	if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ {
   127  		elfshnum = SHN_UNDEF
   128  	} else {
   129  		if xo.Sect == nil {
   130  			Ctxt.Cursym = x
   131  			Diag("missing section in putelfsym")
   132  			return
   133  		}
   134  		if xo.Sect.(*Section).Elfsect == nil {
   135  			Ctxt.Cursym = x
   136  			Diag("missing ELF section in putelfsym")
   137  			return
   138  		}
   139  		elfshnum = xo.Sect.(*Section).Elfsect.(*ElfShdr).shnum
   140  	}
   141  
   142  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   143  	// maybe one day STB_WEAK.
   144  	bind := STB_GLOBAL
   145  
   146  	if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Local {
   147  		bind = STB_LOCAL
   148  	}
   149  
   150  	// In external linking mode, we have to invoke gcc with -rdynamic
   151  	// to get the exported symbols put into the dynamic symbol table.
   152  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   153  	// mark all Go symbols local (not global) in the final executable.
   154  	// But when we're dynamically linking, we need all those global symbols.
   155  	if !DynlinkingGo() && Linkmode == LinkExternal && x.Cgoexport&CgoExportStatic == 0 && elfshnum != SHN_UNDEF {
   156  		bind = STB_LOCAL
   157  	}
   158  
   159  	if bind != elfbind {
   160  		return
   161  	}
   162  
   163  	off := putelfstr(s)
   164  	if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
   165  		addr -= int64(xo.Sect.(*Section).Vaddr)
   166  	}
   167  	other := STV_DEFAULT
   168  	if x.Type&obj.SHIDDEN != 0 {
   169  		other = STV_HIDDEN
   170  	}
   171  	putelfsyment(off, addr, size, bind<<4|type_&0xf, elfshnum, other)
   172  	x.Elfsym = int32(numelfsym)
   173  	numelfsym++
   174  }
   175  
   176  func putelfsectionsym(s *LSym, shndx int) {
   177  	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
   178  	s.Elfsym = int32(numelfsym)
   179  	numelfsym++
   180  }
   181  
   182  func putelfsymshndx(sympos int64, shndx int) {
   183  	here := Cpos()
   184  	if elf64 {
   185  		Cseek(sympos + 6)
   186  	} else {
   187  		Cseek(sympos + 14)
   188  	}
   189  
   190  	Thearch.Wput(uint16(shndx))
   191  	Cseek(here)
   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  	elfbind = STB_LOCAL
   201  	genasmsym(putelfsym)
   202  
   203  	elfbind = STB_GLOBAL
   204  	elfglobalsymndx = numelfsym
   205  	genasmsym(putelfsym)
   206  }
   207  
   208  func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
   209  	switch t {
   210  	case 'T', 'L', 'D', 'B':
   211  		if ver != 0 {
   212  			t += 'a' - 'A'
   213  		}
   214  		fallthrough
   215  
   216  	case 'a',
   217  		'p',
   218  		'f',
   219  		'z',
   220  		'Z',
   221  		'm':
   222  		l := 4
   223  		if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 {
   224  			Lputb(uint32(addr >> 32))
   225  			l = 8
   226  		}
   227  
   228  		Lputb(uint32(addr))
   229  		Cput(uint8(t + 0x80)) /* 0x80 is variable length */
   230  
   231  		var i int
   232  		if t == 'z' || t == 'Z' {
   233  			Cput(uint8(s[0]))
   234  			for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 {
   235  				Cput(uint8(s[i]))
   236  				Cput(uint8(s[i+1]))
   237  			}
   238  
   239  			Cput(0)
   240  			Cput(0)
   241  			i++
   242  		} else {
   243  			/* skip the '<' in filenames */
   244  			if t == 'f' {
   245  				s = s[1:]
   246  			}
   247  			for i = 0; i < len(s); i++ {
   248  				Cput(uint8(s[i]))
   249  			}
   250  			Cput(0)
   251  		}
   252  
   253  		Symsize += int32(l) + 1 + int32(i) + 1
   254  
   255  	default:
   256  		return
   257  	}
   258  }
   259  
   260  func Asmplan9sym() {
   261  	genasmsym(putplan9sym)
   262  }
   263  
   264  var symt *LSym
   265  
   266  func Wputl(w uint16) {
   267  	Cput(uint8(w))
   268  	Cput(uint8(w >> 8))
   269  }
   270  
   271  func Wputb(w uint16) {
   272  	Cput(uint8(w >> 8))
   273  	Cput(uint8(w))
   274  }
   275  
   276  func Lputb(l uint32) {
   277  	Cput(uint8(l >> 24))
   278  	Cput(uint8(l >> 16))
   279  	Cput(uint8(l >> 8))
   280  	Cput(uint8(l))
   281  }
   282  
   283  func Lputl(l uint32) {
   284  	Cput(uint8(l))
   285  	Cput(uint8(l >> 8))
   286  	Cput(uint8(l >> 16))
   287  	Cput(uint8(l >> 24))
   288  }
   289  
   290  func Vputb(v uint64) {
   291  	Lputb(uint32(v >> 32))
   292  	Lputb(uint32(v))
   293  }
   294  
   295  func Vputl(v uint64) {
   296  	Lputl(uint32(v))
   297  	Lputl(uint32(v >> 32))
   298  }
   299  
   300  func symtab() {
   301  	dosymtype()
   302  
   303  	// Define these so that they'll get put into the symbol table.
   304  	// data.c:/^address will provide the actual values.
   305  	xdefine("runtime.text", obj.STEXT, 0)
   306  
   307  	xdefine("runtime.etext", obj.STEXT, 0)
   308  	xdefine("runtime.typelink", obj.SRODATA, 0)
   309  	xdefine("runtime.etypelink", obj.SRODATA, 0)
   310  	xdefine("runtime.rodata", obj.SRODATA, 0)
   311  	xdefine("runtime.erodata", obj.SRODATA, 0)
   312  	xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0)
   313  	xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0)
   314  	xdefine("runtime.data", obj.SDATA, 0)
   315  	xdefine("runtime.edata", obj.SDATA, 0)
   316  	xdefine("runtime.bss", obj.SBSS, 0)
   317  	xdefine("runtime.ebss", obj.SBSS, 0)
   318  	xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0)
   319  	xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0)
   320  	xdefine("runtime.end", obj.SBSS, 0)
   321  	xdefine("runtime.epclntab", obj.SRODATA, 0)
   322  	xdefine("runtime.esymtab", obj.SRODATA, 0)
   323  
   324  	// garbage collection symbols
   325  	s := Linklookup(Ctxt, "runtime.gcdata", 0)
   326  
   327  	s.Type = obj.SRODATA
   328  	s.Size = 0
   329  	s.Reachable = true
   330  	xdefine("runtime.egcdata", obj.SRODATA, 0)
   331  
   332  	s = Linklookup(Ctxt, "runtime.gcbss", 0)
   333  	s.Type = obj.SRODATA
   334  	s.Size = 0
   335  	s.Reachable = true
   336  	xdefine("runtime.egcbss", obj.SRODATA, 0)
   337  
   338  	// pseudo-symbols to mark locations of type, string, and go string data.
   339  	var symtype *LSym
   340  	if !DynlinkingGo() {
   341  		s = Linklookup(Ctxt, "type.*", 0)
   342  
   343  		s.Type = obj.STYPE
   344  		s.Size = 0
   345  		s.Reachable = true
   346  		symtype = s
   347  	}
   348  
   349  	s = Linklookup(Ctxt, "go.string.*", 0)
   350  	s.Type = obj.SGOSTRING
   351  	s.Local = true
   352  	s.Size = 0
   353  	s.Reachable = true
   354  	symgostring := s
   355  
   356  	s = Linklookup(Ctxt, "go.func.*", 0)
   357  	s.Type = obj.SGOFUNC
   358  	s.Local = true
   359  	s.Size = 0
   360  	s.Reachable = true
   361  	symgofunc := s
   362  
   363  	symtypelink := Linklookup(Ctxt, "runtime.typelink", 0)
   364  
   365  	symt = Linklookup(Ctxt, "runtime.symtab", 0)
   366  	symt.Local = true
   367  	symt.Type = obj.SSYMTAB
   368  	symt.Size = 0
   369  	symt.Reachable = true
   370  
   371  	ntypelinks := 0
   372  
   373  	// assign specific types so that they sort together.
   374  	// within a type they sort by size, so the .* symbols
   375  	// just defined above will be first.
   376  	// hide the specific symbols.
   377  	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
   378  		if !s.Reachable || s.Special != 0 || s.Type != obj.SRODATA {
   379  			continue
   380  		}
   381  
   382  		if strings.HasPrefix(s.Name, "type.") && !DynlinkingGo() {
   383  			s.Type = obj.STYPE
   384  			s.Hide = 1
   385  			s.Outer = symtype
   386  		}
   387  
   388  		if strings.HasPrefix(s.Name, "go.typelink.") {
   389  			ntypelinks++
   390  			s.Type = obj.STYPELINK
   391  			s.Hide = 1
   392  			s.Outer = symtypelink
   393  		}
   394  
   395  		if strings.HasPrefix(s.Name, "go.string.") {
   396  			s.Type = obj.SGOSTRING
   397  			s.Hide = 1
   398  			s.Outer = symgostring
   399  		}
   400  
   401  		if strings.HasPrefix(s.Name, "go.func.") {
   402  			s.Type = obj.SGOFUNC
   403  			s.Hide = 1
   404  			s.Outer = symgofunc
   405  		}
   406  
   407  		if strings.HasPrefix(s.Name, "gcargs.") || strings.HasPrefix(s.Name, "gclocals.") || strings.HasPrefix(s.Name, "gclocals·") {
   408  			s.Type = obj.SGOFUNC
   409  			s.Hide = 1
   410  			s.Outer = symgofunc
   411  			s.Align = 4
   412  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   413  		}
   414  	}
   415  
   416  	// Information about the layout of the executable image for the
   417  	// runtime to use. Any changes here must be matched by changes to
   418  	// the definition of moduledata in runtime/symtab.go.
   419  	// This code uses several global variables that are set by pcln.go:pclntab.
   420  	moduledata := Linklookup(Ctxt, "runtime.firstmoduledata", 0)
   421  	moduledata.Type = obj.SNOPTRDATA
   422  	moduledata.Size = 0 // truncate symbol back to 0 bytes to reinitialize
   423  	moduledata.Reachable = true
   424  	moduledata.Local = true
   425  	// The pclntab slice
   426  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0))
   427  	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
   428  	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
   429  	// The ftab slice
   430  	Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset))
   431  	adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
   432  	adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
   433  	// The filetab slice
   434  	Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
   435  	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
   436  	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
   437  	// findfunctab
   438  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
   439  	// minpc, maxpc
   440  	Addaddr(Ctxt, moduledata, pclntabFirstFunc)
   441  	Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size)
   442  	// pointers to specific parts of the module
   443  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0))
   444  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0))
   445  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0))
   446  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0))
   447  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0))
   448  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0))
   449  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0))
   450  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0))
   451  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0))
   452  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0))
   453  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0))
   454  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0))
   455  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0))
   456  	// The typelinks slice
   457  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
   458  	adduint(Ctxt, moduledata, uint64(ntypelinks))
   459  	adduint(Ctxt, moduledata, uint64(ntypelinks))
   460  	// The rest of moduledata is zero initialized.
   461  	// When linking an object that does not contain the runtime we are
   462  	// creating the moduledata from scratch and it does not have a
   463  	// compiler-provided size, so read it from the type data.
   464  	moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0)
   465  	moduledata.Size = decodetype_size(moduledatatype)
   466  	Symgrow(Ctxt, moduledata, moduledata.Size)
   467  
   468  	lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0)
   469  	if lastmoduledatap.Type != obj.SDYNIMPORT {
   470  		lastmoduledatap.Type = obj.SNOPTRDATA
   471  		lastmoduledatap.Size = 0 // overwrite existing value
   472  		Addaddr(Ctxt, lastmoduledatap, moduledata)
   473  	}
   474  }