mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] cmd/link/internal/loader: support 'variant' relocations
Add support to the loader for getting/setting the 'variant' property of a symbol relocation. The variant property handles unusual or infrequently used relocations that have both a type and a variant of that type (this is needed for S390). In the sym.Symbol world, a relocation variant is a field on the 'relocExt' extension that is part of sym.Reloc. In this new implementation for the loader, reloc variants are stored in a side table (a map) in the loader, and accessed via loader methods. Change-Id: I62bf54ae7ff6d500c0ea8d2dbe759b2431087378 Reviewed-on: https://go-review.googlesource.com/c/go/+/227018 Reviewed-by: Jeremy Faller <jeremy@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
8e457c865d
commit
6636b3f2fc
2 changed files with 49 additions and 5 deletions
|
|
@ -248,6 +248,8 @@ type Loader struct {
|
||||||
got map[Sym]int32 // stores got for pe objects
|
got map[Sym]int32 // stores got for pe objects
|
||||||
dynid map[Sym]int32 // stores Dynid for symbol
|
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
|
// Used to implement field tracking; created during deadcode if
|
||||||
// field tracking is enabled. Reachparent[K] contains the index of
|
// field tracking is enabled. Reachparent[K] contains the index of
|
||||||
// the symbol that triggered the marking of symbol K as live.
|
// the symbol that triggered the marking of symbol K as live.
|
||||||
|
|
@ -1741,7 +1743,7 @@ func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols) {
|
||||||
s.R = batch[:len(pp.relocs):len(pp.relocs)]
|
s.R = batch[:len(pp.relocs):len(pp.relocs)]
|
||||||
l.relocBatch = batch[len(pp.relocs):]
|
l.relocBatch = batch[len(pp.relocs):]
|
||||||
relocs := l.Relocs(i)
|
relocs := l.Relocs(i)
|
||||||
l.convertRelocations(&relocs, s, false)
|
l.convertRelocations(i, &relocs, s, false)
|
||||||
|
|
||||||
// Copy data
|
// Copy data
|
||||||
s.P = pp.data
|
s.P = pp.data
|
||||||
|
|
@ -1941,7 +1943,7 @@ func (l *Loader) PropagateLoaderChangesToSymbols(toconvert []Sym, anonVerReplace
|
||||||
if len(s.R) != relocs.Count() {
|
if len(s.R) != relocs.Count() {
|
||||||
s.R = make([]sym.Reloc, relocs.Count())
|
s.R = make([]sym.Reloc, relocs.Count())
|
||||||
}
|
}
|
||||||
l.convertRelocations(&relocs, s, true)
|
l.convertRelocations(cand, &relocs, s, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
@ -2356,7 +2358,7 @@ func loadObjFull(l *Loader, r *oReader) {
|
||||||
batch := l.relocBatch
|
batch := l.relocBatch
|
||||||
s.R = batch[:relocs.Count():relocs.Count()]
|
s.R = batch[:relocs.Count():relocs.Count()]
|
||||||
l.relocBatch = batch[relocs.Count():]
|
l.relocBatch = batch[relocs.Count():]
|
||||||
l.convertRelocations(&relocs, s, false)
|
l.convertRelocations(gi, &relocs, s, false)
|
||||||
|
|
||||||
// Aux symbol info
|
// Aux symbol info
|
||||||
isym := -1
|
isym := -1
|
||||||
|
|
@ -2525,7 +2527,7 @@ func loadObjFull(l *Loader, r *oReader) {
|
||||||
// etc. It is assumed that the caller has pre-allocated the dst symbol
|
// etc. It is assumed that the caller has pre-allocated the dst symbol
|
||||||
// relocations slice. If 'strict' is set, then this method will
|
// relocations slice. If 'strict' is set, then this method will
|
||||||
// panic if it finds a relocation targeting a nil symbol.
|
// 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 {
|
for j := range dst.R {
|
||||||
r := src.At2(j)
|
r := src.At2(j)
|
||||||
rs := r.Sym()
|
rs := r.Sym()
|
||||||
|
|
@ -2557,9 +2559,46 @@ func (l *Loader) convertRelocations(src *Relocs, dst *sym.Symbol, strict bool) {
|
||||||
Add: r.Add(),
|
Add: r.Add(),
|
||||||
Sym: l.Syms[rs],
|
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
|
// UndefinedRelocTargets iterates through the global symbol index
|
||||||
// space, looking for symbols with relocations targeting undefined
|
// space, looking for symbols with relocations targeting undefined
|
||||||
// references. The linker's loadlib method uses this to determine if
|
// references. The linker's loadlib method uses this to determine if
|
||||||
|
|
|
||||||
|
|
@ -140,12 +140,17 @@ func (sb *SymbolBuilder) SetRelocs(rslice []Reloc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
// Populate a goobj2.Reloc from external reloc record.
|
||||||
|
rval := uint32(len(sb.relocs))
|
||||||
var b goobj2.Reloc2
|
var b goobj2.Reloc2
|
||||||
b.Set(r.Off, r.Size, 0, r.Add, goobj2.SymRef{PkgIdx: 0, SymIdx: uint32(r.Sym)})
|
b.Set(r.Off, r.Size, 0, r.Add, goobj2.SymRef{PkgIdx: 0, SymIdx: uint32(r.Sym)})
|
||||||
sb.relocs = append(sb.relocs, b)
|
sb.relocs = append(sb.relocs, b)
|
||||||
sb.reltypes = append(sb.reltypes, r.Type)
|
sb.reltypes = append(sb.reltypes, r.Type)
|
||||||
|
return rval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the j-th relocation in place.
|
// Update the j-th relocation in place.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue