github.com/bir3/gocompiler@v0.3.205/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) setReachable() { 180 sb.SetReachable(true) 181 } 182 183 func (sb *SymbolBuilder) ReadOnly() bool { 184 return sb.l.AttrReadOnly(sb.symIdx) 185 } 186 187 func (sb *SymbolBuilder) SetReadOnly(v bool) { 188 sb.l.SetAttrReadOnly(sb.symIdx, v) 189 } 190 191 func (sb *SymbolBuilder) DuplicateOK() bool { 192 return sb.l.AttrDuplicateOK(sb.symIdx) 193 } 194 195 func (sb *SymbolBuilder) SetDuplicateOK(v bool) { 196 sb.l.SetAttrDuplicateOK(sb.symIdx, v) 197 } 198 199 func (sb *SymbolBuilder) Outer() Sym { 200 return sb.l.OuterSym(sb.symIdx) 201 } 202 203 func (sb *SymbolBuilder) Sub() Sym { 204 return sb.l.SubSym(sb.symIdx) 205 } 206 207 func (sb *SymbolBuilder) SortSub() { 208 sb.l.SortSub(sb.symIdx) 209 } 210 211 func (sb *SymbolBuilder) AddInteriorSym(sub Sym) { 212 sb.l.AddInteriorSym(sb.symIdx, sub) 213 } 214 215 func (sb *SymbolBuilder) AddUint8(v uint8) int64 { 216 off := sb.size 217 if sb.kind == 0 { 218 sb.kind = sym.SDATA 219 } 220 sb.size++ 221 sb.data = append(sb.data, v) 222 return off 223 } 224 225 func (sb *SymbolBuilder) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 { 226 off := sb.size 227 sb.setUintXX(arch, off, v, int64(wid)) 228 return off 229 } 230 231 func (sb *SymbolBuilder) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 { 232 if sb.kind == 0 { 233 sb.kind = sym.SDATA 234 } 235 if sb.size < off+wid { 236 sb.size = off + wid 237 sb.Grow(sb.size) 238 } 239 240 switch wid { 241 case 1: 242 sb.data[off] = uint8(v) 243 case 2: 244 arch.ByteOrder.PutUint16(sb.data[off:], uint16(v)) 245 case 4: 246 arch.ByteOrder.PutUint32(sb.data[off:], uint32(v)) 247 case 8: 248 arch.ByteOrder.PutUint64(sb.data[off:], v) 249 } 250 251 return off + wid 252 } 253 254 func (sb *SymbolBuilder) AddUint16(arch *sys.Arch, v uint16) int64 { 255 return sb.AddUintXX(arch, uint64(v), 2) 256 } 257 258 func (sb *SymbolBuilder) AddUint32(arch *sys.Arch, v uint32) int64 { 259 return sb.AddUintXX(arch, uint64(v), 4) 260 } 261 262 func (sb *SymbolBuilder) AddUint64(arch *sys.Arch, v uint64) int64 { 263 return sb.AddUintXX(arch, v, 8) 264 } 265 266 func (sb *SymbolBuilder) AddUint(arch *sys.Arch, v uint64) int64 { 267 return sb.AddUintXX(arch, v, arch.PtrSize) 268 } 269 270 func (sb *SymbolBuilder) SetUint8(arch *sys.Arch, r int64, v uint8) int64 { 271 return sb.setUintXX(arch, r, uint64(v), 1) 272 } 273 274 func (sb *SymbolBuilder) SetUint16(arch *sys.Arch, r int64, v uint16) int64 { 275 return sb.setUintXX(arch, r, uint64(v), 2) 276 } 277 278 func (sb *SymbolBuilder) SetUint32(arch *sys.Arch, r int64, v uint32) int64 { 279 return sb.setUintXX(arch, r, uint64(v), 4) 280 } 281 282 func (sb *SymbolBuilder) SetUint(arch *sys.Arch, r int64, v uint64) int64 { 283 return sb.setUintXX(arch, r, v, int64(arch.PtrSize)) 284 } 285 286 func (sb *SymbolBuilder) SetUintptr(arch *sys.Arch, r int64, v uintptr) int64 { 287 return sb.setUintXX(arch, r, uint64(v), int64(arch.PtrSize)) 288 } 289 290 func (sb *SymbolBuilder) SetAddrPlus(arch *sys.Arch, off int64, tgt Sym, add int64) int64 { 291 if sb.Type() == 0 { 292 sb.SetType(sym.SDATA) 293 } 294 if off+int64(arch.PtrSize) > sb.size { 295 sb.size = off + int64(arch.PtrSize) 296 sb.Grow(sb.size) 297 } 298 r, _ := sb.AddRel(objabi.R_ADDR) 299 r.SetSym(tgt) 300 r.SetOff(int32(off)) 301 r.SetSiz(uint8(arch.PtrSize)) 302 r.SetAdd(add) 303 return off + int64(r.Siz()) 304 } 305 306 func (sb *SymbolBuilder) SetAddr(arch *sys.Arch, off int64, tgt Sym) int64 { 307 return sb.SetAddrPlus(arch, off, tgt, 0) 308 } 309 310 func (sb *SymbolBuilder) AddStringAt(off int64, str string) int64 { 311 strLen := int64(len(str)) 312 if off+strLen > int64(len(sb.data)) { 313 panic("attempt to write past end of buffer") 314 } 315 copy(sb.data[off:off+strLen], str) 316 return off + strLen 317 } 318 319 // AddCStringAt adds str plus a null terminating byte. 320 func (sb *SymbolBuilder) AddCStringAt(off int64, str string) int64 { 321 strLen := int64(len(str)) 322 if off+strLen+1 > int64(len(sb.data)) { 323 panic("attempt to write past end of buffer") 324 } 325 copy(sb.data[off:off+strLen], str) 326 sb.data[off+strLen] = 0 327 return off + strLen + 1 328 } 329 330 func (sb *SymbolBuilder) Addstring(str string) int64 { 331 if sb.kind == 0 { 332 sb.kind = sym.SNOPTRDATA 333 } 334 r := sb.size 335 if sb.name == ".shstrtab" { 336 // FIXME: find a better mechanism for this 337 sb.l.elfsetstring(str, int(r)) 338 } 339 sb.data = append(sb.data, str...) 340 sb.data = append(sb.data, 0) 341 sb.size = int64(len(sb.data)) 342 return r 343 } 344 345 func (sb *SymbolBuilder) SetBytesAt(off int64, b []byte) int64 { 346 datLen := int64(len(b)) 347 if off+datLen > int64(len(sb.data)) { 348 panic("attempt to write past end of buffer") 349 } 350 copy(sb.data[off:off+datLen], b) 351 return off + datLen 352 } 353 354 func (sb *SymbolBuilder) addSymRef(tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 { 355 if sb.kind == 0 { 356 sb.kind = sym.SDATA 357 } 358 i := sb.size 359 360 sb.size += int64(rsize) 361 sb.Grow(sb.size) 362 363 r, _ := sb.AddRel(typ) 364 r.SetSym(tgt) 365 r.SetOff(int32(i)) 366 r.SetSiz(uint8(rsize)) 367 r.SetAdd(add) 368 369 return i + int64(rsize) 370 } 371 372 // Add a symbol reference (relocation) with given type, addend, and size 373 // (the most generic form). 374 func (sb *SymbolBuilder) AddSymRef(arch *sys.Arch, tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 { 375 return sb.addSymRef(tgt, add, typ, rsize) 376 } 377 378 func (sb *SymbolBuilder) AddAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 { 379 return sb.addSymRef(tgt, add, objabi.R_ADDR, arch.PtrSize) 380 } 381 382 func (sb *SymbolBuilder) AddAddrPlus4(arch *sys.Arch, tgt Sym, add int64) int64 { 383 return sb.addSymRef(tgt, add, objabi.R_ADDR, 4) 384 } 385 386 func (sb *SymbolBuilder) AddAddr(arch *sys.Arch, tgt Sym) int64 { 387 return sb.AddAddrPlus(arch, tgt, 0) 388 } 389 390 func (sb *SymbolBuilder) AddPCRelPlus(arch *sys.Arch, tgt Sym, add int64) int64 { 391 return sb.addSymRef(tgt, add, objabi.R_PCREL, 4) 392 } 393 394 func (sb *SymbolBuilder) AddCURelativeAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 { 395 return sb.addSymRef(tgt, add, objabi.R_ADDRCUOFF, arch.PtrSize) 396 } 397 398 func (sb *SymbolBuilder) AddSize(arch *sys.Arch, tgt Sym) int64 { 399 return sb.addSymRef(tgt, 0, objabi.R_SIZE, arch.PtrSize) 400 } 401 402 // GenAddAddrPlusFunc returns a function to be called when capturing 403 // a function symbol's address. In later stages of the link (when 404 // address assignment is done) when doing internal linking and 405 // targeting an executable, we can just emit the address of a function 406 // directly instead of generating a relocation. Clients can call 407 // this function (setting 'internalExec' based on build mode and target) 408 // and then invoke the returned function in roughly the same way that 409 // loader.*SymbolBuilder.AddAddrPlus would be used. 410 func GenAddAddrPlusFunc(internalExec bool) func(s *SymbolBuilder, arch *sys.Arch, tgt Sym, add int64) int64 { 411 if internalExec { 412 return func(s *SymbolBuilder, arch *sys.Arch, tgt Sym, add int64) int64 { 413 if v := s.l.SymValue(tgt); v != 0 { 414 return s.AddUint(arch, uint64(v+add)) 415 } 416 return s.AddAddrPlus(arch, tgt, add) 417 } 418 } else { 419 return (*SymbolBuilder).AddAddrPlus 420 } 421 } 422 423 func (sb *SymbolBuilder) MakeWritable() { 424 if sb.ReadOnly() { 425 sb.data = append([]byte(nil), sb.data...) 426 sb.l.SetAttrReadOnly(sb.symIdx, false) 427 } 428 } 429 430 func (sb *SymbolBuilder) AddUleb(v uint64) { 431 if v < 128 { // common case: 1 byte 432 sb.AddUint8(uint8(v)) 433 return 434 } 435 for { 436 c := uint8(v & 0x7f) 437 v >>= 7 438 if v != 0 { 439 c |= 0x80 440 } 441 sb.AddUint8(c) 442 if c&0x80 == 0 { 443 break 444 } 445 } 446 }