From 1b4d28f8cf48f6d8cf346adc1d3cbd0ede338558 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 2 Sep 2015 22:25:57 +1200 Subject: [PATCH] cmd/link, runtime: arm implementation of addmoduledata Change-Id: I3975e10c2445e23c2798a7203a877ff2de3427c7 Reviewed-on: https://go-review.googlesource.com/14189 Reviewed-by: Ian Lance Taylor --- src/cmd/link/internal/arm/asm.go | 75 ++++++++++++++++++++++++++++++++ src/runtime/asm_arm.s | 11 +++++ 2 files changed, 86 insertions(+) diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index 5507312a1b..8ffa656208 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -37,7 +37,75 @@ import ( "log" ) +// This assembler: +// +// .align 2 +// local.dso_init: +// ldr r0, .Lmoduledata +// .Lloadfrom: +// ldr r0, [r0] +// b runtime.addmoduledata@plt +// .align 2 +// .Lmoduledata: +// .word local.moduledata(GOT_PREL) + (. - (.Lloadfrom + 4)) +// assembles to: +// +// 00000000 : +// 0: e59f0004 ldr r0, [pc, #4] ; c +// 4: e5900000 ldr r0, [r0] +// 8: eafffffe b 0 +// 8: R_ARM_JUMP24 runtime.addmoduledata +// c: 00000004 .word 0x00000004 +// c: R_ARM_GOT_PREL local.moduledata + func gentext() { + if !ld.DynlinkingGo() { + return + } + addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0) + if addmoduledata.Type == obj.STEXT { + // we're linking a module containing the runtime -> no need for + // an init function + return + } + addmoduledata.Reachable = true + initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0) + initfunc.Type = obj.STEXT + initfunc.Local = true + initfunc.Reachable = true + o := func(op uint32) { + ld.Adduint32(ld.Ctxt, initfunc, op) + } + o(0xe59f0004) + o(0xe08f0000) + + o(0xeafffffe) + rel := ld.Addrel(initfunc) + rel.Off = 8 + rel.Siz = 4 + rel.Sym = ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0) + rel.Type = obj.R_CALLARM + rel.Add = 0xeafffffe // vomit + + o(0x00000000) + rel = ld.Addrel(initfunc) + rel.Off = 12 + rel.Siz = 4 + rel.Sym = ld.Ctxt.Moduledata + rel.Type = obj.R_PCREL + rel.Add = 4 + + if ld.Ctxt.Etextp != nil { + ld.Ctxt.Etextp.Next = initfunc + } else { + ld.Ctxt.Textp = initfunc + } + ld.Ctxt.Etextp = initfunc + initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0) + initarray_entry.Reachable = true + initarray_entry.Local = true + initarray_entry.Type = obj.SINITARR + ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) } // Preserve highest 8 bits of a, and do addition to lower 24-bit @@ -228,6 +296,13 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int { case obj.R_TLS_IE: ld.Thearch.Lput(ld.R_ARM_TLS_IE32 | uint32(elfsym)<<8) + + case obj.R_GOTPCREL: + if r.Siz == 4 { + ld.Thearch.Lput(ld.R_ARM_GOT_PREL | uint32(elfsym)<<8) + } else { + return -1 + } } return 0 diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index 8472090d8b..62f2a276e7 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -1076,3 +1076,14 @@ TEXT runtime·usplitR0(SB),NOSPLIT,$0 TEXT runtime·sigreturn(SB),NOSPLIT,$0-4 RET + +#ifndef GOOS_nacl +// This is called from .init_array and follows the platform, not Go, ABI. +TEXT runtime·addmoduledata(SB),NOSPLIT,$0-4 + MOVW R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save + MOVW runtime·lastmoduledatap(SB), R1 + MOVW R0, moduledata_next(R1) + MOVW R0, runtime·lastmoduledatap(SB) + MOVW saver9-4(SP), R9 + RET +#endif -- 2.48.1