delocate: remove the need to demangle local variables
We need to demangle because the backing storage for a delocated BSS
symbol is declared static. The compiler seems to be always give it a
C++-mangled name. But we relied on those names to infer the names of the
bss_get functions that the rest of the code wanted.
Instead, if we make the backing storage non-static, we get the name we
want. Ideally we would avoid having to extract those names (see
https://boringssl-review.googlesource.com/c/boringssl/+/70849), but
faking the linker script behavior in delocate seemed tricky, so I opted
to do this and then we can finish up the linker script version later.
While I'm here, prefix the underlying names with 'bcm_' so we're not
squatting as much of the namespace.
Change-Id: I1ce9a189e620c872511dbce09d23e655f1593d34
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/76847
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/delocate.h b/crypto/fipsmodule/delocate.h
index 26d3d41..e104d6e 100644
--- a/crypto/fipsmodule/delocate.h
+++ b/crypto/fipsmodule/delocate.h
@@ -22,11 +22,18 @@
#if !defined(BORINGSSL_SHARED_LIBRARY) && defined(BORINGSSL_FIPS) && \
!defined(OPENSSL_ASAN) && !defined(OPENSSL_MSAN)
-#define DEFINE_BSS_GET(type, name, init_value) \
- static type name __attribute__((used)) = init_value; \
- extern "C" { \
- type *name##_bss_get(void) __attribute__((const)); \
- }
+#define DEFINE_BSS_GET(type, name, init_value) \
+ /* delocate needs C linkage and for |name| to be unique across BCM. */ \
+ extern "C" { \
+ extern type bcm_##name; \
+ type bcm_##name = init_value; \
+ type *bcm_##name##_bss_get(void) __attribute__((const)); \
+ } /* extern "C" */ \
+ \
+ /* The getter functions are exported, but static variables are usually named \
+ * with short names. Define a static wrapper function so the caller can use \
+ * a short name, while the symbol itself is prefixed. */ \
+ static type *name##_bss_get(void) { return bcm_##name##_bss_get(); }
// For FIPS builds we require that CRYPTO_ONCE_INIT be zero.
#define DEFINE_STATIC_ONCE(name) \
DEFINE_BSS_GET(CRYPTO_once_t, name, CRYPTO_ONCE_INIT)
diff --git a/util/fipstools/delocate/delocate.go b/util/fipstools/delocate/delocate.go
index a1a990e..e4b6111 100644
--- a/util/fipstools/delocate/delocate.go
+++ b/util/fipstools/delocate/delocate.go
@@ -195,7 +195,7 @@
if len(args) < 1 {
return nil, errors.New("comm directive has no arguments")
}
- d.bssAccessorsNeeded[demangle(args[0])] = args[0]
+ d.bssAccessorsNeeded[args[0]] = args[0]
d.writeNode(statement)
case "data":
@@ -204,6 +204,10 @@
// will have to work around this in the future.
return nil, errors.New(".data section found in module")
+ case "bss":
+ d.writeNode(statement)
+ return d.handleBSS(statement)
+
case "section":
section := args[0]
@@ -1259,7 +1263,7 @@
localSymbol := localTargetName(symbol)
d.output.WriteString(fmt.Sprintf("\n%s:\n", localSymbol))
- d.bssAccessorsNeeded[demangle(symbol)] = localSymbol
+ d.bssAccessorsNeeded[symbol] = localSymbol
}
case ruleLabelContainingDirective:
@@ -1746,42 +1750,6 @@
return "bcm_redirector_" + symbol
}
-// Optionally demangle C++ local variable names.
-func demangle(symbol string) string {
- if !strings.HasPrefix(symbol, "_Z") {
- return symbol
- }
-
- // The names must have the form "_ZL", followed by the length of the name
- // in base 10, followed by the name.
- if !strings.HasPrefix(symbol, "_ZL") {
- panic("malformed symbol: starts with _Z but not _ZL")
- }
-
- if len(symbol) < 4 {
- panic("malformed symbol: too short")
- }
-
- pos := 3
- for pos < len(symbol) && '0' <= symbol[pos] && symbol[pos] <= '9' {
- pos++
- }
- if pos == 3 {
- panic("malformed symbol: no length digits")
- }
-
- length, err := strconv.Atoi(symbol[3:pos])
- if err != nil {
- panic("malformed symbol: invalid length")
- }
-
- if len(symbol[pos:]) != length {
- panic("malformed symbol: length mismatch")
- }
-
- return symbol[pos:]
-}
-
// sectionType returns the type of a section. I.e. a section called “.text.foo”
// is a “.text” section.
func sectionType(section string) (string, bool) {
diff --git a/util/fipstools/delocate/testdata/x86_64-BSS/in.s b/util/fipstools/delocate/testdata/x86_64-BSS/in.s
index 2d31363..1dceb5b 100644
--- a/util/fipstools/delocate/testdata/x86_64-BSS/in.s
+++ b/util/fipstools/delocate/testdata/x86_64-BSS/in.s
@@ -19,15 +19,26 @@
# .bss handling is terminated by a .text directive.
.text
+not_bss1:
+ ret
+
+ # The .bss directive can introduce BSS.
+ .bss
+test:
+ .quad 0
+ .text
+not_bss2:
+ ret
+
.section .bss,"awT",@nobits
y:
.quad 0
- # Or a .section directive.
+ # A .section directive also terminates BSS.
.section .rodata
.quad 0
- # Or the end of the file.
+ # The end of the file terminates BSS.
.section .bss,"awT",@nobits
z:
.quad 0
diff --git a/util/fipstools/delocate/testdata/x86_64-BSS/out.s b/util/fipstools/delocate/testdata/x86_64-BSS/out.s
index e768027..4a5be91 100644
--- a/util/fipstools/delocate/testdata/x86_64-BSS/out.s
+++ b/util/fipstools/delocate/testdata/x86_64-BSS/out.s
@@ -25,18 +25,33 @@
# .bss handling is terminated by a .text directive.
.text
+.Lnot_bss1_local_target:
+not_bss1:
+ ret
+
+ # The .bss directive can introduce BSS.
+ .bss
+test:
+.Ltest_local_target:
+
+ .quad 0
+ .text
+.Lnot_bss2_local_target:
+not_bss2:
+ ret
+
.section .bss,"awT",@nobits
y:
.Ly_local_target:
.quad 0
- # Or a .section directive.
+ # A .section directive also terminates BSS.
# WAS .section .rodata
.text
.quad 0
- # Or the end of the file.
+ # The end of the file terminates BSS.
.section .bss,"awT",@nobits
z:
.Lz_local_target:
@@ -53,6 +68,10 @@
aes_128_ctr_generic_storage2_bss_get:
leaq aes_128_ctr_generic_storage2(%rip), %rax
ret
+.type test_bss_get, @function
+test_bss_get:
+ leaq .Ltest_local_target(%rip), %rax
+ ret
.type x_bss_get, @function
x_bss_get:
leaq .Lx_local_target(%rip), %rax