github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/loader/symbolbuilder.go (about) 1 // Copyright 2019 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 loader 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/internal/goobj" 9 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 10 "github.com/bir3/gocompiler/src/cmd/internal/sys" 11 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 12 "sort" 13 ) 14 15 // SymbolBuilder is a helper designed to help with the construction 16 // of new symbol contents. 17 type SymbolBuilder struct { 18 *extSymPayload // points to payload being updated 19 symIdx Sym // index of symbol being updated/constructed 20 l *Loader // loader 21 } 22 23 // MakeSymbolBuilder creates a symbol builder for use in constructing 24 // an entirely new symbol. 25 func (l *Loader) MakeSymbolBuilder(name string) *SymbolBuilder { 26 // for now assume that any new sym is intended to be static 27 symIdx := l.CreateStaticSym(name) 28 sb := &SymbolBuilder{l: l, symIdx: symIdx} 29 sb.extSymPayload = l.getPayload(symIdx) 30 return sb 31 } 32 33 // MakeSymbolUpdater creates a symbol builder helper for an existing 34 // symbol 'symIdx'. If 'symIdx' is not an external symbol, then create 35 // a clone of it (copy name, properties, etc) fix things up so that 36 // the lookup tables and caches point to the new version, not the old 37 // version. 38 func (l *Loader) MakeSymbolUpdater(symIdx Sym) *SymbolBuilder { 39 if symIdx == 0 { 40 panic("can't update the null symbol") 41 } 42 if !l.IsExternal(symIdx) { 43 // Create a clone with the same name/version/kind etc. 44 l.cloneToExternal(symIdx) 45 } 46 47 // Construct updater and return. 48 sb := &SymbolBuilder{l: l, symIdx: symIdx} 49 sb.extSymPayload = l.getPayload(symIdx) 50 return sb 51 } 52 53 // CreateSymForUpdate creates a symbol with given name and version, 54 // returns a CreateSymForUpdate for update. If the symbol already 55 // exists, it will update in-place. 56 func (l *Loader) CreateSymForUpdate(name string, version int) *SymbolBuilder { 57 s := l.LookupOrCreateSym(name, version) 58 l.SetAttrReachable(s, true) 59 return l.MakeSymbolUpdater(s) 60 } 61 62 // Getters for properties of the symbol we're working on. 63 64 func (sb *SymbolBuilder) Sym() Sym { return sb.symIdx } 65 func (sb *SymbolBuilder) Name() string { return sb.name } 66 func (sb *SymbolBuilder) Version() int { return sb.ver } 67 func (sb *SymbolBuilder) Type() sym.SymKind { return sb.kind } 68 func (sb *SymbolBuilder) Size() int64 { return sb.size } 69 func (sb *SymbolBuilder) Data() []byte { return sb.data } 70 func (sb *SymbolBuilder) Value() int64 { return sb.l.SymValue(sb.symIdx) } 71 func (sb *SymbolBuilder) Align() int32 { return sb.l.SymAlign(sb.symIdx) } 72 func (sb *SymbolBuilder) Localentry() uint8 { return sb.l.SymLocalentry(sb.symIdx) } 73 func (sb *SymbolBuilder) OnList() bool { return sb.l.AttrOnList(sb.symIdx) } 74 func (sb *SymbolBuilder) External() bool { return sb.l.AttrExternal(sb.symIdx) } 75 func (sb *SymbolBuilder) Extname() string { return sb.l.SymExtname(sb.symIdx) } 76 func (sb *SymbolBuilder) CgoExportDynamic() bool { return sb.l.AttrCgoExportDynamic(sb.symIdx) } 77 func (sb *SymbolBuilder) Dynimplib() string { return sb.l.SymDynimplib(sb.symIdx) } 78 func (sb *SymbolBuilder) Dynimpvers() string { return sb.l.SymDynimpvers(sb.symIdx) } 79 func (sb *SymbolBuilder) SubSym() Sym { return sb.l.SubSym(sb.symIdx) } 80 func (sb *SymbolBuilder) GoType() Sym { return sb.l.SymGoType(sb.symIdx) } 81 func (sb *SymbolBuilder) VisibilityHidden() bool { return sb.l.AttrVisibilityHidden(sb.symIdx) } 82 func (sb *SymbolBuilder) Sect() *sym.Section { return sb.l.SymSect(sb.symIdx) } 83 84 // Setters for symbol properties. 85 86 func (sb *SymbolBuilder) SetType(kind sym.SymKind) { sb.kind = kind } 87 func (sb *SymbolBuilder) SetSize(size int64) { sb.size = size } 88 func (sb *SymbolBuilder) SetData(data []byte) { sb.data = data } 89 func (sb *SymbolBuilder) SetOnList(v bool) { sb.l.SetAttrOnList(sb.symIdx, v) } 90 func (sb *SymbolBuilder) SetExternal(v bool) { sb.l.SetAttrExternal(sb.symIdx, v) } 91 func (sb *SymbolBuilder) SetValue(v int64) { sb.l.SetSymValue(sb.symIdx, v) } 92 func (sb *SymbolBuilder) SetAlign(align int32) { sb.l.SetSymAlign(sb.symIdx, align) } 93 func (sb *SymbolBuilder) SetLocalentry(value uint8) { sb.l.SetSymLocalentry(sb.symIdx, value) } 94 func (sb *SymbolBuilder) SetExtname(value string) { sb.l.SetSymExtname(sb.symIdx, value) } 95 func (sb *SymbolBuilder) SetDynimplib(value string) { sb.l.SetSymDynimplib(sb.symIdx, value) } 96 func (sb *SymbolBuilder) SetDynimpvers(value string) { sb.l.SetSymDynimpvers(sb.symIdx, value) } 97 func (sb *SymbolBuilder) SetPlt(value int32) { sb.l.SetPlt(sb.symIdx, value) } 98 func (sb *SymbolBuilder) SetGot(value int32) { sb.l.SetGot(sb.symIdx, value) } 99 func (sb *SymbolBuilder) SetSpecial(value bool) { sb.l.SetAttrSpecial(sb.symIdx, value) } 100 func (sb *SymbolBuilder) SetLocal(value bool) { sb.l.SetAttrLocal(sb.symIdx, value) } 101 func (sb *SymbolBuilder) SetVisibilityHidden(value bool) { 102 sb.l.SetAttrVisibilityHidden(sb.symIdx, value) 103 } 104 func (sb *SymbolBuilder) SetNotInSymbolTable(value bool) { 105 sb.l.SetAttrNotInSymbolTable(sb.symIdx, value) 106 } 107 func (sb *SymbolBuilder) SetSect(sect *sym.Section) { sb.l.SetSymSect(sb.symIdx, sect) } 108 109 func (sb *SymbolBuilder) AddBytes(data []byte) { 110 if sb.kind == 0 { 111 sb.kind = sym.SDATA 112 } 113 sb.data = append(sb.data, data...) 114 sb.size = int64(len(sb.data)) 115 } 116 117 func (sb *SymbolBuilder) Relocs() Relocs { 118 return sb.l.Relocs(sb.symIdx) 119 } 120 121 // ResetRelocs removes all relocations on this symbol. 122 func (sb *SymbolBuilder) ResetRelocs() { 123 sb.relocs = sb.relocs[:0] 124 } 125 126 // SetRelocType sets the type of the 'i'-th relocation on this sym to 't' 127 func (sb *SymbolBuilder) SetRelocType(i int, t objabi.RelocType) { 128 sb.relocs[i].SetType(uint16(t)) 129 } 130 131 // SetRelocSym sets the target sym of the 'i'-th relocation on this sym to 's' 132 func (sb *SymbolBuilder) SetRelocSym(i int, tgt Sym) { 133 sb.relocs[i].SetSym(goobj.SymRef{PkgIdx: 0, SymIdx: uint32(tgt)}) 134 } 135 136 // SetRelocAdd sets the addend of the 'i'-th relocation on this sym to 'a' 137 func (sb *SymbolBuilder) SetRelocAdd(i int, a int64) { 138 sb.relocs[i].SetAdd(a) 139 } 140 141 // Add n relocations, return a handle to the relocations. 142 func (sb *SymbolBuilder) AddRelocs(n int) Relocs { 143 sb.relocs = append(sb.relocs, make([]goobj.Reloc, n)...) 144 return sb.l.Relocs(sb.symIdx) 145 } 146 147 // Add a relocation with given type, return its handle and index 148 // (to set other fields). 149 func (sb *SymbolBuilder) AddRel(typ objabi.RelocType) (Reloc, int) { 150 j := len(sb.relocs) 151 sb.relocs = append(sb.relocs, goobj.Reloc{}) 152 sb.relocs[j].SetType(uint16(typ)) 153 relocs := sb.Relocs() 154 return relocs.At(j), j 155 } 156 157 // Sort relocations by offset. 158 func (sb *SymbolBuilder) SortRelocs() { 159 sort.Sort((*relocsByOff)(sb.extSymPayload)) 160 } 161 162 // Implement sort.Interface 163 type relocsByOff extSymPayload 164 165 func (p *relocsByOff) Len() int { return len(p.relocs) } 166 func (p *relocsByOff) Less(i, j int) bool { return p.relocs[i].Off() < p.relocs[j].Off() } 167 func (p *relocsByOff) Swap(i, j int) { 168 p.relocs[i], p.relocs[j] = p.relocs[j], p.relocs[i] 169 } 170 171 func (sb *SymbolBuilder) Reachable() bool { 172 return sb.l.AttrReachable(sb.symIdx) 173 } 174 175 func (sb *SymbolBuilder) SetReachable(v bool) { 176 sb.l.SetAttrReachable(sb.symIdx, v) 177 } 178 179 func (sb *SymbolBuilder) ReadOnly() bool { 180 return sb.l.AttrReadOnly(sb.symIdx) 181 } 182 183 func (sb *SymbolBuilder) SetReadOnly(v bool) { 184 sb.l.SetAttrReadOnly(sb.symIdx, v) 185 } 186 187 func (sb *SymbolBuilder) DuplicateOK() bool { 188 return sb.l.AttrDuplicateOK(sb.symIdx) 189 } 190 191 func (sb *SymbolBuilder) SetDuplicateOK(v bool) { 192 sb.l.SetAttrDuplicateOK(sb.symIdx, v) 193 } 194 195 func (sb *SymbolBuilder) Outer() Sym { 196 return sb.l.OuterSym(sb.symIdx) 197 } 198 199 func (sb *SymbolBuilder) Sub() Sym { 200 return sb.l.SubSym(sb.symIdx) 201 } 202 203 func (sb *SymbolBuilder) SortSub() { 204 sb.l.SortSub(sb.symIdx) 205 } 206 207 func (sb *SymbolBuilder) AddInteriorSym(sub Sym) { 208 sb.l.AddInteriorSym(sb.symIdx, sub) 209 } 210 211 func (sb *SymbolBuilder) AddUint8(v uint8) int64 { 212 off := sb.size 213 if sb.kind == 0 { 214 sb.kind = sym.SDATA 215 } 216 sb.size++ 217 sb.data = append(sb.data, v) 218 return off 219 } 220 221 func (sb *SymbolBuilder) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 { 222 off := sb.size 223 sb.setUintXX(arch, off, v, int64(wid)) 224 return off 225 } 226 227 func (sb *SymbolBuilder) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 { 228 if sb.kind == 0 { 229 sb.kind = sym.SDATA 230 } 231 if sb.size < off+wid { 232 sb.size = off + wid 233 sb.Grow(sb.size) 234 } 235 236 switch wid { 237 case 1: 238 sb.data[off] = uint8(v) 239 case 2: 240 arch.ByteOrder.PutUint16(sb.data[off:], uint16(v)) 241 case 4: 242 arch.ByteOrder.PutUint32(sb.data[off:], uint32(v)) 243 case 8: 244 arch.ByteOrder.PutUint64(sb.data[off:], v) 245 } 246 247 return off + wid 248 } 249 250 func (sb *SymbolBuilder) AddUint16(arch *sys.Arch, v uint16) int64 { 251 return sb.AddUintXX(arch, uint64(v), 2) 252 } 253 254 func (sb *SymbolBuilder) AddUint32(arch *sys.Arch, v uint32) int64 { 255 return sb.AddUintXX(arch, uint64(v), 4) 256 } 257 258 func (sb *SymbolBuilder) AddUint64(arch *sys.Arch, v uint64) int64 { 259 return sb.AddUintXX(arch, v, 8) 260 } 261 262 func (sb *SymbolBuilder) AddUint(arch *sys.Arch, v uint64) int64 { 263 return sb.AddUintXX(arch, v, arch.PtrSize) 264 } 265 266 func (sb *SymbolBuilder) SetUint8(arch *sys.Arch, r int64, v uint8) int64 { 267 return sb.setUintXX(arch, r, uint64(v), 1) 268 } 269 270 func (sb *SymbolBuilder) SetUint16(arch *sys.Arch, r int64, v uint16) int64 { 271 return sb.setUintXX(arch, r, uint64(v), 2) 272 } 273 274 func (sb *SymbolBuilder) SetUint32(arch *sys.Arch, r int64, v uint32) int64 { 275 return sb.setUintXX(arch, r, uint64(v), 4) 276 } 277 278 func (sb *SymbolBuilder) SetUint(arch *sys.Arch, r int64, v uint64) int64 { 279 return sb.setUintXX(arch, r, v, int64(arch.PtrSize)) 280 } 281 282 func (sb *SymbolBuilder) SetUintptr(arch *sys.Arch, r int64, v uintptr) int64 { 283 return sb.setUintXX(arch, r, uint64(v), int64(arch.PtrSize)) 284 } 285 286 func (sb *SymbolBuilder) SetAddrPlus(arch *sys.Arch, off int64, tgt Sym, add int64) int64 { 287 if sb.Type() == 0 { 288 sb.SetType(sym.SDATA) 289 } 290 if off+int64(arch.PtrSize) > sb.size { 291 sb.size = off + int64(arch.PtrSize) 292 sb.Grow(sb.size) 293 } 294 r, _ := sb.AddRel(objabi.R_ADDR) 295 r.SetSym(tgt) 296 r.SetOff(int32(off)) 297 r.SetSiz(uint8(arch.PtrSize)) 298 r.SetAdd(add) 299 return off + int64(r.Siz()) 300 } 301 302 func (sb *SymbolBuilder) SetAddr(arch *sys.Arch, off int64, tgt Sym) int64 { 303 return sb.SetAddrPlus(arch, off, tgt, 0) 304 } 305 306 func (sb *SymbolBuilder) AddStringAt(off int64, str string) int64 { 307 strLen := int64(len(str)) 308 if off+strLen > int64(len(sb.data)) { 309 panic("attempt to write past end of buffer") 310 } 311 copy(sb.data[off:off+strLen], str) 312 return off + strLen 313 } 314 315 // AddCStringAt adds str plus a null terminating byte. 316 func (sb *SymbolBuilder) AddCStringAt(off int64, str string) int64 { 317 strLen := int64(len(str)) 318 if off+strLen+1 > int64(len(sb.data)) { 319 panic("attempt to write past end of buffer") 320 } 321 copy(sb.data[off:off+strLen], str) 322 sb.data[off+strLen] = 0 323 return off + strLen + 1 324 } 325 326 func (sb *SymbolBuilder) Addstring(str string) int64 { 327 if sb.kind == 0 { 328 sb.kind = sym.SNOPTRDATA 329 } 330 r := sb.size 331 sb.data = append(sb.data, str...) 332 sb.data = append(sb.data, 0) 333 sb.size = int64(len(sb.data)) 334 return r 335 } 336 337 func (sb *SymbolBuilder) SetBytesAt(off int64, b []byte) int64 { 338 datLen := int64(len(b)) 339 if off+datLen > int64(len(sb.data)) { 340 panic("attempt to write past end of buffer") 341 } 342 copy(sb.data[off:off+datLen], b) 343 return off + datLen 344 } 345 346 func (sb *SymbolBuilder) addSymRef(tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 { 347 if sb.kind == 0 { 348 sb.kind = sym.SDATA 349 } 350 i := sb.size 351 352 sb.size += int64(rsize) 353 sb.Grow(sb.size) 354 355 r, _ := sb.AddRel(typ) 356 r.SetSym(tgt) 357 r.SetOff(int32(i)) 358 r.SetSiz(uint8(rsize)) 359 r.SetAdd(add) 360 361 return i + int64(rsize) 362 } 363 364 // Add a symbol reference (relocation) with given type, addend, and size 365 // (the most generic form). 366 func (sb *SymbolBuilder) AddSymRef(arch *sys.Arch, tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 { 367 return sb.addSymRef(tgt, add, typ, rsize) 368 } 369 370 func (sb *SymbolBuilder) AddAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 { 371 return sb.addSymRef(tgt, add, objabi.R_ADDR, arch.PtrSize) 372 } 373 374 func (sb *SymbolBuilder) AddAddrPlus4(arch *sys.Arch, tgt Sym, add int64) int64 { 375 return sb.addSymRef(tgt, add, objabi.R_ADDR, 4) 376 } 377 378 func (sb *SymbolBuilder) AddAddr(arch *sys.Arch, tgt Sym) int64 { 379 return sb.AddAddrPlus(arch, tgt, 0) 380 } 381 382 func (sb *SymbolBuilder) AddPEImageRelativeAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 { 383 return sb.addSymRef(tgt, add, objabi.R_PEIMAGEOFF, 4) 384 } 385 386 func (sb *SymbolBuilder) AddPCRelPlus(arch *sys.Arch, tgt Sym, add int64) int64 { 387 return sb.addSymRef(tgt, add, objabi.R_PCREL, 4) 388 } 389 390 func (sb *SymbolBuilder) AddCURelativeAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 { 391 return sb.addSymRef(tgt, add, objabi.R_ADDRCUOFF, arch.PtrSize) 392 } 393 394 func (sb *SymbolBuilder) AddSize(arch *sys.Arch, tgt Sym) int64 { 395 return sb.addSymRef(tgt, 0, objabi.R_SIZE, arch.PtrSize) 396 } 397 398 // GenAddAddrPlusFunc returns a function to be called when capturing 399 // a function symbol's address. In later stages of the link (when 400 // address assignment is done) when doing internal linking and 401 // targeting an executable, we can just emit the address of a function 402 // directly instead of generating a relocation. Clients can call 403 // this function (setting 'internalExec' based on build mode and target) 404 // and then invoke the returned function in roughly the same way that 405 // loader.*SymbolBuilder.AddAddrPlus would be used. 406 func GenAddAddrPlusFunc(internalExec bool) func(s *SymbolBuilder, arch *sys.Arch, tgt Sym, add int64) int64 { 407 if internalExec { 408 return func(s *SymbolBuilder, arch *sys.Arch, tgt Sym, add int64) int64 { 409 if v := s.l.SymValue(tgt); v != 0 { 410 return s.AddUint(arch, uint64(v+add)) 411 } 412 return s.AddAddrPlus(arch, tgt, add) 413 } 414 } else { 415 return (*SymbolBuilder).AddAddrPlus 416 } 417 } 418 419 func (sb *SymbolBuilder) MakeWritable() { 420 if sb.ReadOnly() { 421 sb.data = append([]byte(nil), sb.data...) 422 sb.l.SetAttrReadOnly(sb.symIdx, false) 423 } 424 } 425 426 func (sb *SymbolBuilder) AddUleb(v uint64) { 427 if v < 128 { // common case: 1 byte 428 sb.AddUint8(uint8(v)) 429 return 430 } 431 for { 432 c := uint8(v & 0x7f) 433 v >>= 7 434 if v != 0 { 435 c |= 0x80 436 } 437 sb.AddUint8(c) 438 if c&0x80 == 0 { 439 break 440 } 441 } 442 }