Handle GOTTPOFF relocations in delocate.go

These relocations can be emitted for thread-local data. BoringSSL itself
doesn't include any thread-local variables that need linker support, but
ASAN and MSAN may inject these references in order to handle their own
bookkeeping.

Change-Id: I0c6e61d244be84d6bee5ccbf7c4ff4ea0f0b90fd
Reviewed-on: https://boringssl-review.googlesource.com/15147
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
Adam Langley 2017-04-17 12:54:00 -07:00
parent e5be1740be
commit e2a701ea1e

View File

@ -125,6 +125,13 @@ func referencesIA32CapDirectly(line string) bool {
return i == len(line) || line[i] == '+' || line[i] == '(' return i == len(line) || line[i] == '+' || line[i] == '('
} }
// threadLocalOffsetFunc describes a function that fetches the offset to symbol
// in the thread-local space and writes it to the given target register.
type threadLocalOffsetFunc struct {
target string
symbol string
}
// transform performs a number of transformations on the given assembly code. // transform performs a number of transformations on the given assembly code.
// See FIPS.md in the current directory for an overview. // See FIPS.md in the current directory for an overview.
func transform(lines []string, symbols map[string]bool) (ret []string) { func transform(lines []string, symbols map[string]bool) (ret []string) {
@ -148,6 +155,10 @@ func transform(lines []string, symbols map[string]bool) (ret []string) {
// accessor functions need to be emitted outside of the module. // accessor functions need to be emitted outside of the module.
var bssAccessorsNeeded []string var bssAccessorsNeeded []string
// threadLocalOffsets records the accessor functions needed for getting
// offsets in the thread-local storage.
threadLocalOffsets := make(map[string]threadLocalOffsetFunc)
for lineNo, line := range lines { for lineNo, line := range lines {
if referencesIA32CapDirectly(line) { if referencesIA32CapDirectly(line) {
panic("reference to OPENSSL_ia32cap_P needs to be changed to indirect via OPENSSL_ia32cap_addr") panic("reference to OPENSSL_ia32cap_P needs to be changed to indirect via OPENSSL_ia32cap_addr")
@ -218,6 +229,30 @@ func transform(lines []string, symbols map[string]bool) (ret []string) {
ret = append(ret, line) ret = append(ret, line)
continue continue
case "movq":
if !strings.Contains(line, "@GOTTPOFF(%rip)") {
ret = append(ret, line)
continue
}
// GOTTPOFF are offsets into the thread-local storage
// that are stored in the GOT. We have to move these
// relocations out of the module, but do not know
// whether rax is live at this point. Thus a normal
// function call might clobber a register and so we
// synthesize different functions for writing to each
// target register.
//
// (BoringSSL itself does not use __thread variables,
// but ASAN and MSAN may add these references for their
// bookkeeping.)
targetRegister := parts[2][1:]
symbol := strings.SplitN(parts[1], "@", 2)[0]
functionName := fmt.Sprintf("BORINGSSL_bcm_tpoff_to_%s_for_%s", targetRegister, symbol)
threadLocalOffsets[functionName] = threadLocalOffsetFunc{target: targetRegister, symbol: symbol}
ret = append(ret, "\tcallq "+functionName+"\n")
continue
case ".file": case ".file":
// Do not reorder .file directives. These define // Do not reorder .file directives. These define
// numbered files which are referenced by other debug // numbered files which are referenced by other debug
@ -320,6 +355,22 @@ func transform(lines []string, symbols map[string]bool) (ret []string) {
ret = append(ret, "\t.quad OPENSSL_ia32cap_P") ret = append(ret, "\t.quad OPENSSL_ia32cap_P")
} }
// Emit accessors for thread-local offsets.
var threadAccessorNames []string
for name := range threadLocalOffsets {
threadAccessorNames = append(threadAccessorNames, name)
}
sort.Strings(threadAccessorNames)
for _, name := range threadAccessorNames {
f := threadLocalOffsets[name]
ret = append(ret, ".type "+name+",@function")
ret = append(ret, name+":")
ret = append(ret, "\tmovq "+f.symbol+"@GOTTPOFF(%rip), %"+f.target)
ret = append(ret, "\tret")
}
// Emit an array for storing the module hash. // Emit an array for storing the module hash.
ret = append(ret, ".type BORINGSSL_bcm_text_hash,@object") ret = append(ret, ".type BORINGSSL_bcm_text_hash,@object")
ret = append(ret, ".size OPENSSL_ia32cap_addr,32") ret = append(ret, ".size OPENSSL_ia32cap_addr,32")