aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal/arm64
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2023-06-08 12:19:54 -0400
committerCherry Mui <cherryyz@google.com>2023-07-20 19:39:32 +0000
commitac81156bce3ff4bfdcf983cf21acb6830a450a4b (patch)
tree2ea28191bd8b8f0311785496800a0efde2384b6f /src/cmd/link/internal/arm64
parent3ffc8a25569ed107ebc1786bbd4f993dd6689601 (diff)
downloadgo-ac81156bce3ff4bfdcf983cf21acb6830a450a4b.tar.xz
cmd/link: handle dynamic import variables on Darwin
Currently, on darwin, we only support cgo_dynamic_import for functions, but not variables, as we don't need it before. mach_task_self_ is a variable defined in the system library, which can be used to e.g. access the process's memory mappings via the mach API. The C header defines a macro mach_task_self(), which refers to the variable. To use mach_task_self_ (in pure-Go programs) we need to access it in Go. This CL handles cgo_dynamic_import for variables in the linker, loading its address via the GOT. (Currently only on Darwin, as we only need it there.) For #50891. Change-Id: Idf64fa88ba2f2381443a1ed0b42b14b581843493 Reviewed-on: https://go-review.googlesource.com/c/go/+/501855 Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/link/internal/arm64')
-rw-r--r--src/cmd/link/internal/arm64/asm.go34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go
index 312ee27aa6..e3fc1c4dd4 100644
--- a/src/cmd/link/internal/arm64/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -306,6 +306,40 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
return true
+ case objabi.R_ADDRARM64:
+ if targType == sym.SDYNIMPORT && ldr.SymType(s) == sym.STEXT && target.IsDarwin() {
+ // Loading the address of a dynamic symbol. Rewrite to use GOT.
+ // turn MOVD $sym (adrp+add) into MOVD sym@GOT (adrp+ldr)
+ if r.Add() != 0 {
+ ldr.Errorf(s, "unexpected nonzero addend for dynamic symbol %s", ldr.SymName(targ))
+ return false
+ }
+ su := ldr.MakeSymbolUpdater(s)
+ data := ldr.Data(s)
+ off := r.Off()
+ if int(off+8) > len(data) {
+ ldr.Errorf(s, "unexpected R_ADDRARM64 reloc for dynamic symbol %s", ldr.SymName(targ))
+ return false
+ }
+ o := target.Arch.ByteOrder.Uint32(data[off+4:])
+ if o>>24 == 0x91 { // add
+ // rewrite to ldr
+ o = (0xf9 << 24) | 1<<22 | (o & (1<<22 - 1))
+ su.MakeWritable()
+ su.SetUint32(target.Arch, int64(off+4), o)
+ if target.IsInternal() {
+ ld.AddGotSym(target, ldr, syms, targ, 0)
+ su.SetRelocSym(rIdx, syms.GOT)
+ su.SetRelocAdd(rIdx, int64(ldr.SymGot(targ)))
+ su.SetRelocType(rIdx, objabi.R_ARM64_PCREL_LDST64)
+ } else {
+ su.SetRelocType(rIdx, objabi.R_ARM64_GOTPCREL)
+ }
+ return true
+ }
+ ldr.Errorf(s, "unexpected R_ADDRARM64 reloc for dynamic symbol %s", ldr.SymName(targ))
+ }
+
case objabi.R_ADDR:
if ldr.SymType(s) == sym.STEXT && target.IsElf() {
// The code is asking for the address of an external