Commit 328adf9d authored by isharipo's avatar isharipo Committed by Brad Fitzpatrick

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: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 4201c207
...@@ -532,8 +532,8 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, secto ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment