cmd/internal/obj/x86: handle global reference in From3 in dynlink mode

In dynlink mode, we rewrite reference to a global variable to
a load from the GOT. Currently this code does not handle the case
that the global reference is in From3 of a Prog. Most instructions
don't expect a memory operand in From3, but some do, like
VGF2P8AFFINEQB. Handle this case.

Change-Id: Ibb6773606e6967bcc629d9ef5dac6e050f4008ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/722181
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
This commit is contained in:
Cherry Mui 2025-11-19 17:32:12 -05:00
parent 790384c6c2
commit 4b740af56a
2 changed files with 25 additions and 5 deletions

View file

@ -169,3 +169,8 @@ TEXT ·a34(SB), 0, $0-0
SHLXQ AX, CX, R15 SHLXQ AX, CX, R15
ADDQ $1, R15 ADDQ $1, R15
RET RET
// Ensure from3 get GOT-rewritten without errors.
TEXT ·a35(SB), 0, $0-0
VGF2P8AFFINEQB $0, runtime·writeBarrier(SB), Z1, Z1
RET

View file

@ -423,9 +423,13 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
q.From.Reg = reg q.From.Reg = reg
} }
} }
if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN { from3 := p.GetFrom3()
for i := range p.RestArgs {
a := &p.RestArgs[i].Addr
if a != from3 && a.Name == obj.NAME_EXTERN && !a.Sym.Local() {
ctxt.Diag("don't know how to handle %v with -dynlink", p) ctxt.Diag("don't know how to handle %v with -dynlink", p)
} }
}
var source *obj.Addr var source *obj.Addr
// MOVx sym, Ry becomes $MOV sym@GOT, R15; MOVx (R15), Ry // MOVx sym, Ry becomes $MOV sym@GOT, R15; MOVx (R15), Ry
// MOVx Ry, sym becomes $MOV sym@GOT, R15; MOVx Ry, (R15) // MOVx Ry, sym becomes $MOV sym@GOT, R15; MOVx Ry, (R15)
@ -434,9 +438,17 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
} }
if from3 != nil && from3.Name == obj.NAME_EXTERN && !from3.Sym.Local() {
ctxt.Diag("cannot handle NAME_EXTERN on multiple operands in %v with -dynlink", p)
}
source = &p.From source = &p.From
} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
if from3 != nil && from3.Name == obj.NAME_EXTERN && !from3.Sym.Local() {
ctxt.Diag("cannot handle NAME_EXTERN on multiple operands in %v with -dynlink", p)
}
source = &p.To source = &p.To
} else if from3 != nil && from3.Name == obj.NAME_EXTERN && !from3.Sym.Local() {
source = from3
} else { } else {
return return
} }
@ -501,9 +513,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
p2.As = p.As p2.As = p.As
p2.From = p.From p2.From = p.From
p2.To = p.To p2.To = p.To
if from3 := p.GetFrom3(); from3 != nil { p2.RestArgs = p.RestArgs
p2.AddRestSource(*from3)
}
if p.From.Name == obj.NAME_EXTERN { if p.From.Name == obj.NAME_EXTERN {
p2.From.Reg = reg p2.From.Reg = reg
p2.From.Name = obj.NAME_NONE p2.From.Name = obj.NAME_NONE
@ -512,6 +522,11 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
p2.To.Reg = reg p2.To.Reg = reg
p2.To.Name = obj.NAME_NONE p2.To.Name = obj.NAME_NONE
p2.To.Sym = nil p2.To.Sym = nil
} else if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
from3 = p2.GetFrom3()
from3.Reg = reg
from3.Name = obj.NAME_NONE
from3.Sym = nil
} else { } else {
return return
} }