diff --git a/crypto/fipsmodule/delocate.go b/crypto/fipsmodule/delocate.go index e28c12aa..0a07f0f0 100644 --- a/crypto/fipsmodule/delocate.go +++ b/crypto/fipsmodule/delocate.go @@ -164,9 +164,12 @@ func transform(lines []string, symbols map[string]bool) (ret []string) { // referenced and thus needs to be emitted outside the module. ia32capAddrNeeded := false - // bssAccessorsNeeded contains the names of BSS symbols for which - // accessor functions need to be emitted outside of the module. - var bssAccessorsNeeded []string + // bssAccessorsNeeded maps the names of BSS variables for which + // accessor functions need to be emitted outside of the module, to the + // BSS symbols they point to. For example, “EVP_sha256_once” could map + // to “.LEVP_sha256_once_local_target” or “EVP_sha256_once” (if .comm + // was used). + bssAccessorsNeeded := make(map[string]string) // threadLocalOffsets records the accessor functions needed for getting // offsets in the thread-local storage. @@ -283,7 +286,7 @@ func transform(lines []string, symbols map[string]bool) (ret []string) { case ".comm": p := strings.Split(parts[1], ",") name := p[0] - bssAccessorsNeeded = append(bssAccessorsNeeded, name) + bssAccessorsNeeded[name] = name ret = append(ret, line) case ".section": @@ -330,6 +333,15 @@ func transform(lines []string, symbols map[string]bool) (ret []string) { case ".debug", ".note": ret = append(ret, line) + case ".bss": + ret = append(ret, line) + + var accessors map[string]string + accessors, ret = handleBSSSection(ret, source) + for accessor, name := range accessors { + bssAccessorsNeeded[accessor] = name + } + default: panic(fmt.Sprintf("unknown section %q on line %d", section, source.lineNo)) } @@ -361,12 +373,18 @@ func transform(lines []string, symbols map[string]bool) (ret []string) { ret = append(ret, "\tjmp "+redirectors[name]+"@PLT") } + var accessorNames []string + for accessor := range bssAccessorsNeeded { + accessorNames = append(accessorNames, accessor) + } + sort.Strings(accessorNames) + // Emit BSS accessor functions. Each is a single LEA followed by RET. - for _, name := range bssAccessorsNeeded { + for _, name := range accessorNames { funcName := accessorName(name) ret = append(ret, ".type "+funcName+", @function") ret = append(ret, funcName+":") - ret = append(ret, "\tleaq "+name+"(%rip), %rax") + ret = append(ret, "\tleaq "+bssAccessorsNeeded[name]+"(%rip), %rax") ret = append(ret, "\tret") } @@ -406,6 +424,45 @@ func transform(lines []string, symbols map[string]bool) (ret []string) { return ret } +// handleBSSSection reads lines from source until the next section and adds a +// local symbol for each BSS symbol found. +func handleBSSSection(lines []string, source *lineSource) (map[string]string, []string) { + accessors := make(map[string]string) + + for { + line, ok := source.Next() + if !ok { + return accessors, lines + } + + parts := strings.Fields(strings.TrimSpace(line)) + if len(parts) == 0 { + lines = append(lines, line) + continue + } + + if strings.HasSuffix(parts[0], ":") { + symbol := parts[0][:len(parts[0])-1] + localSymbol := ".L" + symbol + "_local_target" + + lines = append(lines, line) + lines = append(lines, localSymbol + ":") + + accessors[symbol] = localSymbol + continue + } + + switch parts[0] { + case ".text", ".section": + source.Unread() + return accessors, lines + + default: + lines = append(lines, line) + } + } +} + // accessorName returns the name of the accessor function for a BSS symbol // named name. func accessorName(name string) string {