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