Handle pushing a pointer from the GOT.

When code wants to push a pointer from the GOT onto the stack, we don't
have any registers to play with. We do, however, know that the stack is
viable and thankfully Intel has an “xchg” instruction that avoids the
need for an intermediate register.

Change-Id: Iba7e4f0f4c9b43b3d994cf6cfc92837b312c7728
Reviewed-on: https://boringssl-review.googlesource.com/15625
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/fipsmodule/delocate.go b/crypto/fipsmodule/delocate.go
index 7b5454c..fd11a21 100644
--- a/crypto/fipsmodule/delocate.go
+++ b/crypto/fipsmodule/delocate.go
@@ -290,6 +290,23 @@
 			redirectors[redirectorName] = target
 			continue
 
+		case "pushq":
+			target := args[0]
+			if strings.HasSuffix(target, "@GOTPCREL(%rip)") {
+				target = target[:len(target)-15]
+				if !symbols[target] {
+					panic(fmt.Sprintf("Reference to unknown symbol on line %d: %s", source.lineNo, line))
+				}
+
+				ret = append(ret, "\tpushq %rax")
+				ret = append(ret, "\tleaq "+localTargetName(target)+"(%rip), %rax")
+				ret = append(ret, "\txchg %rax, (%rsp)")
+				continue
+			}
+
+			ret = append(ret, line)
+			continue
+
 		case "leaq", "movq", "cmpq":
 			if instr == "movq" && strings.Contains(line, "@GOTTPOFF(%rip)") {
 				// GOTTPOFF are offsets into the thread-local