]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/6g: call duffcopy, duffzero via got when dynamically linking go
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Mon, 30 Mar 2015 01:54:49 +0000 (01:54 +0000)
committerIan Lance Taylor <iant@golang.org>
Sat, 11 Apr 2015 00:52:39 +0000 (00:52 +0000)
Jumping to an offset past a symbol isn't something that is really
supported by dynamic linkers, so do it by hand.

Change-Id: Ifff8834c6cdfa3d521ebd8479d2e93906df9b258
Reviewed-on: https://go-review.googlesource.com/8238
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>

src/cmd/internal/obj/x86/asm6.go
src/cmd/internal/obj/x86/obj6.go

index dfabfd4124ae79d928ee32040d404f57660bf07a..04f829a7d7617857ee21423c192edb26eff93724 100644 (file)
@@ -3450,6 +3450,10 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
                                        log.Fatalf("bad code")
                                }
 
+                               if yt.zcase == Zcallduff && ctxt.Flag_dynlink {
+                                       ctxt.Diag("directly calling duff when dynamically linking Go")
+                               }
+
                                if obj.Framepointer_enabled != 0 && yt.zcase == Zcallduff && p.Mode == 64 {
                                        // Maintain BP around call, since duffcopy/duffzero can't do it
                                        // (the call jumps into the middle of the function).
index 2d30e9ebd4ed7e0dd1ca8477a6d1b163df6f06af..31475733e36941c82c1c14291c1351ed1958cf0b 100644 (file)
@@ -298,6 +298,34 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
                }
        }
 
+       if ctxt.Flag_dynlink && (p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO) {
+               var sym *obj.LSym
+               if p.As == obj.ADUFFZERO {
+                       sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
+               } else {
+                       sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
+               }
+               offset := p.To.Offset
+               p.As = AMOVQ
+               p.From.Type = obj.TYPE_MEM
+               p.From.Name = obj.NAME_GOTREF
+               p.From.Sym = sym
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = REG_R15
+               p.To.Offset = 0
+               p.To.Sym = nil
+               p1 := obj.Appendp(ctxt, p)
+               p1.As = AADDQ
+               p1.From.Type = obj.TYPE_CONST
+               p1.From.Offset = offset
+               p1.To.Type = obj.TYPE_REG
+               p1.To.Reg = REG_R15
+               p2 := obj.Appendp(ctxt, p1)
+               p2.As = obj.ACALL
+               p2.To.Type = obj.TYPE_REG
+               p2.To.Reg = REG_R15
+       }
+
        if ctxt.Flag_dynlink {
                if p.As == ALEAQ && p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_EXTERN {
                        p.As = AMOVQ