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 }