mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/obj/arm64, cmd/internal/ld, cmd/7l: remove absolute addressing in .text
This CL introduces R_ADDRARM64, which is similar to R_ADDRPOWER. Fixes #10112. Change-Id: I309e3df7608b9eef9339196fdc50dedf5f9439f1 Reviewed-on: https://go-review.googlesource.com/8438 Reviewed-by: Aram Hăvărneanu <aram@mgk.ro> Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
f55b2a11f4
commit
6e3a2a3f9f
6 changed files with 392 additions and 313 deletions
|
|
@ -33,6 +33,7 @@ package main
|
|||
import (
|
||||
"cmd/internal/ld"
|
||||
"cmd/internal/obj"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
|
@ -83,6 +84,13 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
case ld.R_ADDRARM64:
|
||||
// two relocations: R_AARCH64_ADR_PREL_PG_HI21 and R_AARCH64_ADD_ABS_LO12_NC
|
||||
ld.Thearch.Vput(ld.R_AARCH64_ADR_PREL_PG_HI21 | uint64(elfsym)<<32)
|
||||
ld.Thearch.Vput(uint64(r.Xadd))
|
||||
ld.Thearch.Vput(uint64(sectoff + 4))
|
||||
ld.Thearch.Vput(ld.R_AARCH64_ADD_ABS_LO12_NC | uint64(elfsym)<<32)
|
||||
|
||||
case ld.R_CALLARM64:
|
||||
if r.Siz != 4 {
|
||||
return -1
|
||||
|
|
@ -110,6 +118,36 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
|
|||
default:
|
||||
return -1
|
||||
|
||||
case ld.R_ADDRARM64:
|
||||
r.Done = 0
|
||||
|
||||
// the first instruction is always at the lower address, this is endian neutral;
|
||||
// but note that o0 and o1 should still use the target endian.
|
||||
o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
|
||||
o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
|
||||
|
||||
// when laid out, the instruction order must always be o1, o2.
|
||||
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||
*val = int64(o0)<<32 | int64(o1)
|
||||
} else {
|
||||
*val = int64(o1)<<32 | int64(o0)
|
||||
}
|
||||
|
||||
// set up addend for eventual relocation via outer symbol.
|
||||
rs := r.Sym
|
||||
r.Xadd = r.Add
|
||||
for rs.Outer != nil {
|
||||
r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
|
||||
rs = rs.Outer
|
||||
}
|
||||
|
||||
if rs.Type != ld.SHOSTOBJ && rs.Sect == nil {
|
||||
ld.Diag("missing section for %s", rs.Name)
|
||||
}
|
||||
r.Xsym = rs
|
||||
|
||||
return 0
|
||||
|
||||
case ld.R_CALLARM64:
|
||||
r.Done = 0
|
||||
r.Xsym = r.Sym
|
||||
|
|
@ -129,6 +167,28 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
|
|||
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
|
||||
return 0
|
||||
|
||||
case ld.R_ADDRARM64:
|
||||
t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
|
||||
if t >= 1<<32 || t < -1<<32 {
|
||||
ld.Diag("program too large, address relocation distance = %d", t)
|
||||
}
|
||||
|
||||
// the first instruction is always at the lower address, this is endian neutral;
|
||||
// but note that o0 and o1 should still use the target endian.
|
||||
o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
|
||||
o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
|
||||
|
||||
o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
|
||||
o1 |= uint32(t&0xfff) << 10
|
||||
|
||||
// when laid out, the instruction order must always be o1, o2.
|
||||
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
|
||||
*val = int64(o0)<<32 | int64(o1)
|
||||
} else {
|
||||
*val = int64(o1)<<32 | int64(o0)
|
||||
}
|
||||
return 0
|
||||
|
||||
case ld.R_CALLARM64:
|
||||
*val = int64((0xfc000000 & uint32(r.Add)) | uint32((ld.Symaddr(r.Sym)+r.Add*4-(s.Value+int64(r.Off)))/4))
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -119,8 +119,7 @@ func archinit() {
|
|||
ld.INITRND = 4096
|
||||
}
|
||||
|
||||
case ld.Hlinux: /* ppc64 elf */
|
||||
ld.Debug['d'] = 1 // TODO(aram): dynamic linking is not supported yet.
|
||||
case ld.Hlinux: /* arm64 elf */
|
||||
ld.Elfinit()
|
||||
ld.HEADR = ld.ELFRESERVE
|
||||
if ld.INITTEXT == -1 {
|
||||
|
|
|
|||
|
|
@ -348,6 +348,8 @@ const (
|
|||
R_AARCH64_ABS64 = 257
|
||||
R_AARCH64_ABS32 = 258
|
||||
R_AARCH64_CALL26 = 283
|
||||
R_AARCH64_ADR_PREL_PG_HI21 = 275
|
||||
R_AARCH64_ADD_ABS_LO12_NC = 277
|
||||
R_ALPHA_NONE = 0
|
||||
R_ALPHA_REFLONG = 1
|
||||
R_ALPHA_REFQUAD = 2
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ const (
|
|||
const (
|
||||
R_ADDR = 1 + iota
|
||||
R_ADDRPOWER
|
||||
R_ADDRARM64
|
||||
R_SIZE
|
||||
R_CALL
|
||||
R_CALLARM
|
||||
|
|
|
|||
|
|
@ -258,17 +258,19 @@ var optab = []Optab{
|
|||
{AWORD, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
|
||||
{AWORD, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
|
||||
{AMOVW, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
|
||||
{AMOVW, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0},
|
||||
{AMOVD, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
|
||||
{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO, 0},
|
||||
{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO, 0},
|
||||
{AMOVH, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO, 0},
|
||||
{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO, 0},
|
||||
{AMOVD, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO, 0},
|
||||
{AMOVB, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM, 0},
|
||||
{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM, 0},
|
||||
{AMOVH, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM, 0},
|
||||
{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM, 0},
|
||||
{AMOVD, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM, 0},
|
||||
{AMOVD, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0},
|
||||
{AMOVB, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
|
||||
{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
|
||||
{AMOVH, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
|
||||
{AMOVW, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
|
||||
{AMOVD, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
|
||||
{AMOVB, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
|
||||
{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
|
||||
{AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
|
||||
{AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
|
||||
{AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
|
||||
{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
|
||||
{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
|
||||
{AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
|
||||
|
|
@ -447,10 +449,10 @@ var optab = []Optab{
|
|||
{AFMOVS, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
|
||||
{AFMOVD, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
|
||||
{AFMOVD, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
|
||||
{AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 8, 0, LTO, 0},
|
||||
{AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 8, 0, LFROM, 0},
|
||||
{AFMOVD, C_FREG, C_NONE, C_ADDR, 64, 8, 0, LTO, 0},
|
||||
{AFMOVD, C_ADDR, C_NONE, C_FREG, 65, 8, 0, LFROM, 0},
|
||||
{AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
|
||||
{AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0},
|
||||
{AFMOVD, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
|
||||
{AFMOVD, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0},
|
||||
{AFADDS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
|
||||
{AFADDS, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0},
|
||||
{AFADDS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0},
|
||||
|
|
@ -1176,12 +1178,7 @@ func cmp(a int, b int) bool {
|
|||
}
|
||||
|
||||
case C_VCON:
|
||||
if b == C_VCONADDR {
|
||||
return true
|
||||
} else {
|
||||
return cmp(C_LCON, b)
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case C_LACON:
|
||||
if b == C_AACON {
|
||||
|
|
@ -2724,21 +2721,27 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
|
|||
}
|
||||
|
||||
/* reloc ops */
|
||||
case 64: /* movT R,addr */
|
||||
o1 = omovlit(ctxt, AMOVD, p, &p.To, REGTMP)
|
||||
case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
|
||||
o1 = ADR(1, 0, REGTMP)
|
||||
o2 = opirr(ctxt, AADD) | REGTMP&31<<5 | REGTMP&31
|
||||
rel := obj.Addrel(ctxt.Cursym)
|
||||
rel.Off = int32(ctxt.Pc)
|
||||
rel.Siz = 8
|
||||
rel.Sym = p.To.Sym
|
||||
rel.Add = p.To.Offset
|
||||
rel.Type = obj.R_ADDRARM64
|
||||
o3 = olsr12u(ctxt, int32(opstr12(ctxt, int(p.As))), 0, REGTMP, int(p.From.Reg))
|
||||
|
||||
if !(o1 != 0) {
|
||||
break
|
||||
}
|
||||
o2 = olsr12u(ctxt, int32(opstr12(ctxt, int(p.As))), 0, REGTMP, int(p.From.Reg))
|
||||
|
||||
case 65: /* movT addr,R */
|
||||
o1 = omovlit(ctxt, AMOVD, p, &p.From, REGTMP)
|
||||
|
||||
if !(o1 != 0) {
|
||||
break
|
||||
}
|
||||
o2 = olsr12u(ctxt, int32(opldr12(ctxt, int(p.As))), 0, REGTMP, int(p.To.Reg))
|
||||
case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
|
||||
o1 = ADR(1, 0, REGTMP)
|
||||
o2 = opirr(ctxt, AADD) | REGTMP&31<<5 | REGTMP&31
|
||||
rel := obj.Addrel(ctxt.Cursym)
|
||||
rel.Off = int32(ctxt.Pc)
|
||||
rel.Siz = 8
|
||||
rel.Sym = p.From.Sym
|
||||
rel.Add = p.From.Offset
|
||||
rel.Type = obj.R_ADDRARM64
|
||||
o3 = olsr12u(ctxt, int32(opldr12(ctxt, int(p.As))), 0, REGTMP, int(p.To.Reg))
|
||||
|
||||
case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
|
||||
v := int32(p.From.Offset)
|
||||
|
|
@ -2767,6 +2770,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
|
|||
}
|
||||
o1 |= uint32(int64(2<<30|5<<27|((uint32(v)/8)&0x7f)<<15) | p.From.Offset<<10 | int64(uint32(p.To.Reg&31)<<5) | int64(p.From.Reg&31))
|
||||
|
||||
case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
|
||||
if p.As == AMOVW {
|
||||
ctxt.Diag("invalid load of 32-bit address: %v", p)
|
||||
}
|
||||
o1 = ADR(1, 0, uint32(p.To.Reg))
|
||||
o2 = opirr(ctxt, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
|
||||
rel := obj.Addrel(ctxt.Cursym)
|
||||
rel.Off = int32(ctxt.Pc)
|
||||
rel.Siz = 8
|
||||
rel.Sym = p.From.Sym
|
||||
rel.Add = p.From.Offset
|
||||
rel.Type = obj.R_ADDRARM64
|
||||
|
||||
// This is supposed to be something that stops execution.
|
||||
// It's not supposed to be reached, ever, but if it is, we'd
|
||||
// like to be able to tell how we got there. Assemble as
|
||||
|
|
|
|||
|
|
@ -362,6 +362,7 @@ type Reloc struct {
|
|||
const (
|
||||
R_ADDR = 1 + iota
|
||||
R_ADDRPOWER
|
||||
R_ADDRARM64
|
||||
R_SIZE
|
||||
R_CALL
|
||||
R_CALLARM
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue