github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/internal/sym/symbol.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package sym
     6  
     7  import (
     8  	"github.com/gagliardetto/golang-go/cmd/internal/obj"
     9  	"github.com/gagliardetto/golang-go/cmd/internal/objabi"
    10  	"github.com/gagliardetto/golang-go/cmd/internal/sys"
    11  	"debug/elf"
    12  	"fmt"
    13  	"log"
    14  )
    15  
    16  // Symbol is an entry in the symbol table.
    17  type Symbol struct {
    18  	Name        string
    19  	Type        SymKind
    20  	Version     int16
    21  	Attr        Attribute
    22  	Dynid       int32
    23  	Align       int32
    24  	Elfsym      int32
    25  	LocalElfsym int32
    26  	Value       int64
    27  	Size        int64
    28  	Sub         *Symbol
    29  	Outer       *Symbol
    30  	Gotype      *Symbol
    31  	File        string // actually package!
    32  	auxinfo     *AuxSymbol
    33  	Sect        *Section
    34  	FuncInfo    *FuncInfo
    35  	Unit        *CompilationUnit
    36  	// P contains the raw symbol data.
    37  	P []byte
    38  	R []Reloc
    39  }
    40  
    41  // AuxSymbol contains less-frequently used sym.Symbol fields.
    42  type AuxSymbol struct {
    43  	extname    string
    44  	dynimplib  string
    45  	dynimpvers string
    46  	localentry uint8
    47  	plt        int32
    48  	got        int32
    49  	// ElfType is set for symbols read from shared libraries by ldshlibsyms. It
    50  	// is not set for symbols defined by the packages being linked or by symbols
    51  	// read by ldelf (and so is left as elf.STT_NOTYPE).
    52  	elftype elf.SymType
    53  }
    54  
    55  const (
    56  	SymVerABI0        = 0
    57  	SymVerABIInternal = 1
    58  	SymVerStatic      = 10 // Minimum version used by static (file-local) syms
    59  )
    60  
    61  func ABIToVersion(abi obj.ABI) int {
    62  	switch abi {
    63  	case obj.ABI0:
    64  		return SymVerABI0
    65  	case obj.ABIInternal:
    66  		return SymVerABIInternal
    67  	}
    68  	return -1
    69  }
    70  
    71  func VersionToABI(v int) (obj.ABI, bool) {
    72  	switch v {
    73  	case SymVerABI0:
    74  		return obj.ABI0, true
    75  	case SymVerABIInternal:
    76  		return obj.ABIInternal, true
    77  	}
    78  	return ^obj.ABI(0), false
    79  }
    80  
    81  func (s *Symbol) String() string {
    82  	if s.Version == 0 {
    83  		return s.Name
    84  	}
    85  	return fmt.Sprintf("%s<%d>", s.Name, s.Version)
    86  }
    87  
    88  func (s *Symbol) IsFileLocal() bool {
    89  	return s.Version >= SymVerStatic
    90  }
    91  
    92  func (s *Symbol) ElfsymForReloc() int32 {
    93  	// If putelfsym created a local version of this symbol, use that in all
    94  	// relocations.
    95  	if s.LocalElfsym != 0 {
    96  		return s.LocalElfsym
    97  	} else {
    98  		return s.Elfsym
    99  	}
   100  }
   101  
   102  func (s *Symbol) Len() int64 {
   103  	return s.Size
   104  }
   105  
   106  func (s *Symbol) Grow(siz int64) {
   107  	if int64(int(siz)) != siz {
   108  		log.Fatalf("symgrow size %d too long", siz)
   109  	}
   110  	if int64(len(s.P)) >= siz {
   111  		return
   112  	}
   113  	if cap(s.P) < int(siz) {
   114  		p := make([]byte, 2*(siz+1))
   115  		s.P = append(p[:0], s.P...)
   116  	}
   117  	s.P = s.P[:siz]
   118  }
   119  
   120  func (s *Symbol) AddBytes(bytes []byte) int64 {
   121  	if s.Type == 0 {
   122  		s.Type = SDATA
   123  	}
   124  	s.Attr |= AttrReachable
   125  	s.P = append(s.P, bytes...)
   126  	s.Size = int64(len(s.P))
   127  
   128  	return s.Size
   129  }
   130  
   131  func (s *Symbol) AddUint8(v uint8) int64 {
   132  	off := s.Size
   133  	if s.Type == 0 {
   134  		s.Type = SDATA
   135  	}
   136  	s.Attr |= AttrReachable
   137  	s.Size++
   138  	s.P = append(s.P, v)
   139  
   140  	return off
   141  }
   142  
   143  func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 {
   144  	return s.AddUintXX(arch, uint64(v), 2)
   145  }
   146  
   147  func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 {
   148  	return s.AddUintXX(arch, uint64(v), 4)
   149  }
   150  
   151  func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 {
   152  	return s.AddUintXX(arch, v, 8)
   153  }
   154  
   155  func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 {
   156  	return s.AddUintXX(arch, v, arch.PtrSize)
   157  }
   158  
   159  func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 {
   160  	return s.setUintXX(arch, r, uint64(v), 1)
   161  }
   162  
   163  func (s *Symbol) SetUint16(arch *sys.Arch, r int64, v uint16) int64 {
   164  	return s.setUintXX(arch, r, uint64(v), 2)
   165  }
   166  
   167  func (s *Symbol) SetUint32(arch *sys.Arch, r int64, v uint32) int64 {
   168  	return s.setUintXX(arch, r, uint64(v), 4)
   169  }
   170  
   171  func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 {
   172  	return s.setUintXX(arch, r, v, int64(arch.PtrSize))
   173  }
   174  
   175  func (s *Symbol) addAddrPlus(arch *sys.Arch, t *Symbol, add int64, typ objabi.RelocType) int64 {
   176  	if s.Type == 0 {
   177  		s.Type = SDATA
   178  	}
   179  	s.Attr |= AttrReachable
   180  	i := s.Size
   181  	s.Size += int64(arch.PtrSize)
   182  	s.Grow(s.Size)
   183  	r := s.AddRel()
   184  	r.Sym = t
   185  	r.Off = int32(i)
   186  	r.Siz = uint8(arch.PtrSize)
   187  	r.Type = typ
   188  	r.Add = add
   189  	return i + int64(r.Siz)
   190  }
   191  
   192  func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
   193  	return s.addAddrPlus(arch, t, add, objabi.R_ADDR)
   194  }
   195  
   196  func (s *Symbol) AddCURelativeAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
   197  	return s.addAddrPlus(arch, t, add, objabi.R_ADDRCUOFF)
   198  }
   199  
   200  func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
   201  	if s.Type == 0 {
   202  		s.Type = SDATA
   203  	}
   204  	s.Attr |= AttrReachable
   205  	i := s.Size
   206  	s.Size += 4
   207  	s.Grow(s.Size)
   208  	r := s.AddRel()
   209  	r.Sym = t
   210  	r.Off = int32(i)
   211  	r.Add = add
   212  	r.Type = objabi.R_PCREL
   213  	r.Siz = 4
   214  	if arch.Family == sys.S390X || arch.Family == sys.PPC64 {
   215  		r.InitExt()
   216  	}
   217  	if arch.Family == sys.S390X {
   218  		r.Variant = RV_390_DBL
   219  	}
   220  	return i + int64(r.Siz)
   221  }
   222  
   223  func (s *Symbol) AddAddr(arch *sys.Arch, t *Symbol) int64 {
   224  	return s.AddAddrPlus(arch, t, 0)
   225  }
   226  
   227  func (s *Symbol) SetAddrPlus(arch *sys.Arch, off int64, t *Symbol, add int64) int64 {
   228  	if s.Type == 0 {
   229  		s.Type = SDATA
   230  	}
   231  	s.Attr |= AttrReachable
   232  	if off+int64(arch.PtrSize) > s.Size {
   233  		s.Size = off + int64(arch.PtrSize)
   234  		s.Grow(s.Size)
   235  	}
   236  
   237  	r := s.AddRel()
   238  	r.Sym = t
   239  	r.Off = int32(off)
   240  	r.Siz = uint8(arch.PtrSize)
   241  	r.Type = objabi.R_ADDR
   242  	r.Add = add
   243  	return off + int64(r.Siz)
   244  }
   245  
   246  func (s *Symbol) SetAddr(arch *sys.Arch, off int64, t *Symbol) int64 {
   247  	return s.SetAddrPlus(arch, off, t, 0)
   248  }
   249  
   250  func (s *Symbol) AddSize(arch *sys.Arch, t *Symbol) int64 {
   251  	if s.Type == 0 {
   252  		s.Type = SDATA
   253  	}
   254  	s.Attr |= AttrReachable
   255  	i := s.Size
   256  	s.Size += int64(arch.PtrSize)
   257  	s.Grow(s.Size)
   258  	r := s.AddRel()
   259  	r.Sym = t
   260  	r.Off = int32(i)
   261  	r.Siz = uint8(arch.PtrSize)
   262  	r.Type = objabi.R_SIZE
   263  	return i + int64(r.Siz)
   264  }
   265  
   266  func (s *Symbol) AddAddrPlus4(t *Symbol, add int64) int64 {
   267  	if s.Type == 0 {
   268  		s.Type = SDATA
   269  	}
   270  	s.Attr |= AttrReachable
   271  	i := s.Size
   272  	s.Size += 4
   273  	s.Grow(s.Size)
   274  	r := s.AddRel()
   275  	r.Sym = t
   276  	r.Off = int32(i)
   277  	r.Siz = 4
   278  	r.Type = objabi.R_ADDR
   279  	r.Add = add
   280  	return i + int64(r.Siz)
   281  }
   282  
   283  func (s *Symbol) AddRel() *Reloc {
   284  	s.R = append(s.R, Reloc{})
   285  	return &s.R[len(s.R)-1]
   286  }
   287  
   288  func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 {
   289  	off := s.Size
   290  	s.setUintXX(arch, off, v, int64(wid))
   291  	return off
   292  }
   293  
   294  func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 {
   295  	if s.Type == 0 {
   296  		s.Type = SDATA
   297  	}
   298  	s.Attr |= AttrReachable
   299  	if s.Size < off+wid {
   300  		s.Size = off + wid
   301  		s.Grow(s.Size)
   302  	}
   303  
   304  	switch wid {
   305  	case 1:
   306  		s.P[off] = uint8(v)
   307  	case 2:
   308  		arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
   309  	case 4:
   310  		arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
   311  	case 8:
   312  		arch.ByteOrder.PutUint64(s.P[off:], v)
   313  	}
   314  
   315  	return off + wid
   316  }
   317  
   318  func (s *Symbol) makeAuxInfo() {
   319  	if s.auxinfo == nil {
   320  		s.auxinfo = &AuxSymbol{extname: s.Name, plt: -1, got: -1}
   321  	}
   322  }
   323  
   324  func (s *Symbol) Extname() string {
   325  	if s.auxinfo == nil {
   326  		return s.Name
   327  	}
   328  	return s.auxinfo.extname
   329  }
   330  
   331  func (s *Symbol) SetExtname(n string) {
   332  	if s.auxinfo == nil {
   333  		if s.Name == n {
   334  			return
   335  		}
   336  		s.makeAuxInfo()
   337  	}
   338  	s.auxinfo.extname = n
   339  }
   340  
   341  func (s *Symbol) Dynimplib() string {
   342  	if s.auxinfo == nil {
   343  		return ""
   344  	}
   345  	return s.auxinfo.dynimplib
   346  }
   347  
   348  func (s *Symbol) Dynimpvers() string {
   349  	if s.auxinfo == nil {
   350  		return ""
   351  	}
   352  	return s.auxinfo.dynimpvers
   353  }
   354  
   355  func (s *Symbol) SetDynimplib(lib string) {
   356  	if s.auxinfo == nil {
   357  		s.makeAuxInfo()
   358  	}
   359  	s.auxinfo.dynimplib = lib
   360  }
   361  
   362  func (s *Symbol) SetDynimpvers(vers string) {
   363  	if s.auxinfo == nil {
   364  		s.makeAuxInfo()
   365  	}
   366  	s.auxinfo.dynimpvers = vers
   367  }
   368  
   369  func (s *Symbol) ResetDyninfo() {
   370  	if s.auxinfo != nil {
   371  		s.auxinfo.dynimplib = ""
   372  		s.auxinfo.dynimpvers = ""
   373  	}
   374  }
   375  
   376  func (s *Symbol) Localentry() uint8 {
   377  	if s.auxinfo == nil {
   378  		return 0
   379  	}
   380  	return s.auxinfo.localentry
   381  }
   382  
   383  func (s *Symbol) SetLocalentry(val uint8) {
   384  	if s.auxinfo == nil {
   385  		if val != 0 {
   386  			return
   387  		}
   388  		s.makeAuxInfo()
   389  	}
   390  	s.auxinfo.localentry = val
   391  }
   392  
   393  func (s *Symbol) Plt() int32 {
   394  	if s.auxinfo == nil {
   395  		return -1
   396  	}
   397  	return s.auxinfo.plt
   398  }
   399  
   400  func (s *Symbol) SetPlt(val int32) {
   401  	if s.auxinfo == nil {
   402  		if val == -1 {
   403  			return
   404  		}
   405  		s.makeAuxInfo()
   406  	}
   407  	s.auxinfo.plt = val
   408  }
   409  
   410  func (s *Symbol) Got() int32 {
   411  	if s.auxinfo == nil {
   412  		return -1
   413  	}
   414  	return s.auxinfo.got
   415  }
   416  
   417  func (s *Symbol) SetGot(val int32) {
   418  	if s.auxinfo == nil {
   419  		if val == -1 {
   420  			return
   421  		}
   422  		s.makeAuxInfo()
   423  	}
   424  	s.auxinfo.got = val
   425  }
   426  
   427  func (s *Symbol) ElfType() elf.SymType {
   428  	if s.auxinfo == nil {
   429  		return elf.STT_NOTYPE
   430  	}
   431  	return s.auxinfo.elftype
   432  }
   433  
   434  func (s *Symbol) SetElfType(val elf.SymType) {
   435  	if s.auxinfo == nil {
   436  		if val == elf.STT_NOTYPE {
   437  			return
   438  		}
   439  		s.makeAuxInfo()
   440  	}
   441  	s.auxinfo.elftype = val
   442  }
   443  
   444  // SortSub sorts a linked-list (by Sub) of *Symbol by Value.
   445  // Used for sub-symbols when loading host objects (see e.g. ldelf.go).
   446  func SortSub(l *Symbol) *Symbol {
   447  	if l == nil || l.Sub == nil {
   448  		return l
   449  	}
   450  
   451  	l1 := l
   452  	l2 := l
   453  	for {
   454  		l2 = l2.Sub
   455  		if l2 == nil {
   456  			break
   457  		}
   458  		l2 = l2.Sub
   459  		if l2 == nil {
   460  			break
   461  		}
   462  		l1 = l1.Sub
   463  	}
   464  
   465  	l2 = l1.Sub
   466  	l1.Sub = nil
   467  	l1 = SortSub(l)
   468  	l2 = SortSub(l2)
   469  
   470  	/* set up lead element */
   471  	if l1.Value < l2.Value {
   472  		l = l1
   473  		l1 = l1.Sub
   474  	} else {
   475  		l = l2
   476  		l2 = l2.Sub
   477  	}
   478  
   479  	le := l
   480  
   481  	for {
   482  		if l1 == nil {
   483  			for l2 != nil {
   484  				le.Sub = l2
   485  				le = l2
   486  				l2 = l2.Sub
   487  			}
   488  
   489  			le.Sub = nil
   490  			break
   491  		}
   492  
   493  		if l2 == nil {
   494  			for l1 != nil {
   495  				le.Sub = l1
   496  				le = l1
   497  				l1 = l1.Sub
   498  			}
   499  
   500  			break
   501  		}
   502  
   503  		if l1.Value < l2.Value {
   504  			le.Sub = l1
   505  			le = l1
   506  			l1 = l1.Sub
   507  		} else {
   508  			le.Sub = l2
   509  			le = l2
   510  			l2 = l2.Sub
   511  		}
   512  	}
   513  
   514  	le.Sub = nil
   515  	return l
   516  }
   517  
   518  type FuncInfo struct {
   519  	Args        int32
   520  	Locals      int32
   521  	Pcsp        Pcdata
   522  	Pcfile      Pcdata
   523  	Pcline      Pcdata
   524  	Pcinline    Pcdata
   525  	Pcdata      []Pcdata
   526  	Funcdata    []*Symbol
   527  	Funcdataoff []int64
   528  	File        []*Symbol
   529  	InlTree     []InlinedCall
   530  }
   531  
   532  // InlinedCall is a node in a local inlining tree (FuncInfo.InlTree).
   533  type InlinedCall struct {
   534  	Parent   int32   // index of parent in InlTree
   535  	File     *Symbol // file of the inlined call
   536  	Line     int32   // line number of the inlined call
   537  	Func     string  // name of the function that was inlined
   538  	ParentPC int32   // PC of the instruction just before the inlined body (offset from function start)
   539  }
   540  
   541  type Pcdata struct {
   542  	P []byte
   543  }