diff options
| author | Cherry Mui <cherryyz@google.com> | 2023-06-08 12:19:54 -0400 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2023-07-20 19:39:32 +0000 |
| commit | ac81156bce3ff4bfdcf983cf21acb6830a450a4b (patch) | |
| tree | 2ea28191bd8b8f0311785496800a0efde2384b6f /src/cmd/link/internal/arm64 | |
| parent | 3ffc8a25569ed107ebc1786bbd4f993dd6689601 (diff) | |
| download | go-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.go | 34 |
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 |
