From cd334a54caf16474a379b5045c912c117ee745bb Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Wed, 31 May 2017 17:02:42 -0700 Subject: [PATCH] Handle TOC offsets by giving them to the linker. An offset > 2^15 would exceed the range of an addi immediate on ppc64le. Thus, rather than add the offset after loading the TOC reference, have different tocloader functions for each (symbol, offset) pair. In this case, the linker can handle large offsets by changing the value of foo+offset@toc@ha accordingly. Change-Id: Iac1481bccaf55fb0c2b080eedebaf11befdae465 Reviewed-on: https://boringssl-review.googlesource.com/16784 Commit-Queue: David Benjamin Reviewed-by: David Benjamin CQ-Verified: CQ bot account: commit-bot@chromium.org --- util/fipstools/delocate.go | 56 +++++++++++-------- .../testdata/ppc64le-TOCWithOffset/in.s | 3 + .../testdata/ppc64le-TOCWithOffset/out.s | 42 ++++++++++++-- 3 files changed, 71 insertions(+), 30 deletions(-) diff --git a/util/fipstools/delocate.go b/util/fipstools/delocate.go index eb5ca5a5..93fb4bb0 100644 --- a/util/fipstools/delocate.go +++ b/util/fipstools/delocate.go @@ -479,13 +479,27 @@ func establishTOC(w stringWriter) { } // loadTOCFuncName returns the name of a synthesized function that sets r3 to -// the value of “symbol”. -func loadTOCFuncName(symbol string) string { - return ".Lbcm_loadtoc_" + strings.Replace(symbol, ".", "_dot_", -1) +// the value of “symbol+offset”. +func loadTOCFuncName(symbol, offset string) string { + ret := ".Lbcm_loadtoc_" + strings.Replace(symbol, ".", "_dot_", -1) + switch { + case len(offset) == 0: + break + case offset[0] == '+': + ret += "__plus_" + offset[1:] + case offset[0] == '-': + ret += "__minus_" + offset[1:] + default: + // parseMemRef will prepend a plus to bare offsets. + panic("bad offset: " + offset) + } + + return ret } -func (d *delocation) loadFromTOC(w stringWriter, symbol, dest string) wrapperFunc { - d.tocLoaders[symbol] = struct{}{} +func (d *delocation) loadFromTOC(w stringWriter, symbol, offset, dest string) wrapperFunc { + d.tocLoaders[symbol + "\x00" + offset] = struct{}{} + return func(k func()) { w.WriteString("\taddi 1, 1, -288\n") // Clear the red zone. w.WriteString("\tmflr " + dest + "\n") // Stash the link register. @@ -497,7 +511,7 @@ func (d *delocation) loadFromTOC(w stringWriter, symbol, dest string) wrapperFun // Because loadTOCFuncName returns a “.L” name, we don't need a // nop after this call. - w.WriteString("\tbl " + loadTOCFuncName(symbol) + "\n") + w.WriteString("\tbl " + loadTOCFuncName(symbol, offset) + "\n") // Cycle registers around. We need r3 -> destReg, -8(1) -> // lr and, optionally, -16(1) -> r3. @@ -672,26 +686,20 @@ Args: // destination register is the first argument. destReg := args[0] - wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, destReg)) + wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, offset, destReg)) switch instructionName { case "addi": // The original instruction was: // addi destReg, tocHaReg, offset+symbol@toc@l - // - // All that is left is adding the offset, if any. instructionName = "" - if len(offset) != 0 { - wrappers = append(wrappers, func(k func()) { - d.output.WriteString("\taddi " + destReg + ", " + destReg + ", " + offset + "\n") - }) - } + case "ld", "lhz", "lwz": // The original instruction was: // l?? destReg, offset+symbol@toc@l(tocHaReg) // // We transform that into the // equivalent dereference of destReg: - // l?? destReg, offset(destReg) + // l?? destReg, 0(destReg) origInstructionName := instructionName instructionName = "" @@ -702,11 +710,7 @@ Args: } wrappers = append(wrappers, func(k func()) { - fixedOffset := offset - if len(fixedOffset) == 0 { - fixedOffset = "0" - } - d.output.WriteString("\t" + origInstructionName + " " + destReg + ", " + fixedOffset + "(" + destReg + ")\n") + d.output.WriteString("\t" + origInstructionName + " " + destReg + ", 0(" + destReg + ")\n") }) default: return nil, fmt.Errorf("can't process TOC argument to %q", instructionName) @@ -1212,14 +1216,18 @@ func transform(w stringWriter, inputs []inputFile) error { if d.processor == ppc64le { loadTOCNames := sortedSet(d.tocLoaders) - for _, symbol := range loadTOCNames { - funcName := loadTOCFuncName(symbol) + for _, symbolAndOffset := range loadTOCNames { + parts := strings.SplitN(symbolAndOffset, "\x00", 2) + symbol, offset := parts[0], parts[1] + + funcName := loadTOCFuncName(symbol, offset) + ref := symbol + offset w.WriteString(".type " + funcName[2:] + ", @function\n") w.WriteString(funcName[2:] + ":\n") w.WriteString(funcName + ":\n") - w.WriteString("\taddis 3, 2, " + symbol + "@toc@ha\n") - w.WriteString("\taddi 3, 3, " + symbol + "@toc@l\n") + w.WriteString("\taddis 3, 2, " + ref + "@toc@ha\n") + w.WriteString("\taddi 3, 3, " + ref + "@toc@l\n") w.WriteString("\tblr\n") } diff --git a/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s b/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s index abd3006b..af1347e3 100644 --- a/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s +++ b/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s @@ -12,3 +12,6 @@ foo: addis 5, 2, 5+foo@toc@ha ld 5, 10+foo@toc@l(5) + + addis 4, 2, foo-10@toc@ha + addi 4, 4, foo-10@toc@l diff --git a/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s b/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s index 633a0891..070c97d1 100644 --- a/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s +++ b/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s @@ -9,26 +9,24 @@ foo: addi 1, 1, -288 mflr 3 std 3, -8(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10 std 3, -24(1) ld 3, -8(1) mtlr 3 ld 3, -24(1) addi 1, 1, 288 - addi 3, 3, +10 # WAS addis 3, 2, 15+foo@toc@ha # WAS addi 3, 3, 20+foo@toc@l addi 1, 1, -288 mflr 3 std 3, -8(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_20 std 3, -24(1) ld 3, -8(1) mtlr 3 ld 3, -24(1) addi 1, 1, 288 - addi 3, 3, +20 # WAS addis 4, 2, foo@toc@ha # WAS addi 4, 4, foo@toc@l @@ -50,14 +48,28 @@ foo: mflr 5 std 5, -8(1) std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10 std 3, -24(1) ld 3, -8(1) mtlr 3 ld 5, -24(1) ld 3, -16(1) addi 1, 1, 288 - ld 5, +10(5) + ld 5, 0(5) + +# WAS addis 4, 2, foo-10@toc@ha +# WAS addi 4, 4, foo-10@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target__minus_10 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 .text BORINGSSL_bcm_text_end: .type bcm_loadtoc__dot_Lfoo_local_target, @function @@ -66,6 +78,24 @@ bcm_loadtoc__dot_Lfoo_local_target: addis 3, 2, .Lfoo_local_target@toc@ha addi 3, 3, .Lfoo_local_target@toc@l blr +.type bcm_loadtoc__dot_Lfoo_local_target__plus_10, @function +bcm_loadtoc__dot_Lfoo_local_target__plus_10: +.Lbcm_loadtoc__dot_Lfoo_local_target__plus_10: + addis 3, 2, .Lfoo_local_target+10@toc@ha + addi 3, 3, .Lfoo_local_target+10@toc@l + blr +.type bcm_loadtoc__dot_Lfoo_local_target__plus_20, @function +bcm_loadtoc__dot_Lfoo_local_target__plus_20: +.Lbcm_loadtoc__dot_Lfoo_local_target__plus_20: + addis 3, 2, .Lfoo_local_target+20@toc@ha + addi 3, 3, .Lfoo_local_target+20@toc@l + blr +.type bcm_loadtoc__dot_Lfoo_local_target__minus_10, @function +bcm_loadtoc__dot_Lfoo_local_target__minus_10: +.Lbcm_loadtoc__dot_Lfoo_local_target__minus_10: + addis 3, 2, .Lfoo_local_target-10@toc@ha + addi 3, 3, .Lfoo_local_target-10@toc@l + blr .LBORINGSSL_external_toc: .quad .TOC.-.LBORINGSSL_external_toc .type BORINGSSL_bcm_text_hash, @object