got map[Sym]int32 // stores got for pe objects
dynid map[Sym]int32 // stores Dynid for symbol
+ relocVariant map[relocId]sym.RelocVariant // stores variant relocs
+
// Used to implement field tracking; created during deadcode if
// field tracking is enabled. Reachparent[K] contains the index of
// the symbol that triggered the marking of symbol K as live.
s.R = batch[:len(pp.relocs):len(pp.relocs)]
l.relocBatch = batch[len(pp.relocs):]
relocs := l.Relocs(i)
- l.convertRelocations(&relocs, s, false)
+ l.convertRelocations(i, &relocs, s, false)
// Copy data
s.P = pp.data
if len(s.R) != relocs.Count() {
s.R = make([]sym.Reloc, relocs.Count())
}
- l.convertRelocations(&relocs, s, true)
+ l.convertRelocations(cand, &relocs, s, true)
}
return result
batch := l.relocBatch
s.R = batch[:relocs.Count():relocs.Count()]
l.relocBatch = batch[relocs.Count():]
- l.convertRelocations(&relocs, s, false)
+ l.convertRelocations(gi, &relocs, s, false)
// Aux symbol info
isym := -1
// etc. It is assumed that the caller has pre-allocated the dst symbol
// relocations slice. If 'strict' is set, then this method will
// panic if it finds a relocation targeting a nil symbol.
-func (l *Loader) convertRelocations(src *Relocs, dst *sym.Symbol, strict bool) {
+func (l *Loader) convertRelocations(symIdx Sym, src *Relocs, dst *sym.Symbol, strict bool) {
for j := range dst.R {
r := src.At2(j)
rs := r.Sym()
Add: r.Add(),
Sym: l.Syms[rs],
}
+ if rv := l.RelocVariant(symIdx, j); rv != 0 {
+ dst.R[j].InitExt()
+ dst.R[j].Variant = rv
+ }
+ }
+}
+
+// relocId is essentially a <S,R> tuple identifying the Rth
+// relocation of symbol S.
+type relocId struct {
+ sym Sym
+ ridx int
+}
+
+// SetRelocVariant sets the 'variant' property of a relocation on
+// some specific symbol.
+func (l *Loader) SetRelocVariant(s Sym, ri int, v sym.RelocVariant) {
+ // sanity check
+ if relocs := l.Relocs(s); ri >= relocs.Count() {
+ panic("invalid relocation ID")
+ }
+ if l.relocVariant == nil {
+ l.relocVariant = make(map[relocId]sym.RelocVariant)
+ }
+ if v != 0 {
+ l.relocVariant[relocId{s, ri}] = v
+ } else {
+ delete(l.relocVariant, relocId{s, ri})
+ }
+}
+
+// RelocVariant returns the 'variant' property of a relocation on
+// some specific symbol.
+func (l *Loader) RelocVariant(s Sym, ri int) sym.RelocVariant {
+ if relocs := l.Relocs(s); ri >= relocs.Count() {
+ panic("invalid relocation ID")
}
+ return l.relocVariant[relocId{s, ri}]
}
// UndefinedRelocTargets iterates through the global symbol index
}
}
-func (sb *SymbolBuilder) AddReloc(r Reloc) {
+// AddReloc appends the specified reloc to the symbols list of
+// relocations. Return value is the index of the newly created
+// reloc.
+func (sb *SymbolBuilder) AddReloc(r Reloc) uint32 {
// Populate a goobj2.Reloc from external reloc record.
+ rval := uint32(len(sb.relocs))
var b goobj2.Reloc2
b.Set(r.Off, r.Size, 0, r.Add, goobj2.SymRef{PkgIdx: 0, SymIdx: uint32(r.Sym)})
sb.relocs = append(sb.relocs, b)
sb.reltypes = append(sb.reltypes, r.Type)
+ return rval
}
// Update the j-th relocation in place.