summaryrefslogtreecommitdiff
path: root/src/util/fipstools/delocate
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/fipstools/delocate')
-rw-r--r--src/util/fipstools/delocate/delocate.go29
-rw-r--r--src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s3
-rw-r--r--src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s15
3 files changed, 45 insertions, 2 deletions
diff --git a/src/util/fipstools/delocate/delocate.go b/src/util/fipstools/delocate/delocate.go
index a43b4286..92b4c31d 100644
--- a/src/util/fipstools/delocate/delocate.go
+++ b/src/util/fipstools/delocate/delocate.go
@@ -803,6 +803,8 @@ const (
instrCombine
// instrThreeArg merges two sources into a destination in some fashion.
instrThreeArg
+ // instrCompare takes two arguments and writes outputs to the flags register.
+ instrCompare
instrOther
)
@@ -833,6 +835,11 @@ func classifyInstruction(instr string, args []*node32) instructionType {
return instrCombine
}
+ case "cmpq":
+ if len(args) == 2 {
+ return instrCompare
+ }
+
case "sarxq", "shlxq", "shrxq":
if len(args) == 3 {
return instrThreeArg
@@ -855,6 +862,13 @@ func push(w stringWriter) wrapperFunc {
}
}
+func compare(w stringWriter, instr, a, b string) wrapperFunc {
+ return func(k func()) {
+ k()
+ w.WriteString(fmt.Sprintf("\t%s %s, %s\n", instr, a, b))
+ }
+}
+
func (d *delocation) loadFromGOT(w stringWriter, destination, symbol, section string, redzoneCleared bool) wrapperFunc {
d.gotExternalsNeeded[symbol+"@"+section] = struct{}{}
@@ -1074,7 +1088,7 @@ Args:
}
classification := classifyInstruction(instructionName, argNodes)
- if classification != instrThreeArg && i != 0 {
+ if classification != instrThreeArg && classification != instrCompare && i != 0 {
return nil, errors.New("GOT access must be source operand")
}
@@ -1091,6 +1105,17 @@ Args:
case instrMove:
assertNodeType(argNodes[1], ruleRegisterOrConstant)
targetReg = d.contents(argNodes[1])
+ case instrCompare:
+ otherSource := d.contents(argNodes[i^1])
+ saveRegWrapper, tempReg := saveRegister(d.output, []string{otherSource})
+ redzoneCleared = true
+ wrappers = append(wrappers, saveRegWrapper)
+ if i == 0 {
+ wrappers = append(wrappers, compare(d.output, instructionName, tempReg, otherSource))
+ } else {
+ wrappers = append(wrappers, compare(d.output, instructionName, otherSource, tempReg))
+ }
+ targetReg = tempReg
case instrTransformingMove:
assertNodeType(argNodes[1], ruleRegisterOrConstant)
targetReg = d.contents(argNodes[1])
@@ -1114,7 +1139,7 @@ Args:
return nil, fmt.Errorf("three-argument instruction has %d arguments", n)
}
if i != 0 && i != 1 {
- return nil, errors.New("GOT access must be from soure operand")
+ return nil, errors.New("GOT access must be from source operand")
}
targetReg = d.contents(argNodes[2])
diff --git a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
index ccbc0bf3..398032f8 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
@@ -44,4 +44,7 @@ foo:
vpbroadcastq stderr@GOTPCREL(%rip), %xmm0
vpbroadcastq foo@GOTPCREL(%rip), %xmm0
+ cmpq foo@GOTPCREL(%rip), %rax
+ cmpq %rax, foo@GOTPCREL(%rip)
+
.comm foobar,64,32
diff --git a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
index 273cfe94..e14a71e6 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
@@ -172,6 +172,21 @@ foo:
leaq 128(%rsp), %rsp
vpbroadcastq %xmm0, %xmm0
+# WAS cmpq foo@GOTPCREL(%rip), %rax
+ leaq -128(%rsp), %rsp
+ pushq %rbx
+ leaq .Lfoo_local_target(%rip), %rbx
+ cmpq %rbx, %rax
+ popq %rbx
+ leaq 128(%rsp), %rsp
+# WAS cmpq %rax, foo@GOTPCREL(%rip)
+ leaq -128(%rsp), %rsp
+ pushq %rbx
+ leaq .Lfoo_local_target(%rip), %rbx
+ cmpq %rax, %rbx
+ popq %rbx
+ leaq 128(%rsp), %rsp
+
.comm foobar,64,32
.text
.loc 1 2 0