Commit 09d7de8d authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/link, runtime: call addmoduledata when dynamically linking on linux/386

Change-Id: If1faa2bba28a4e9a8061693173797c4114a7d699
Reviewed-on: https://go-review.googlesource.com/16387Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 34cbccd3
...@@ -37,6 +37,19 @@ import ( ...@@ -37,6 +37,19 @@ import (
"log" "log"
) )
// Append 4 bytes to s and create a R_CALL relocation targeting t to fill them in.
func addcall(ctxt *ld.Link, s *ld.LSym, t *ld.LSym) {
s.Reachable = true
i := s.Size
s.Size += 4
ld.Symgrow(ctxt, s, s.Size)
r := ld.Addrel(s)
r.Sym = t
r.Off = int32(i)
r.Type = obj.R_CALL
r.Siz = 4
}
func gentext() { func gentext() {
if !ld.DynlinkingGo() && ld.Buildmode != ld.BuildmodePIE { if !ld.DynlinkingGo() && ld.Buildmode != ld.BuildmodePIE {
return return
...@@ -62,6 +75,68 @@ func gentext() { ...@@ -62,6 +75,68 @@ func gentext() {
ld.Ctxt.Textp = thunkfunc ld.Ctxt.Textp = thunkfunc
} }
ld.Ctxt.Etextp = thunkfunc ld.Ctxt.Etextp = thunkfunc
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 ...uint8) {
for _, op1 := range op {
ld.Adduint8(ld.Ctxt, initfunc, op1)
}
}
// go.link.addmoduledata:
// 53 push %ebx
// e8 00 00 00 00 call __x86.get_pc_thunk.cx + R_CALL __x86.get_pc_thunk.cx
// 8d 81 00 00 00 00 lea 0x0(%ecx), %eax + R_PCREL ld.Ctxt.Moduledata
// 8d 99 00 00 00 00 lea 0x0(%ecx), %ebx + R_GOTPC _GLOBAL_OFFSET_TABLE_
// e8 00 00 00 00 call runtime.addmoduledata@plt + R_CALL runtime.addmoduledata
// 5b pop %ebx
// c3 ret
o(0x53)
o(0xe8)
addcall(ld.Ctxt, initfunc, ld.Linklookup(ld.Ctxt, "__x86.get_pc_thunk.cx", 0))
o(0x8d, 0x81)
ld.Addpcrelplus(ld.Ctxt, initfunc, ld.Ctxt.Moduledata, 6)
o(0x8d, 0x99)
i := initfunc.Size
initfunc.Size += 4
ld.Symgrow(ld.Ctxt, initfunc, initfunc.Size)
r := ld.Addrel(initfunc)
r.Sym = ld.Linklookup(ld.Ctxt, "_GLOBAL_OFFSET_TABLE_", 0)
r.Off = int32(i)
r.Type = obj.R_PCREL
r.Add = 12
r.Siz = 4
o(0xe8)
addcall(ld.Ctxt, initfunc, addmoduledata)
o(0x5b)
o(0xc3)
ld.Ctxt.Etextp.Next = 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)
} }
func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) { func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) {
......
...@@ -1546,3 +1546,14 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4 ...@@ -1546,3 +1546,14 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
RET RET
// Add a module's moduledata to the linked list of moduledata objects. This
// is called from .init_array by a function generated in the linker and so
// follows the platform ABI wrt register preservation -- it only touches AX,
// CX (implicitly) and DX, but it does not follow the ABI wrt arguments:
// instead the pointer to the moduledata is passed in AX.
TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
MOVL runtime·lastmoduledatap(SB), DX
MOVL AX, moduledata_next(DX)
MOVL AX, runtime·lastmoduledatap(SB)
RET
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