// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package sym import ( "cmd/internal/obj" "cmd/internal/objabi" "cmd/internal/sys" "debug/elf" "fmt" "log" ) // Symbol is an entry in the symbol table. type Symbol struct { Name string Type SymKind Version int16 Attr Attribute Dynid int32 Align int32 Value int64 Size int64 Sub *Symbol Outer *Symbol SymIdx LoaderSym auxinfo *AuxSymbol Sect *Section // P contains the raw symbol data. P []byte R []Reloc } // AuxSymbol contains less-frequently used sym.Symbol fields. type AuxSymbol struct { extname string dynimplib string dynimpvers string localentry uint8 plt int32 got int32 // ElfType is set for symbols read from shared libraries by ldshlibsyms. It // is not set for symbols defined by the packages being linked or by symbols // read by ldelf (and so is left as elf.STT_NOTYPE). elftype elf.SymType } const ( SymVerABI0 = 0 SymVerABIInternal = 1 SymVerStatic = 10 // Minimum version used by static (file-local) syms ) func ABIToVersion(abi obj.ABI) int { switch abi { case obj.ABI0: return SymVerABI0 case obj.ABIInternal: return SymVerABIInternal } return -1 } func VersionToABI(v int) (obj.ABI, bool) { switch v { case SymVerABI0: return obj.ABI0, true case SymVerABIInternal: return obj.ABIInternal, true } return ^obj.ABI(0), false } func (s *Symbol) String() string { if s.Version == 0 { return s.Name } return fmt.Sprintf("%s<%d>", s.Name, s.Version) } func (s *Symbol) IsFileLocal() bool { return s.Version >= SymVerStatic } func (s *Symbol) Len() int64 { return s.Size } func (s *Symbol) Length(dwarfContext interface{}) int64 { return s.Size } func (s *Symbol) Grow(siz int64) { if int64(int(siz)) != siz { log.Fatalf("symgrow size %d too long", siz) } if int64(len(s.P)) >= siz { return } if cap(s.P) < int(siz) { p := make([]byte, 2*(siz+1)) s.P = append(p[:0], s.P...) } s.P = s.P[:siz] } func (s *Symbol) AddBytes(bytes []byte) int64 { if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable s.P = append(s.P, bytes...) s.Size = int64(len(s.P)) return s.Size } func (s *Symbol) AddUint8(v uint8) int64 { off := s.Size if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable s.Size++ s.P = append(s.P, v) return off } func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 { return s.AddUintXX(arch, uint64(v), 2) } func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 { return s.AddUintXX(arch, uint64(v), 4) } func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 { return s.AddUintXX(arch, v, 8) } func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 { return s.AddUintXX(arch, v, arch.PtrSize) } func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 { return s.setUintXX(arch, r, uint64(v), 1) } func (s *Symbol) SetUint16(arch *sys.Arch, r int64, v uint16) int64 { return s.setUintXX(arch, r, uint64(v), 2) } func (s *Symbol) SetUint32(arch *sys.Arch, r int64, v uint32) int64 { return s.setUintXX(arch, r, uint64(v), 4) } func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 { return s.setUintXX(arch, r, v, int64(arch.PtrSize)) } func (s *Symbol) addAddrPlus(arch *sys.Arch, t *Symbol, add int64, typ objabi.RelocType) int64 { if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable i := s.Size s.Size += int64(arch.PtrSize) s.Grow(s.Size) r := s.AddRel() r.Sym = t r.Off = int32(i) r.Siz = uint8(arch.PtrSize) r.Type = typ r.Add = add return i + int64(r.Siz) } func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { return s.addAddrPlus(arch, t, add, objabi.R_ADDR) } func (s *Symbol) AddCURelativeAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { return s.addAddrPlus(arch, t, add, objabi.R_ADDRCUOFF) } func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 { if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable i := s.Size s.Size += 4 s.Grow(s.Size) r := s.AddRel() r.Sym = t r.Off = int32(i) r.Add = add r.Type = objabi.R_PCREL r.Siz = 4 if arch.Family == sys.S390X || arch.Family == sys.PPC64 { r.InitExt() } if arch.Family == sys.S390X { r.Variant = RV_390_DBL } return i + int64(r.Siz) } func (s *Symbol) AddAddr(arch *sys.Arch, t *Symbol) int64 { return s.AddAddrPlus(arch, t, 0) } func (s *Symbol) SetAddrPlus(arch *sys.Arch, off int64, t *Symbol, add int64) int64 { if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable if off+int64(arch.PtrSize) > s.Size { s.Size = off + int64(arch.PtrSize) s.Grow(s.Size) } r := s.AddRel() r.Sym = t r.Off = int32(off) r.Siz = uint8(arch.PtrSize) r.Type = objabi.R_ADDR r.Add = add return off + int64(r.Siz) } func (s *Symbol) SetAddr(arch *sys.Arch, off int64, t *Symbol) int64 { return s.SetAddrPlus(arch, off, t, 0) } func (s *Symbol) AddSize(arch *sys.Arch, t *Symbol) int64 { if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable i := s.Size s.Size += int64(arch.PtrSize) s.Grow(s.Size) r := s.AddRel() r.Sym = t r.Off = int32(i) r.Siz = uint8(arch.PtrSize) r.Type = objabi.R_SIZE return i + int64(r.Siz) } func (s *Symbol) AddAddrPlus4(t *Symbol, add int64) int64 { if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable i := s.Size s.Size += 4 s.Grow(s.Size) r := s.AddRel() r.Sym = t r.Off = int32(i) r.Siz = 4 r.Type = objabi.R_ADDR r.Add = add return i + int64(r.Siz) } func (s *Symbol) AddRel() *Reloc { s.R = append(s.R, Reloc{}) return &s.R[len(s.R)-1] } func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 { off := s.Size s.setUintXX(arch, off, v, int64(wid)) return off } func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 { if s.Type == 0 { s.Type = SDATA } s.Attr |= AttrReachable if s.Size < off+wid { s.Size = off + wid s.Grow(s.Size) } switch wid { case 1: s.P[off] = uint8(v) case 2: arch.ByteOrder.PutUint16(s.P[off:], uint16(v)) case 4: arch.ByteOrder.PutUint32(s.P[off:], uint32(v)) case 8: arch.ByteOrder.PutUint64(s.P[off:], v) } return off + wid } func (s *Symbol) makeAuxInfo() { if s.auxinfo == nil { s.auxinfo = &AuxSymbol{extname: s.Name, plt: -1, got: -1} } } func (s *Symbol) Extname() string { if s.auxinfo == nil { return s.Name } return s.auxinfo.extname } func (s *Symbol) SetExtname(n string) { if s.auxinfo == nil { if s.Name == n { return } s.makeAuxInfo() } s.auxinfo.extname = n } func (s *Symbol) Dynimplib() string { if s.auxinfo == nil { return "" } return s.auxinfo.dynimplib } func (s *Symbol) Dynimpvers() string { if s.auxinfo == nil { return "" } return s.auxinfo.dynimpvers } func (s *Symbol) SetDynimplib(lib string) { if s.auxinfo == nil { s.makeAuxInfo() } s.auxinfo.dynimplib = lib } func (s *Symbol) SetDynimpvers(vers string) { if s.auxinfo == nil { s.makeAuxInfo() } s.auxinfo.dynimpvers = vers } func (s *Symbol) ResetDyninfo() { if s.auxinfo != nil { s.auxinfo.dynimplib = "" s.auxinfo.dynimpvers = "" } } func (s *Symbol) Localentry() uint8 { if s.auxinfo == nil { return 0 } return s.auxinfo.localentry } func (s *Symbol) SetLocalentry(val uint8) { if s.auxinfo == nil { if val != 0 { return } s.makeAuxInfo() } s.auxinfo.localentry = val } func (s *Symbol) Plt() int32 { if s.auxinfo == nil { return -1 } return s.auxinfo.plt } func (s *Symbol) SetPlt(val int32) { if s.auxinfo == nil { if val == -1 { return } s.makeAuxInfo() } s.auxinfo.plt = val } func (s *Symbol) Got() int32 { if s.auxinfo == nil { return -1 } return s.auxinfo.got } func (s *Symbol) SetGot(val int32) { if s.auxinfo == nil { if val == -1 { return } s.makeAuxInfo() } s.auxinfo.got = val } func (s *Symbol) ElfType() elf.SymType { if s.auxinfo == nil { return elf.STT_NOTYPE } return s.auxinfo.elftype } func (s *Symbol) SetElfType(val elf.SymType) { if s.auxinfo == nil { if val == elf.STT_NOTYPE { return } s.makeAuxInfo() } s.auxinfo.elftype = val } type Pcdata struct { P []byte }