github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/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  	Extname     string
    19  	Type        SymKind
    20  	Version     int16
    21  	Attr        Attribute
    22  	Localentry  uint8
    23  	Dynid       int32
    24  	Plt         int32
    25  	Got         int32
    26  	Align       int32
    27  	Elfsym      int32
    28  	LocalElfsym int32
    29  	Value       int64
    30  	Size        int64
    31  	// ElfType is set for symbols read from shared libraries by ldshlibsyms. It
    32  	// is not set for symbols defined by the packages being linked or by symbols
    33  	// read by ldelf (and so is left as elf.STT_NOTYPE).
    34  	ElfType     elf.SymType
    35  	Sub         *Symbol
    36  	Outer       *Symbol
    37  	Gotype      *Symbol
    38  	Reachparent *Symbol
    39  	File        string
    40  	Dynimplib   string
    41  	Dynimpvers  string
    42  	Sect        *Section
    43  	FuncInfo    *FuncInfo
    44  	// P contains the raw symbol data.
    45  	P []byte
    46  	R []Reloc
    47  }
    48  
    49  func (s *Symbol) String() string {
    50  	if s.Version == 0 {
    51  		return s.Name
    52  	}
    53  	return fmt.Sprintf("%s<%d>", s.Name, s.Version)
    54  }
    55  
    56  func (s *Symbol) ElfsymForReloc() int32 {
    57  	// If putelfsym created a local version of this symbol, use that in all
    58  	// relocations.
    59  	if s.LocalElfsym != 0 {
    60  		return s.LocalElfsym
    61  	} else {
    62  		return s.Elfsym
    63  	}
    64  }
    65  
    66  func (s *Symbol) Len() int64 {
    67  	return s.Size
    68  }
    69  
    70  func (s *Symbol) Grow(siz int64) {
    71  	if int64(int(siz)) != siz {
    72  		log.Fatalf("symgrow size %d too long", siz)
    73  	}
    74  	if int64(len(s.P)) >= siz {
    75  		return
    76  	}
    77  	if cap(s.P) < int(siz) {
    78  		p := make([]byte, 2*(siz+1))
    79  		s.P = append(p[:0], s.P...)
    80  	}
    81  	s.P = s.P[:siz]
    82  }
    83  
    84  func (s *Symbol) AddBytes(bytes []byte) int64 {
    85  	if s.Type == 0 {
    86  		s.Type = SDATA
    87  	}
    88  	s.Attr |= AttrReachable
    89  	s.P = append(s.P, bytes...)
    90  	s.Size = int64(len(s.P))
    91  
    92  	return s.Size
    93  }
    94  
    95  func (s *Symbol) AddUint8(v uint8) int64 {
    96  	off := s.Size
    97  	if s.Type == 0 {
    98  		s.Type = SDATA
    99  	}
   100  	s.Attr |= AttrReachable
   101  	s.Size++
   102  	s.P = append(s.P, v)
   103  
   104  	return off
   105  }
   106  
   107  func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 {
   108  	return s.AddUintXX(arch, uint64(v), 2)
   109  }
   110  
   111  func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 {
   112  	return s.AddUintXX(arch, uint64(v), 4)
   113  }
   114  
   115  func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 {
   116  	return s.AddUintXX(arch, v, 8)
   117  }
   118  
   119  func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 {
   120  	return s.AddUintXX(arch, v, arch.PtrSize)
   121  }
   122  
   123  func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 {
   124  	return s.setUintXX(arch, r, uint64(v), 1)
   125  }
   126  
   127  func (s *Symbol) SetUint32(arch *sys.Arch, r int64, v uint32) int64 {
   128  	return s.setUintXX(arch, r, uint64(v), 4)
   129  }
   130  
   131  func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 {
   132  	return s.setUintXX(arch, r, v, int64(arch.PtrSize))
   133  }
   134  
   135  func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
   136  	if s.Type == 0 {
   137  		s.Type = SDATA
   138  	}
   139  	s.Attr |= AttrReachable
   140  	i := s.Size
   141  	s.Size += int64(arch.PtrSize)
   142  	s.Grow(s.Size)
   143  	r := s.AddRel()
   144  	r.Sym = t
   145  	r.Off = int32(i)
   146  	r.Siz = uint8(arch.PtrSize)
   147  	r.Type = objabi.R_ADDR
   148  	r.Add = add
   149  	return i + int64(r.Siz)
   150  }
   151  
   152  func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
   153  	if s.Type == 0 {
   154  		s.Type = SDATA
   155  	}
   156  	s.Attr |= AttrReachable
   157  	i := s.Size
   158  	s.Size += 4
   159  	s.Grow(s.Size)
   160  	r := s.AddRel()
   161  	r.Sym = t
   162  	r.Off = int32(i)
   163  	r.Add = add
   164  	r.Type = objabi.R_PCREL
   165  	r.Siz = 4
   166  	if arch.Family == sys.S390X {
   167  		r.Variant = RV_390_DBL
   168  	}
   169  	return i + int64(r.Siz)
   170  }
   171  
   172  func (s *Symbol) AddAddr(arch *sys.Arch, t *Symbol) int64 {
   173  	return s.AddAddrPlus(arch, t, 0)
   174  }
   175  
   176  func (s *Symbol) SetAddrPlus(arch *sys.Arch, off int64, t *Symbol, add int64) int64 {
   177  	if s.Type == 0 {
   178  		s.Type = SDATA
   179  	}
   180  	s.Attr |= AttrReachable
   181  	if off+int64(arch.PtrSize) > s.Size {
   182  		s.Size = off + int64(arch.PtrSize)
   183  		s.Grow(s.Size)
   184  	}
   185  
   186  	r := s.AddRel()
   187  	r.Sym = t
   188  	r.Off = int32(off)
   189  	r.Siz = uint8(arch.PtrSize)
   190  	r.Type = objabi.R_ADDR
   191  	r.Add = add
   192  	return off + int64(r.Siz)
   193  }
   194  
   195  func (s *Symbol) SetAddr(arch *sys.Arch, off int64, t *Symbol) int64 {
   196  	return s.SetAddrPlus(arch, off, t, 0)
   197  }
   198  
   199  func (s *Symbol) AddSize(arch *sys.Arch, t *Symbol) int64 {
   200  	if s.Type == 0 {
   201  		s.Type = SDATA
   202  	}
   203  	s.Attr |= AttrReachable
   204  	i := s.Size
   205  	s.Size += int64(arch.PtrSize)
   206  	s.Grow(s.Size)
   207  	r := s.AddRel()
   208  	r.Sym = t
   209  	r.Off = int32(i)
   210  	r.Siz = uint8(arch.PtrSize)
   211  	r.Type = objabi.R_SIZE
   212  	return i + int64(r.Siz)
   213  }
   214  
   215  func (s *Symbol) AddAddrPlus4(t *Symbol, add int64) int64 {
   216  	if s.Type == 0 {
   217  		s.Type = SDATA
   218  	}
   219  	s.Attr |= AttrReachable
   220  	i := s.Size
   221  	s.Size += 4
   222  	s.Grow(s.Size)
   223  	r := s.AddRel()
   224  	r.Sym = t
   225  	r.Off = int32(i)
   226  	r.Siz = 4
   227  	r.Type = objabi.R_ADDR
   228  	r.Add = add
   229  	return i + int64(r.Siz)
   230  }
   231  
   232  func (s *Symbol) AddRel() *Reloc {
   233  	s.R = append(s.R, Reloc{})
   234  	return &s.R[len(s.R)-1]
   235  }
   236  
   237  func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 {
   238  	off := s.Size
   239  	s.setUintXX(arch, off, v, int64(wid))
   240  	return off
   241  }
   242  
   243  func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 {
   244  	if s.Type == 0 {
   245  		s.Type = SDATA
   246  	}
   247  	s.Attr |= AttrReachable
   248  	if s.Size < off+wid {
   249  		s.Size = off + wid
   250  		s.Grow(s.Size)
   251  	}
   252  
   253  	switch wid {
   254  	case 1:
   255  		s.P[off] = uint8(v)
   256  	case 2:
   257  		arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
   258  	case 4:
   259  		arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
   260  	case 8:
   261  		arch.ByteOrder.PutUint64(s.P[off:], v)
   262  	}
   263  
   264  	return off + wid
   265  }
   266  
   267  // SortSub sorts a linked-list (by Sub) of *Symbol by Value.
   268  // Used for sub-symbols when loading host objects (see e.g. ldelf.go).
   269  func SortSub(l *Symbol) *Symbol {
   270  	if l == nil || l.Sub == nil {
   271  		return l
   272  	}
   273  
   274  	l1 := l
   275  	l2 := l
   276  	for {
   277  		l2 = l2.Sub
   278  		if l2 == nil {
   279  			break
   280  		}
   281  		l2 = l2.Sub
   282  		if l2 == nil {
   283  			break
   284  		}
   285  		l1 = l1.Sub
   286  	}
   287  
   288  	l2 = l1.Sub
   289  	l1.Sub = nil
   290  	l1 = SortSub(l)
   291  	l2 = SortSub(l2)
   292  
   293  	/* set up lead element */
   294  	if l1.Value < l2.Value {
   295  		l = l1
   296  		l1 = l1.Sub
   297  	} else {
   298  		l = l2
   299  		l2 = l2.Sub
   300  	}
   301  
   302  	le := l
   303  
   304  	for {
   305  		if l1 == nil {
   306  			for l2 != nil {
   307  				le.Sub = l2
   308  				le = l2
   309  				l2 = l2.Sub
   310  			}
   311  
   312  			le.Sub = nil
   313  			break
   314  		}
   315  
   316  		if l2 == nil {
   317  			for l1 != nil {
   318  				le.Sub = l1
   319  				le = l1
   320  				l1 = l1.Sub
   321  			}
   322  
   323  			break
   324  		}
   325  
   326  		if l1.Value < l2.Value {
   327  			le.Sub = l1
   328  			le = l1
   329  			l1 = l1.Sub
   330  		} else {
   331  			le.Sub = l2
   332  			le = l2
   333  			l2 = l2.Sub
   334  		}
   335  	}
   336  
   337  	le.Sub = nil
   338  	return l
   339  }
   340  
   341  type FuncInfo struct {
   342  	Args        int32
   343  	Locals      int32
   344  	Autom       []Auto
   345  	Pcsp        Pcdata
   346  	Pcfile      Pcdata
   347  	Pcline      Pcdata
   348  	Pcinline    Pcdata
   349  	Pcdata      []Pcdata
   350  	Funcdata    []*Symbol
   351  	Funcdataoff []int64
   352  	File        []*Symbol
   353  	InlTree     []InlinedCall
   354  }
   355  
   356  // InlinedCall is a node in a local inlining tree (FuncInfo.InlTree).
   357  type InlinedCall struct {
   358  	Parent int32   // index of parent in InlTree
   359  	File   *Symbol // file of the inlined call
   360  	Line   int32   // line number of the inlined call
   361  	Func   *Symbol // function that was inlined
   362  }
   363  
   364  type Pcdata struct {
   365  	P []byte
   366  }
   367  
   368  type Auto struct {
   369  	Asym    *Symbol
   370  	Gotype  *Symbol
   371  	Aoffset int32
   372  	Name    int16
   373  }