...

Source file src/cmd/link/internal/sym/symbol.go

     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/obj"
     9		"cmd/internal/objabi"
    10		"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		Lib         *Library // Package defining this symbol
    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		Autom       []Auto
   522		Pcsp        Pcdata
   523		Pcfile      Pcdata
   524		Pcline      Pcdata
   525		Pcinline    Pcdata
   526		Pcdata      []Pcdata
   527		Funcdata    []*Symbol
   528		Funcdataoff []int64
   529		File        []*Symbol
   530		InlTree     []InlinedCall
   531	}
   532	
   533	// InlinedCall is a node in a local inlining tree (FuncInfo.InlTree).
   534	type InlinedCall struct {
   535		Parent   int32   // index of parent in InlTree
   536		File     *Symbol // file of the inlined call
   537		Line     int32   // line number of the inlined call
   538		Func     *Symbol // function that was inlined
   539		ParentPC int32   // PC of the instruction just before the inlined body (offset from function start)
   540	}
   541	
   542	type Pcdata struct {
   543		P []byte
   544	}
   545	
   546	type Auto struct {
   547		Asym    *Symbol
   548		Gotype  *Symbol
   549		Aoffset int32
   550		Name    int16
   551	}
   552	

View as plain text