mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/link: fewer allocs in ld.Arch.Archreloc
Archreloc had this signature: func(*Link, *sym.Reloc, *sym.Symbol, *int64) bool The last *int64 argument is used as out parameter. Passed valus could be allocated on stack, but escape analysis fails here, leading to high number of unwanted allocs. If instead 4th arg is passed by value, and modified values is returned, no problems with allocations arise: func(*Link, *sym.Reloc, *sym.Symbol, int64) (int64, bool) There are 2 benefits: 1. code becomes more readable. 2. less allocations. For linking "hello world" example from net/http: name old time/op new time/op delta Linker-4 530ms ± 2% 520ms ± 2% -1.83% (p=0.001 n=17+16) It's top 1 in alloc_objects from memprofile: flat flat% sum% cum cum% 229379 33.05% 33.05% 229379 33.05% cmd/link/internal/ld.relocsym ... list relocsym: 229379 229379 (flat, cum) 33.05% of Total 229379 229379 183: var o int64 After the patch, ~230k of int64 allocs (~ 1.75mb) removed. Passes toolshash-check (toolstash cmp). Change-Id: I25504fe27967bcff70c4b7338790f3921d15473d Reviewed-on: https://go-review.googlesource.com/113637 Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
4201c2077e
commit
328adf9d62
10 changed files with 100 additions and 136 deletions
|
|
@ -532,8 +532,8 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, secto
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,7 @@ func gentrampdyn(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
if ctxt.LinkMode == ld.LinkExternal {
|
if ctxt.LinkMode == ld.LinkExternal {
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CALLARM:
|
case objabi.R_CALLARM:
|
||||||
|
|
@ -602,20 +602,17 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
ld.Errorf(s, "direct call too far %d", r.Xadd/4)
|
ld.Errorf(s, "direct call too far %d", r.Xadd/4)
|
||||||
}
|
}
|
||||||
|
|
||||||
*val = int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&uint32(r.Xadd/4))))
|
return int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&uint32(r.Xadd/4)))), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return -1, false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CONST:
|
case objabi.R_CONST:
|
||||||
*val = r.Add
|
return r.Add, true
|
||||||
return true
|
|
||||||
case objabi.R_GOTOFF:
|
case objabi.R_GOTOFF:
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
|
||||||
return true
|
|
||||||
|
|
||||||
// The following three arch specific relocations are only for generation of
|
// The following three arch specific relocations are only for generation of
|
||||||
// Linux/ARM ELF's PLT entry (3 assembler instruction)
|
// Linux/ARM ELF's PLT entry (3 assembler instruction)
|
||||||
|
|
@ -623,16 +620,11 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
if ld.Symaddr(ctxt.Syms.Lookup(".got.plt", 0)) < ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) {
|
if ld.Symaddr(ctxt.Syms.Lookup(".got.plt", 0)) < ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) {
|
||||||
ld.Errorf(s, ".got.plt should be placed after .plt section.")
|
ld.Errorf(s, ".got.plt should be placed after .plt section.")
|
||||||
}
|
}
|
||||||
*val = 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add)) >> 20))
|
return 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add)) >> 20)), true
|
||||||
return true
|
|
||||||
case objabi.R_PLT1: // add ip, ip, #0xYY000
|
case objabi.R_PLT1: // add ip, ip, #0xYY000
|
||||||
*val = 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+4)) >> 12))
|
return 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+4)) >> 12)), true
|
||||||
|
|
||||||
return true
|
|
||||||
case objabi.R_PLT2: // ldr pc, [ip, #0xZZZ]!
|
case objabi.R_PLT2: // ldr pc, [ip, #0xZZZ]!
|
||||||
*val = 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+8)))
|
return 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+8))), true
|
||||||
|
|
||||||
return true
|
|
||||||
case objabi.R_CALLARM: // bl XXXXXX or b YYYYYY
|
case objabi.R_CALLARM: // bl XXXXXX or b YYYYYY
|
||||||
// r.Add is the instruction
|
// r.Add is the instruction
|
||||||
// low 24-bit encodes the target address
|
// low 24-bit encodes the target address
|
||||||
|
|
@ -640,12 +632,10 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
if t > 0x7fffff || t < -0x800000 {
|
if t > 0x7fffff || t < -0x800000 {
|
||||||
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
|
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
|
||||||
}
|
}
|
||||||
*val = int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&t)))
|
return int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&t))), true
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
|
|
@ -234,19 +234,19 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
if ctxt.LinkMode == ld.LinkExternal {
|
if ctxt.LinkMode == ld.LinkExternal {
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
default:
|
default:
|
||||||
return false
|
return val, false
|
||||||
case objabi.R_ARM64_GOTPCREL:
|
case objabi.R_ARM64_GOTPCREL:
|
||||||
var o1, o2 uint32
|
var o1, o2 uint32
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
o1 = uint32(*val >> 32)
|
o1 = uint32(val >> 32)
|
||||||
o2 = uint32(*val)
|
o2 = uint32(val)
|
||||||
} else {
|
} else {
|
||||||
o1 = uint32(*val)
|
o1 = uint32(val)
|
||||||
o2 = uint32(*val >> 32)
|
o2 = uint32(val >> 32)
|
||||||
}
|
}
|
||||||
// Any relocation against a function symbol is redirected to
|
// Any relocation against a function symbol is redirected to
|
||||||
// be against a local symbol instead (see putelfsym in
|
// be against a local symbol instead (see putelfsym in
|
||||||
|
|
@ -264,9 +264,9 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
r.Type = objabi.R_ADDRARM64
|
r.Type = objabi.R_ADDRARM64
|
||||||
}
|
}
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
*val = int64(o1)<<32 | int64(o2)
|
val = int64(o1)<<32 | int64(o2)
|
||||||
} else {
|
} else {
|
||||||
*val = int64(o2)<<32 | int64(o1)
|
val = int64(o2)<<32 | int64(o1)
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case objabi.R_ADDRARM64:
|
case objabi.R_ADDRARM64:
|
||||||
|
|
@ -294,11 +294,11 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
var o0, o1 uint32
|
var o0, o1 uint32
|
||||||
|
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
o0 = uint32(*val >> 32)
|
o0 = uint32(val >> 32)
|
||||||
o1 = uint32(*val)
|
o1 = uint32(val)
|
||||||
} else {
|
} else {
|
||||||
o0 = uint32(*val)
|
o0 = uint32(val)
|
||||||
o1 = uint32(*val >> 32)
|
o1 = uint32(val >> 32)
|
||||||
}
|
}
|
||||||
// Mach-O wants the addend to be encoded in the instruction
|
// Mach-O wants the addend to be encoded in the instruction
|
||||||
// Note that although Mach-O supports ARM64_RELOC_ADDEND, it
|
// Note that although Mach-O supports ARM64_RELOC_ADDEND, it
|
||||||
|
|
@ -311,30 +311,28 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
|
|
||||||
// when laid out, the instruction order must always be o1, o2.
|
// when laid out, the instruction order must always be o1, o2.
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
*val = int64(o0)<<32 | int64(o1)
|
val = int64(o0)<<32 | int64(o1)
|
||||||
} else {
|
} else {
|
||||||
*val = int64(o1)<<32 | int64(o0)
|
val = int64(o1)<<32 | int64(o0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return val, true
|
||||||
case objabi.R_CALLARM64,
|
case objabi.R_CALLARM64,
|
||||||
objabi.R_ARM64_TLS_LE,
|
objabi.R_ARM64_TLS_LE,
|
||||||
objabi.R_ARM64_TLS_IE:
|
objabi.R_ARM64_TLS_IE:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
return true
|
return val, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CONST:
|
case objabi.R_CONST:
|
||||||
*val = r.Add
|
return r.Add, true
|
||||||
return true
|
|
||||||
case objabi.R_GOTOFF:
|
case objabi.R_GOTOFF:
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
|
||||||
return true
|
|
||||||
case objabi.R_ADDRARM64:
|
case objabi.R_ADDRARM64:
|
||||||
t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
|
t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
|
||||||
if t >= 1<<32 || t < -1<<32 {
|
if t >= 1<<32 || t < -1<<32 {
|
||||||
|
|
@ -344,11 +342,11 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
var o0, o1 uint32
|
var o0, o1 uint32
|
||||||
|
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
o0 = uint32(*val >> 32)
|
o0 = uint32(val >> 32)
|
||||||
o1 = uint32(*val)
|
o1 = uint32(val)
|
||||||
} else {
|
} else {
|
||||||
o0 = uint32(*val)
|
o0 = uint32(val)
|
||||||
o1 = uint32(*val >> 32)
|
o1 = uint32(val >> 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
|
o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
|
||||||
|
|
@ -356,11 +354,9 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
|
|
||||||
// when laid out, the instruction order must always be o1, o2.
|
// when laid out, the instruction order must always be o1, o2.
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
*val = int64(o0)<<32 | int64(o1)
|
return int64(o0)<<32 | int64(o1), true
|
||||||
} else {
|
|
||||||
*val = int64(o1)<<32 | int64(o0)
|
|
||||||
}
|
}
|
||||||
return true
|
return int64(o1)<<32 | int64(o0), true
|
||||||
case objabi.R_ARM64_TLS_LE:
|
case objabi.R_ARM64_TLS_LE:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
if ctxt.HeadType != objabi.Hlinux {
|
if ctxt.HeadType != objabi.Hlinux {
|
||||||
|
|
@ -372,18 +368,16 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
if v < 0 || v >= 32678 {
|
if v < 0 || v >= 32678 {
|
||||||
ld.Errorf(s, "TLS offset out of range %d", v)
|
ld.Errorf(s, "TLS offset out of range %d", v)
|
||||||
}
|
}
|
||||||
*val |= v << 5
|
return val | (v << 5), true
|
||||||
return true
|
|
||||||
case objabi.R_CALLARM64:
|
case objabi.R_CALLARM64:
|
||||||
t := (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
|
t := (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
|
||||||
if t >= 1<<27 || t < -1<<27 {
|
if t >= 1<<27 || t < -1<<27 {
|
||||||
ld.Errorf(s, "program too large, call relocation distance = %d", t)
|
ld.Errorf(s, "program too large, call relocation distance = %d", t)
|
||||||
}
|
}
|
||||||
*val |= (t >> 2) & 0x03ffffff
|
return val | ((t >> 2) & 0x03ffffff), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,9 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
case 8:
|
case 8:
|
||||||
o = int64(ctxt.Arch.ByteOrder.Uint64(s.P[off:]))
|
o = int64(ctxt.Arch.ByteOrder.Uint64(s.P[off:]))
|
||||||
}
|
}
|
||||||
if !thearch.Archreloc(ctxt, r, s, &o) {
|
if offset, ok := thearch.Archreloc(ctxt, r, s, o); ok {
|
||||||
|
o = offset
|
||||||
|
} else {
|
||||||
Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(ctxt.Arch, r.Type))
|
Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(ctxt.Arch, r.Type))
|
||||||
}
|
}
|
||||||
case objabi.R_TLS_LE:
|
case objabi.R_TLS_LE:
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ type Arch struct {
|
||||||
Solarisdynld string
|
Solarisdynld string
|
||||||
Adddynrel func(*Link, *sym.Symbol, *sym.Reloc) bool
|
Adddynrel func(*Link, *sym.Symbol, *sym.Reloc) bool
|
||||||
Archinit func(*Link)
|
Archinit func(*Link)
|
||||||
Archreloc func(*Link, *sym.Reloc, *sym.Symbol, *int64) bool
|
Archreloc func(*Link, *sym.Reloc, *sym.Symbol, int64) (int64, bool)
|
||||||
Archrelocvariant func(*Link, *sym.Reloc, *sym.Symbol, int64) int64
|
Archrelocvariant func(*Link, *sym.Reloc, *sym.Symbol, int64) int64
|
||||||
Trampoline func(*Link, *sym.Reloc, *sym.Symbol)
|
Trampoline func(*Link, *sym.Reloc, *sym.Symbol)
|
||||||
Asmb func(*Link)
|
Asmb func(*Link)
|
||||||
|
|
|
||||||
|
|
@ -82,23 +82,25 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyrel(arch *sys.Arch, r *sym.Reloc, s *sym.Symbol, val *int64, t int64) {
|
func applyrel(arch *sys.Arch, r *sym.Reloc, s *sym.Symbol, val int64, t int64) int64 {
|
||||||
o := arch.ByteOrder.Uint32(s.P[r.Off:])
|
o := arch.ByteOrder.Uint32(s.P[r.Off:])
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS:
|
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS:
|
||||||
*val = int64(o&0xffff0000 | uint32(t)&0xffff)
|
return int64(o&0xffff0000 | uint32(t)&0xffff)
|
||||||
case objabi.R_ADDRMIPSU:
|
case objabi.R_ADDRMIPSU:
|
||||||
*val = int64(o&0xffff0000 | uint32((t+(1<<15))>>16)&0xffff)
|
return int64(o&0xffff0000 | uint32((t+(1<<15))>>16)&0xffff)
|
||||||
case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
|
case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
|
||||||
*val = int64(o&0xfc000000 | uint32(t>>2)&^0xfc000000)
|
return int64(o&0xfc000000 | uint32(t>>2)&^0xfc000000)
|
||||||
|
default:
|
||||||
|
return val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
if ctxt.LinkMode == ld.LinkExternal {
|
if ctxt.LinkMode == ld.LinkExternal {
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
default:
|
default:
|
||||||
return false
|
return val, false
|
||||||
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
|
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
|
|
||||||
|
|
@ -114,28 +116,23 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
ld.Errorf(s, "missing section for %s", rs.Name)
|
ld.Errorf(s, "missing section for %s", rs.Name)
|
||||||
}
|
}
|
||||||
r.Xsym = rs
|
r.Xsym = rs
|
||||||
applyrel(ctxt.Arch, r, s, val, r.Xadd)
|
return applyrel(ctxt.Arch, r, s, val, r.Xadd), true
|
||||||
return true
|
|
||||||
case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
|
case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
applyrel(ctxt.Arch, r, s, val, r.Add)
|
return applyrel(ctxt.Arch, r, s, val, r.Add), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CONST:
|
case objabi.R_CONST:
|
||||||
*val = r.Add
|
return r.Add, true
|
||||||
return true
|
|
||||||
case objabi.R_GOTOFF:
|
case objabi.R_GOTOFF:
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
|
||||||
return true
|
|
||||||
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
|
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
|
||||||
t := ld.Symaddr(r.Sym) + r.Add
|
t := ld.Symaddr(r.Sym) + r.Add
|
||||||
applyrel(ctxt.Arch, r, s, val, t)
|
return applyrel(ctxt.Arch, r, s, val, t), true
|
||||||
return true
|
|
||||||
case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
|
case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
|
||||||
t := ld.Symaddr(r.Sym) + r.Add
|
t := ld.Symaddr(r.Sym) + r.Add
|
||||||
|
|
||||||
|
|
@ -148,19 +145,17 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
|
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
applyrel(ctxt.Arch, r, s, val, t)
|
return applyrel(ctxt.Arch, r, s, val, t), true
|
||||||
return true
|
|
||||||
case objabi.R_ADDRMIPSTLS:
|
case objabi.R_ADDRMIPSTLS:
|
||||||
// thread pointer is at 0x7000 offset from the start of TLS data area
|
// thread pointer is at 0x7000 offset from the start of TLS data area
|
||||||
t := ld.Symaddr(r.Sym) + r.Add - 0x7000
|
t := ld.Symaddr(r.Sym) + r.Add - 0x7000
|
||||||
if t < -32768 || t >= 32678 {
|
if t < -32768 || t >= 32678 {
|
||||||
ld.Errorf(s, "TLS offset out of range %d", t)
|
ld.Errorf(s, "TLS offset out of range %d", t)
|
||||||
}
|
}
|
||||||
applyrel(ctxt.Arch, r, s, val, t)
|
return applyrel(ctxt.Arch, r, s, val, t), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
|
|
@ -99,11 +99,11 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
if ctxt.LinkMode == ld.LinkExternal {
|
if ctxt.LinkMode == ld.LinkExternal {
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
default:
|
default:
|
||||||
return false
|
return val, false
|
||||||
case objabi.R_ADDRMIPS,
|
case objabi.R_ADDRMIPS,
|
||||||
objabi.R_ADDRMIPSU:
|
objabi.R_ADDRMIPSU:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
|
|
@ -121,34 +121,30 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
}
|
}
|
||||||
r.Xsym = rs
|
r.Xsym = rs
|
||||||
|
|
||||||
return true
|
return val, true
|
||||||
case objabi.R_ADDRMIPSTLS,
|
case objabi.R_ADDRMIPSTLS,
|
||||||
objabi.R_CALLMIPS,
|
objabi.R_CALLMIPS,
|
||||||
objabi.R_JMPMIPS:
|
objabi.R_JMPMIPS:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
return true
|
return val, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CONST:
|
case objabi.R_CONST:
|
||||||
*val = r.Add
|
return r.Add, true
|
||||||
return true
|
|
||||||
case objabi.R_GOTOFF:
|
case objabi.R_GOTOFF:
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
|
||||||
return true
|
|
||||||
case objabi.R_ADDRMIPS,
|
case objabi.R_ADDRMIPS,
|
||||||
objabi.R_ADDRMIPSU:
|
objabi.R_ADDRMIPSU:
|
||||||
t := ld.Symaddr(r.Sym) + r.Add
|
t := ld.Symaddr(r.Sym) + r.Add
|
||||||
o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
|
o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
|
||||||
if r.Type == objabi.R_ADDRMIPS {
|
if r.Type == objabi.R_ADDRMIPS {
|
||||||
*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
|
return int64(o1&0xffff0000 | uint32(t)&0xffff), true
|
||||||
} else {
|
|
||||||
*val = int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff)
|
|
||||||
}
|
}
|
||||||
return true
|
return int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff), true
|
||||||
case objabi.R_ADDRMIPSTLS:
|
case objabi.R_ADDRMIPSTLS:
|
||||||
// thread pointer is at 0x7000 offset from the start of TLS data area
|
// thread pointer is at 0x7000 offset from the start of TLS data area
|
||||||
t := ld.Symaddr(r.Sym) + r.Add - 0x7000
|
t := ld.Symaddr(r.Sym) + r.Add - 0x7000
|
||||||
|
|
@ -156,18 +152,16 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
ld.Errorf(s, "TLS offset out of range %d", t)
|
ld.Errorf(s, "TLS offset out of range %d", t)
|
||||||
}
|
}
|
||||||
o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
|
o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
|
||||||
*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
|
return int64(o1&0xffff0000 | uint32(t)&0xffff), true
|
||||||
return true
|
|
||||||
case objabi.R_CALLMIPS,
|
case objabi.R_CALLMIPS,
|
||||||
objabi.R_JMPMIPS:
|
objabi.R_JMPMIPS:
|
||||||
// Low 26 bits = (S + A) >> 2
|
// Low 26 bits = (S + A) >> 2
|
||||||
t := ld.Symaddr(r.Sym) + r.Add
|
t := ld.Symaddr(r.Sym) + r.Add
|
||||||
o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
|
o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
|
||||||
*val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
|
return int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
|
|
@ -474,14 +474,14 @@ func symtoc(ctxt *ld.Link, s *sym.Symbol) int64 {
|
||||||
return toc.Value
|
return toc.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocaddr(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archrelocaddr(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
|
||||||
var o1, o2 uint32
|
var o1, o2 uint32
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
o1 = uint32(*val >> 32)
|
o1 = uint32(val >> 32)
|
||||||
o2 = uint32(*val)
|
o2 = uint32(val)
|
||||||
} else {
|
} else {
|
||||||
o1 = uint32(*val)
|
o1 = uint32(val)
|
||||||
o2 = uint32(*val >> 32)
|
o2 = uint32(val >> 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are spreading a 31-bit address across two instructions, putting the
|
// We are spreading a 31-bit address across two instructions, putting the
|
||||||
|
|
@ -510,15 +510,13 @@ func archrelocaddr(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool
|
||||||
}
|
}
|
||||||
o2 |= uint32(t) & 0xfffc
|
o2 |= uint32(t) & 0xfffc
|
||||||
default:
|
default:
|
||||||
return false
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||||
*val = int64(o1)<<32 | int64(o2)
|
return int64(o1)<<32 | int64(o2)
|
||||||
} else {
|
|
||||||
*val = int64(o2)<<32 | int64(o1)
|
|
||||||
}
|
}
|
||||||
return true
|
return int64(o2)<<32 | int64(o1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve direct jump relocation r in s, and add trampoline if necessary
|
// resolve direct jump relocation r in s, and add trampoline if necessary
|
||||||
|
|
@ -623,17 +621,17 @@ func gentramp(arch *sys.Arch, linkmode ld.LinkMode, tramp, target *sym.Symbol, o
|
||||||
arch.ByteOrder.PutUint32(tramp.P[12:], o4)
|
arch.ByteOrder.PutUint32(tramp.P[12:], o4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
if ctxt.LinkMode == ld.LinkExternal {
|
if ctxt.LinkMode == ld.LinkExternal {
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
default:
|
default:
|
||||||
return false
|
return val, false
|
||||||
case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
|
case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
// check Outer is nil, Type is TLSBSS?
|
// check Outer is nil, Type is TLSBSS?
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
return true
|
return val, true
|
||||||
case objabi.R_ADDRPOWER,
|
case objabi.R_ADDRPOWER,
|
||||||
objabi.R_ADDRPOWER_DS,
|
objabi.R_ADDRPOWER_DS,
|
||||||
objabi.R_ADDRPOWER_TOCREL,
|
objabi.R_ADDRPOWER_TOCREL,
|
||||||
|
|
@ -655,24 +653,22 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
}
|
}
|
||||||
r.Xsym = rs
|
r.Xsym = rs
|
||||||
|
|
||||||
return true
|
return val, true
|
||||||
case objabi.R_CALLPOWER:
|
case objabi.R_CALLPOWER:
|
||||||
r.Done = false
|
r.Done = false
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
return true
|
return val, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CONST:
|
case objabi.R_CONST:
|
||||||
*val = r.Add
|
return r.Add, true
|
||||||
return true
|
|
||||||
case objabi.R_GOTOFF:
|
case objabi.R_GOTOFF:
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
|
||||||
return true
|
|
||||||
case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
|
case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
|
||||||
return archrelocaddr(ctxt, r, s, val)
|
return archrelocaddr(ctxt, r, s, val), true
|
||||||
case objabi.R_CALLPOWER:
|
case objabi.R_CALLPOWER:
|
||||||
// Bits 6 through 29 = (S + A - P) >> 2
|
// Bits 6 through 29 = (S + A - P) >> 2
|
||||||
|
|
||||||
|
|
@ -686,12 +682,10 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
if int64(int32(t<<6)>>6) != t {
|
if int64(int32(t<<6)>>6) != t {
|
||||||
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
|
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
|
||||||
}
|
}
|
||||||
*val |= int64(uint32(t) &^ 0xfc000003)
|
return val | int64(uint32(t)&^0xfc000003), true
|
||||||
return true
|
|
||||||
case objabi.R_POWER_TOC: // S + A - .TOC.
|
case objabi.R_POWER_TOC: // S + A - .TOC.
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s)
|
return ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s), true
|
||||||
|
|
||||||
return true
|
|
||||||
case objabi.R_POWER_TLS_LE:
|
case objabi.R_POWER_TLS_LE:
|
||||||
// The thread pointer points 0x7000 bytes after the start of the
|
// The thread pointer points 0x7000 bytes after the start of the
|
||||||
// thread local storage area as documented in section "3.7.2 TLS
|
// thread local storage area as documented in section "3.7.2 TLS
|
||||||
|
|
@ -701,11 +695,10 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
||||||
if int64(int16(v)) != v {
|
if int64(int16(v)) != v {
|
||||||
ld.Errorf(s, "TLS offset out of range %d", v)
|
ld.Errorf(s, "TLS offset out of range %d", v)
|
||||||
}
|
}
|
||||||
*val = (*val &^ 0xffff) | (v & 0xffff)
|
return (val &^ 0xffff) | (v & 0xffff), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
|
|
@ -384,21 +384,19 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
if ctxt.LinkMode == ld.LinkExternal {
|
if ctxt.LinkMode == ld.LinkExternal {
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CONST:
|
case objabi.R_CONST:
|
||||||
*val = r.Add
|
return r.Add, true
|
||||||
return true
|
|
||||||
case objabi.R_GOTOFF:
|
case objabi.R_GOTOFF:
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
|
|
@ -491,20 +491,18 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, secto
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
||||||
if ctxt.LinkMode == ld.LinkExternal {
|
if ctxt.LinkMode == ld.LinkExternal {
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_CONST:
|
case objabi.R_CONST:
|
||||||
*val = r.Add
|
return r.Add, true
|
||||||
return true
|
|
||||||
case objabi.R_GOTOFF:
|
case objabi.R_GOTOFF:
|
||||||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return val, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue