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