diff options
Diffstat (limited to 'src/util/fipstools/delocate')
-rw-r--r-- | src/util/fipstools/delocate/delocate.go | 29 | ||||
-rw-r--r-- | src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s | 3 | ||||
-rw-r--r-- | src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s | 15 |
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 |