external/boringssl: Sync to 0f5ecd3a854546d943104e1f7421e489b7f4d5aa.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/9113e0996fd445ce187ae9dfeabfc95805b947a2..0f5ecd3a854546d943104e1f7421e489b7f4d5aa

Test: atest CtsLibcoreTestCases
Change-Id: I819426d5e00485d972f3c17335f7c3ed7ac4e6ff
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index 6826a81..d6108a3 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-9113e0996fd445ce187ae9dfeabfc95805b947a2
+0f5ecd3a854546d943104e1f7421e489b7f4d5aa
diff --git a/linux-x86/crypto/chacha/chacha-x86.S b/linux-x86/crypto/chacha/chacha-x86.S
index 1c9fdc3..287b62a 100644
--- a/linux-x86/crypto/chacha/chacha-x86.S
+++ b/linux-x86/crypto/chacha/chacha-x86.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	ChaCha20_ctr32
 .hidden	ChaCha20_ctr32
diff --git a/linux-x86/crypto/fipsmodule/aes-586.S b/linux-x86/crypto/fipsmodule/aes-586.S
index 3d6fbf7..c8eeee5 100644
--- a/linux-x86/crypto/fipsmodule/aes-586.S
+++ b/linux-x86/crypto/fipsmodule/aes-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .hidden	_x86_AES_encrypt_compact
 .type	_x86_AES_encrypt_compact,@function
diff --git a/linux-x86/crypto/fipsmodule/aesni-x86.S b/linux-x86/crypto/fipsmodule/aesni-x86.S
index 2e8e98a..b193966 100644
--- a/linux-x86/crypto/fipsmodule/aesni-x86.S
+++ b/linux-x86/crypto/fipsmodule/aesni-x86.S
@@ -2,13 +2,16 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
-.globl	aesni_encrypt
-.hidden	aesni_encrypt
-.type	aesni_encrypt,@function
+.globl	aes_hw_encrypt
+.hidden	aes_hw_encrypt
+.type	aes_hw_encrypt,@function
 .align	16
-aesni_encrypt:
-.L_aesni_encrypt_begin:
+aes_hw_encrypt:
+.L_aes_hw_encrypt_begin:
 	movl	4(%esp),%eax
 	movl	12(%esp),%edx
 	movups	(%eax),%xmm2
@@ -30,13 +33,13 @@
 	movups	%xmm2,(%eax)
 	pxor	%xmm2,%xmm2
 	ret
-.size	aesni_encrypt,.-.L_aesni_encrypt_begin
-.globl	aesni_decrypt
-.hidden	aesni_decrypt
-.type	aesni_decrypt,@function
+.size	aes_hw_encrypt,.-.L_aes_hw_encrypt_begin
+.globl	aes_hw_decrypt
+.hidden	aes_hw_decrypt
+.type	aes_hw_decrypt,@function
 .align	16
-aesni_decrypt:
-.L_aesni_decrypt_begin:
+aes_hw_decrypt:
+.L_aes_hw_decrypt_begin:
 	movl	4(%esp),%eax
 	movl	12(%esp),%edx
 	movups	(%eax),%xmm2
@@ -58,7 +61,7 @@
 	movups	%xmm2,(%eax)
 	pxor	%xmm2,%xmm2
 	ret
-.size	aesni_decrypt,.-.L_aesni_decrypt_begin
+.size	aes_hw_decrypt,.-.L_aes_hw_decrypt_begin
 .hidden	_aesni_encrypt2
 .type	_aesni_encrypt2,@function
 .align	16
@@ -369,12 +372,12 @@
 .byte	102,15,56,223,248
 	ret
 .size	_aesni_decrypt6,.-_aesni_decrypt6
-.globl	aesni_ecb_encrypt
-.hidden	aesni_ecb_encrypt
-.type	aesni_ecb_encrypt,@function
+.globl	aes_hw_ecb_encrypt
+.hidden	aes_hw_ecb_encrypt
+.type	aes_hw_ecb_encrypt,@function
 .align	16
-aesni_ecb_encrypt:
-.L_aesni_ecb_encrypt_begin:
+aes_hw_ecb_encrypt:
+.L_aes_hw_ecb_encrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -604,13 +607,13 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.size	aesni_ecb_encrypt,.-.L_aesni_ecb_encrypt_begin
-.globl	aesni_ccm64_encrypt_blocks
-.hidden	aesni_ccm64_encrypt_blocks
-.type	aesni_ccm64_encrypt_blocks,@function
+.size	aes_hw_ecb_encrypt,.-.L_aes_hw_ecb_encrypt_begin
+.globl	aes_hw_ccm64_encrypt_blocks
+.hidden	aes_hw_ccm64_encrypt_blocks
+.type	aes_hw_ccm64_encrypt_blocks,@function
 .align	16
-aesni_ccm64_encrypt_blocks:
-.L_aesni_ccm64_encrypt_blocks_begin:
+aes_hw_ccm64_encrypt_blocks:
+.L_aes_hw_ccm64_encrypt_blocks_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -693,13 +696,13 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.size	aesni_ccm64_encrypt_blocks,.-.L_aesni_ccm64_encrypt_blocks_begin
-.globl	aesni_ccm64_decrypt_blocks
-.hidden	aesni_ccm64_decrypt_blocks
-.type	aesni_ccm64_decrypt_blocks,@function
+.size	aes_hw_ccm64_encrypt_blocks,.-.L_aes_hw_ccm64_encrypt_blocks_begin
+.globl	aes_hw_ccm64_decrypt_blocks
+.hidden	aes_hw_ccm64_decrypt_blocks
+.type	aes_hw_ccm64_decrypt_blocks,@function
 .align	16
-aesni_ccm64_decrypt_blocks:
-.L_aesni_ccm64_decrypt_blocks_begin:
+aes_hw_ccm64_decrypt_blocks:
+.L_aes_hw_ccm64_decrypt_blocks_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -817,13 +820,13 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.size	aesni_ccm64_decrypt_blocks,.-.L_aesni_ccm64_decrypt_blocks_begin
-.globl	aesni_ctr32_encrypt_blocks
-.hidden	aesni_ctr32_encrypt_blocks
-.type	aesni_ctr32_encrypt_blocks,@function
+.size	aes_hw_ccm64_decrypt_blocks,.-.L_aes_hw_ccm64_decrypt_blocks_begin
+.globl	aes_hw_ctr32_encrypt_blocks
+.hidden	aes_hw_ctr32_encrypt_blocks
+.type	aes_hw_ctr32_encrypt_blocks,@function
 .align	16
-aesni_ctr32_encrypt_blocks:
-.L_aesni_ctr32_encrypt_blocks_begin:
+aes_hw_ctr32_encrypt_blocks:
+.L_aes_hw_ctr32_encrypt_blocks_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -1056,13 +1059,13 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.size	aesni_ctr32_encrypt_blocks,.-.L_aesni_ctr32_encrypt_blocks_begin
-.globl	aesni_xts_encrypt
-.hidden	aesni_xts_encrypt
-.type	aesni_xts_encrypt,@function
+.size	aes_hw_ctr32_encrypt_blocks,.-.L_aes_hw_ctr32_encrypt_blocks_begin
+.globl	aes_hw_xts_encrypt
+.hidden	aes_hw_xts_encrypt
+.type	aes_hw_xts_encrypt,@function
 .align	16
-aesni_xts_encrypt:
-.L_aesni_xts_encrypt_begin:
+aes_hw_xts_encrypt:
+.L_aes_hw_xts_encrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -1417,13 +1420,13 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.size	aesni_xts_encrypt,.-.L_aesni_xts_encrypt_begin
-.globl	aesni_xts_decrypt
-.hidden	aesni_xts_decrypt
-.type	aesni_xts_decrypt,@function
+.size	aes_hw_xts_encrypt,.-.L_aes_hw_xts_encrypt_begin
+.globl	aes_hw_xts_decrypt
+.hidden	aes_hw_xts_decrypt
+.type	aes_hw_xts_decrypt,@function
 .align	16
-aesni_xts_decrypt:
-.L_aesni_xts_decrypt_begin:
+aes_hw_xts_decrypt:
+.L_aes_hw_xts_decrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -1808,13 +1811,13 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.size	aesni_xts_decrypt,.-.L_aesni_xts_decrypt_begin
-.globl	aesni_cbc_encrypt
-.hidden	aesni_cbc_encrypt
-.type	aesni_cbc_encrypt,@function
+.size	aes_hw_xts_decrypt,.-.L_aes_hw_xts_decrypt_begin
+.globl	aes_hw_cbc_encrypt
+.hidden	aes_hw_cbc_encrypt
+.type	aes_hw_cbc_encrypt,@function
 .align	16
-aesni_cbc_encrypt:
-.L_aesni_cbc_encrypt_begin:
+aes_hw_cbc_encrypt:
+.L_aes_hw_cbc_encrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -2070,7 +2073,7 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.size	aesni_cbc_encrypt,.-.L_aesni_cbc_encrypt_begin
+.size	aes_hw_cbc_encrypt,.-.L_aes_hw_cbc_encrypt_begin
 .hidden	_aesni_set_encrypt_key
 .type	_aesni_set_encrypt_key,@function
 .align	16
@@ -2405,24 +2408,24 @@
 	popl	%ebp
 	ret
 .size	_aesni_set_encrypt_key,.-_aesni_set_encrypt_key
-.globl	aesni_set_encrypt_key
-.hidden	aesni_set_encrypt_key
-.type	aesni_set_encrypt_key,@function
+.globl	aes_hw_set_encrypt_key
+.hidden	aes_hw_set_encrypt_key
+.type	aes_hw_set_encrypt_key,@function
 .align	16
-aesni_set_encrypt_key:
-.L_aesni_set_encrypt_key_begin:
+aes_hw_set_encrypt_key:
+.L_aes_hw_set_encrypt_key_begin:
 	movl	4(%esp),%eax
 	movl	8(%esp),%ecx
 	movl	12(%esp),%edx
 	call	_aesni_set_encrypt_key
 	ret
-.size	aesni_set_encrypt_key,.-.L_aesni_set_encrypt_key_begin
-.globl	aesni_set_decrypt_key
-.hidden	aesni_set_decrypt_key
-.type	aesni_set_decrypt_key,@function
+.size	aes_hw_set_encrypt_key,.-.L_aes_hw_set_encrypt_key_begin
+.globl	aes_hw_set_decrypt_key
+.hidden	aes_hw_set_decrypt_key
+.type	aes_hw_set_decrypt_key,@function
 .align	16
-aesni_set_decrypt_key:
-.L_aesni_set_decrypt_key_begin:
+aes_hw_set_decrypt_key:
+.L_aes_hw_set_decrypt_key_begin:
 	movl	4(%esp),%eax
 	movl	8(%esp),%ecx
 	movl	12(%esp),%edx
@@ -2457,7 +2460,7 @@
 	xorl	%eax,%eax
 .L114dec_key_ret:
 	ret
-.size	aesni_set_decrypt_key,.-.L_aesni_set_decrypt_key_begin
+.size	aes_hw_set_decrypt_key,.-.L_aes_hw_set_decrypt_key_begin
 .align	64
 .Lkey_const:
 .long	202313229,202313229,202313229,202313229
diff --git a/linux-x86/crypto/fipsmodule/bn-586.S b/linux-x86/crypto/fipsmodule/bn-586.S
index 1934744..64e36ce 100644
--- a/linux-x86/crypto/fipsmodule/bn-586.S
+++ b/linux-x86/crypto/fipsmodule/bn-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	bn_mul_add_words
 .hidden	bn_mul_add_words
diff --git a/linux-x86/crypto/fipsmodule/co-586.S b/linux-x86/crypto/fipsmodule/co-586.S
index 5e02a90..b617d81 100644
--- a/linux-x86/crypto/fipsmodule/co-586.S
+++ b/linux-x86/crypto/fipsmodule/co-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	bn_mul_comba8
 .hidden	bn_mul_comba8
diff --git a/linux-x86/crypto/fipsmodule/ghash-x86.S b/linux-x86/crypto/fipsmodule/ghash-x86.S
index af0d116..e183078 100644
--- a/linux-x86/crypto/fipsmodule/ghash-x86.S
+++ b/linux-x86/crypto/fipsmodule/ghash-x86.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	gcm_gmult_4bit_mmx
 .hidden	gcm_gmult_4bit_mmx
diff --git a/linux-x86/crypto/fipsmodule/md5-586.S b/linux-x86/crypto/fipsmodule/md5-586.S
index 9c18410..cc0dcd8 100644
--- a/linux-x86/crypto/fipsmodule/md5-586.S
+++ b/linux-x86/crypto/fipsmodule/md5-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	md5_block_asm_data_order
 .hidden	md5_block_asm_data_order
diff --git a/linux-x86/crypto/fipsmodule/sha1-586.S b/linux-x86/crypto/fipsmodule/sha1-586.S
index 94cb06b..4df4d06 100644
--- a/linux-x86/crypto/fipsmodule/sha1-586.S
+++ b/linux-x86/crypto/fipsmodule/sha1-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	sha1_block_data_order
 .hidden	sha1_block_data_order
diff --git a/linux-x86/crypto/fipsmodule/sha256-586.S b/linux-x86/crypto/fipsmodule/sha256-586.S
index ee9116b..39d5778 100644
--- a/linux-x86/crypto/fipsmodule/sha256-586.S
+++ b/linux-x86/crypto/fipsmodule/sha256-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	sha256_block_data_order
 .hidden	sha256_block_data_order
diff --git a/linux-x86/crypto/fipsmodule/sha512-586.S b/linux-x86/crypto/fipsmodule/sha512-586.S
index af6cec7..c8dd677 100644
--- a/linux-x86/crypto/fipsmodule/sha512-586.S
+++ b/linux-x86/crypto/fipsmodule/sha512-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	sha512_block_data_order
 .hidden	sha512_block_data_order
diff --git a/linux-x86/crypto/fipsmodule/vpaes-x86.S b/linux-x86/crypto/fipsmodule/vpaes-x86.S
index 5341134..b2c63e5 100644
--- a/linux-x86/crypto/fipsmodule/vpaes-x86.S
+++ b/linux-x86/crypto/fipsmodule/vpaes-x86.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .align	64
 .L_vpaes_consts:
diff --git a/linux-x86/crypto/fipsmodule/x86-mont.S b/linux-x86/crypto/fipsmodule/x86-mont.S
index ade5964..9924c02 100644
--- a/linux-x86/crypto/fipsmodule/x86-mont.S
+++ b/linux-x86/crypto/fipsmodule/x86-mont.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	bn_mul_mont
 .hidden	bn_mul_mont
diff --git a/mac-x86/crypto/chacha/chacha-x86.S b/mac-x86/crypto/chacha/chacha-x86.S
index 0bf1900..bc32488 100644
--- a/mac-x86/crypto/chacha/chacha-x86.S
+++ b/mac-x86/crypto/chacha/chacha-x86.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_ChaCha20_ctr32
 .private_extern	_ChaCha20_ctr32
diff --git a/mac-x86/crypto/fipsmodule/aes-586.S b/mac-x86/crypto/fipsmodule/aes-586.S
index 781ab4b..3634f64 100644
--- a/mac-x86/crypto/fipsmodule/aes-586.S
+++ b/mac-x86/crypto/fipsmodule/aes-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .private_extern	__x86_AES_encrypt_compact
 .align	4
diff --git a/mac-x86/crypto/fipsmodule/aesni-x86.S b/mac-x86/crypto/fipsmodule/aesni-x86.S
index 7e7cf08..cca1d32 100644
--- a/mac-x86/crypto/fipsmodule/aesni-x86.S
+++ b/mac-x86/crypto/fipsmodule/aesni-x86.S
@@ -2,12 +2,15 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
-.globl	_aesni_encrypt
-.private_extern	_aesni_encrypt
+.globl	_aes_hw_encrypt
+.private_extern	_aes_hw_encrypt
 .align	4
-_aesni_encrypt:
-L_aesni_encrypt_begin:
+_aes_hw_encrypt:
+L_aes_hw_encrypt_begin:
 	movl	4(%esp),%eax
 	movl	12(%esp),%edx
 	movups	(%eax),%xmm2
@@ -29,11 +32,11 @@
 	movups	%xmm2,(%eax)
 	pxor	%xmm2,%xmm2
 	ret
-.globl	_aesni_decrypt
-.private_extern	_aesni_decrypt
+.globl	_aes_hw_decrypt
+.private_extern	_aes_hw_decrypt
 .align	4
-_aesni_decrypt:
-L_aesni_decrypt_begin:
+_aes_hw_decrypt:
+L_aes_hw_decrypt_begin:
 	movl	4(%esp),%eax
 	movl	12(%esp),%edx
 	movups	(%eax),%xmm2
@@ -349,11 +352,11 @@
 .byte	102,15,56,223,240
 .byte	102,15,56,223,248
 	ret
-.globl	_aesni_ecb_encrypt
-.private_extern	_aesni_ecb_encrypt
+.globl	_aes_hw_ecb_encrypt
+.private_extern	_aes_hw_ecb_encrypt
 .align	4
-_aesni_ecb_encrypt:
-L_aesni_ecb_encrypt_begin:
+_aes_hw_ecb_encrypt:
+L_aes_hw_ecb_encrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -583,11 +586,11 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_aesni_ccm64_encrypt_blocks
-.private_extern	_aesni_ccm64_encrypt_blocks
+.globl	_aes_hw_ccm64_encrypt_blocks
+.private_extern	_aes_hw_ccm64_encrypt_blocks
 .align	4
-_aesni_ccm64_encrypt_blocks:
-L_aesni_ccm64_encrypt_blocks_begin:
+_aes_hw_ccm64_encrypt_blocks:
+L_aes_hw_ccm64_encrypt_blocks_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -670,11 +673,11 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_aesni_ccm64_decrypt_blocks
-.private_extern	_aesni_ccm64_decrypt_blocks
+.globl	_aes_hw_ccm64_decrypt_blocks
+.private_extern	_aes_hw_ccm64_decrypt_blocks
 .align	4
-_aesni_ccm64_decrypt_blocks:
-L_aesni_ccm64_decrypt_blocks_begin:
+_aes_hw_ccm64_decrypt_blocks:
+L_aes_hw_ccm64_decrypt_blocks_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -792,11 +795,11 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_aesni_ctr32_encrypt_blocks
-.private_extern	_aesni_ctr32_encrypt_blocks
+.globl	_aes_hw_ctr32_encrypt_blocks
+.private_extern	_aes_hw_ctr32_encrypt_blocks
 .align	4
-_aesni_ctr32_encrypt_blocks:
-L_aesni_ctr32_encrypt_blocks_begin:
+_aes_hw_ctr32_encrypt_blocks:
+L_aes_hw_ctr32_encrypt_blocks_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -1029,11 +1032,11 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_aesni_xts_encrypt
-.private_extern	_aesni_xts_encrypt
+.globl	_aes_hw_xts_encrypt
+.private_extern	_aes_hw_xts_encrypt
 .align	4
-_aesni_xts_encrypt:
-L_aesni_xts_encrypt_begin:
+_aes_hw_xts_encrypt:
+L_aes_hw_xts_encrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -1388,11 +1391,11 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_aesni_xts_decrypt
-.private_extern	_aesni_xts_decrypt
+.globl	_aes_hw_xts_decrypt
+.private_extern	_aes_hw_xts_decrypt
 .align	4
-_aesni_xts_decrypt:
-L_aesni_xts_decrypt_begin:
+_aes_hw_xts_decrypt:
+L_aes_hw_xts_decrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -1777,11 +1780,11 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_aesni_cbc_encrypt
-.private_extern	_aesni_cbc_encrypt
+.globl	_aes_hw_cbc_encrypt
+.private_extern	_aes_hw_cbc_encrypt
 .align	4
-_aesni_cbc_encrypt:
-L_aesni_cbc_encrypt_begin:
+_aes_hw_cbc_encrypt:
+L_aes_hw_cbc_encrypt_begin:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -2369,21 +2372,21 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_aesni_set_encrypt_key
-.private_extern	_aesni_set_encrypt_key
+.globl	_aes_hw_set_encrypt_key
+.private_extern	_aes_hw_set_encrypt_key
 .align	4
-_aesni_set_encrypt_key:
-L_aesni_set_encrypt_key_begin:
+_aes_hw_set_encrypt_key:
+L_aes_hw_set_encrypt_key_begin:
 	movl	4(%esp),%eax
 	movl	8(%esp),%ecx
 	movl	12(%esp),%edx
 	call	__aesni_set_encrypt_key
 	ret
-.globl	_aesni_set_decrypt_key
-.private_extern	_aesni_set_decrypt_key
+.globl	_aes_hw_set_decrypt_key
+.private_extern	_aes_hw_set_decrypt_key
 .align	4
-_aesni_set_decrypt_key:
-L_aesni_set_decrypt_key_begin:
+_aes_hw_set_decrypt_key:
+L_aes_hw_set_decrypt_key_begin:
 	movl	4(%esp),%eax
 	movl	8(%esp),%ecx
 	movl	12(%esp),%edx
diff --git a/mac-x86/crypto/fipsmodule/bn-586.S b/mac-x86/crypto/fipsmodule/bn-586.S
index d48a42a..7d0462b 100644
--- a/mac-x86/crypto/fipsmodule/bn-586.S
+++ b/mac-x86/crypto/fipsmodule/bn-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_bn_mul_add_words
 .private_extern	_bn_mul_add_words
diff --git a/mac-x86/crypto/fipsmodule/co-586.S b/mac-x86/crypto/fipsmodule/co-586.S
index c55fcb0..578ca70 100644
--- a/mac-x86/crypto/fipsmodule/co-586.S
+++ b/mac-x86/crypto/fipsmodule/co-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_bn_mul_comba8
 .private_extern	_bn_mul_comba8
diff --git a/mac-x86/crypto/fipsmodule/ghash-x86.S b/mac-x86/crypto/fipsmodule/ghash-x86.S
index 1d8f246..e13bf3e 100644
--- a/mac-x86/crypto/fipsmodule/ghash-x86.S
+++ b/mac-x86/crypto/fipsmodule/ghash-x86.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_gcm_gmult_4bit_mmx
 .private_extern	_gcm_gmult_4bit_mmx
diff --git a/mac-x86/crypto/fipsmodule/md5-586.S b/mac-x86/crypto/fipsmodule/md5-586.S
index 5cb4b15..391acbd 100644
--- a/mac-x86/crypto/fipsmodule/md5-586.S
+++ b/mac-x86/crypto/fipsmodule/md5-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_md5_block_asm_data_order
 .private_extern	_md5_block_asm_data_order
diff --git a/mac-x86/crypto/fipsmodule/sha1-586.S b/mac-x86/crypto/fipsmodule/sha1-586.S
index d449b66..89c5d16 100644
--- a/mac-x86/crypto/fipsmodule/sha1-586.S
+++ b/mac-x86/crypto/fipsmodule/sha1-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_sha1_block_data_order
 .private_extern	_sha1_block_data_order
diff --git a/mac-x86/crypto/fipsmodule/sha256-586.S b/mac-x86/crypto/fipsmodule/sha256-586.S
index 68e3089..a974488 100644
--- a/mac-x86/crypto/fipsmodule/sha256-586.S
+++ b/mac-x86/crypto/fipsmodule/sha256-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_sha256_block_data_order
 .private_extern	_sha256_block_data_order
diff --git a/mac-x86/crypto/fipsmodule/sha512-586.S b/mac-x86/crypto/fipsmodule/sha512-586.S
index 1fe10cc..a08e6ef 100644
--- a/mac-x86/crypto/fipsmodule/sha512-586.S
+++ b/mac-x86/crypto/fipsmodule/sha512-586.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_sha512_block_data_order
 .private_extern	_sha512_block_data_order
diff --git a/mac-x86/crypto/fipsmodule/vpaes-x86.S b/mac-x86/crypto/fipsmodule/vpaes-x86.S
index b232bad..c47a217 100644
--- a/mac-x86/crypto/fipsmodule/vpaes-x86.S
+++ b/mac-x86/crypto/fipsmodule/vpaes-x86.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .align	6,0x90
 L_vpaes_consts:
diff --git a/mac-x86/crypto/fipsmodule/x86-mont.S b/mac-x86/crypto/fipsmodule/x86-mont.S
index c6c16da..3ef8774 100644
--- a/mac-x86/crypto/fipsmodule/x86-mont.S
+++ b/mac-x86/crypto/fipsmodule/x86-mont.S
@@ -2,6 +2,9 @@
 # source tree. Do not edit by hand.
 
 #if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
 .text
 .globl	_bn_mul_mont
 .private_extern	_bn_mul_mont
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dd2d937..bfde5d5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -53,6 +53,9 @@
 
 if(BORINGSSL_PREFIX AND BORINGSSL_PREFIX_SYMBOLS)
   add_definitions(-DBORINGSSL_PREFIX=${BORINGSSL_PREFIX})
+  # CMake automatically connects include_directories to the NASM command-line,
+  # but not add_definitions.
+  set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DBORINGSSL_PREFIX=${BORINGSSL_PREFIX}")
 
   # Use "symbol_prefix_include" to store generated header files
   include_directories(${CMAKE_CURRENT_BINARY_DIR}/symbol_prefix_include)
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index ee9626a..b1ca70e 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -53,7 +53,7 @@
       set(PERLASM_STYLE win32n)
       set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2")
     endif()
-    set(CMAKE_ASM_NASM_FLAGS "-gcv8")
+    set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -gcv8")
 
     # On Windows, we use the NASM output, specifically built with Yasm.
     set(ASM_EXT asm)
diff --git a/src/crypto/fipsmodule/aes/asm/aesni-x86.pl b/src/crypto/fipsmodule/aes/asm/aesni-x86.pl
index cf1a51e..aff2b40 100644
--- a/src/crypto/fipsmodule/aes/asm/aesni-x86.pl
+++ b/src/crypto/fipsmodule/aes/asm/aesni-x86.pl
@@ -67,9 +67,10 @@
 # Goldmont	3.84/1.39	1.39	1.63	1.31	1.70
 # Bulldozer	5.80/0.98	1.05	1.24	0.93	1.23
 
-$PREFIX="aesni";	# if $PREFIX is set to "AES", the script
+$PREFIX="aes_hw";	# if $PREFIX is set to "AES", the script
 			# generates drop-in replacement for
 			# crypto/aes/asm/aes-586.pl:-)
+$AESNI_PREFIX="aes_hw";
 $inline=1;		# inline _aesni_[en|de]crypt
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -85,7 +86,7 @@
 &external_label("OPENSSL_ia32cap_P");
 &static_label("key_const");
 
-if ($PREFIX eq "aesni")	{ $movekey=\&movups; }
+if ($PREFIX eq $AESNI_PREFIX)	{ $movekey=\&movups; }
 else			{ $movekey=\&movups; }
 
 $len="eax";
@@ -414,21 +415,21 @@
     &ret();
     &function_end_B("_aesni_${p}rypt6");
 }
-&aesni_generate2("enc") if ($PREFIX eq "aesni");
+&aesni_generate2("enc") if ($PREFIX eq $AESNI_PREFIX);
 &aesni_generate2("dec");
-&aesni_generate3("enc") if ($PREFIX eq "aesni");
+&aesni_generate3("enc") if ($PREFIX eq $AESNI_PREFIX);
 &aesni_generate3("dec");
-&aesni_generate4("enc") if ($PREFIX eq "aesni");
+&aesni_generate4("enc") if ($PREFIX eq $AESNI_PREFIX);
 &aesni_generate4("dec");
-&aesni_generate6("enc") if ($PREFIX eq "aesni");
+&aesni_generate6("enc") if ($PREFIX eq $AESNI_PREFIX);
 &aesni_generate6("dec");
 
-if ($PREFIX eq "aesni") {
+if ($PREFIX eq $AESNI_PREFIX) {
 ######################################################################
-# void aesni_ecb_encrypt (const void *in, void *out,
+# void aes_hw_ecb_encrypt (const void *in, void *out,
 #                         size_t length, const AES_KEY *key,
 #                         int enc);
-&function_begin("aesni_ecb_encrypt");
+&function_begin("${PREFIX}_ecb_encrypt");
 	&mov	($inp,&wparam(0));
 	&mov	($out,&wparam(1));
 	&mov	($len,&wparam(2));
@@ -647,10 +648,10 @@
 	&pxor	("xmm5","xmm5");
 	&pxor	("xmm6","xmm6");
 	&pxor	("xmm7","xmm7");
-&function_end("aesni_ecb_encrypt");
+&function_end("${PREFIX}_ecb_encrypt");
 
 ######################################################################
-# void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
+# void aes_hw_ccm64_[en|de]crypt_blocks (const void *in, void *out,
 #                         size_t blocks, const AES_KEY *key,
 #                         const char *ivec,char *cmac);
 #
@@ -659,7 +660,7 @@
 # (see engine/eng_aesni.c for details)
 #
 { my $cmac=$inout1;
-&function_begin("aesni_ccm64_encrypt_blocks");
+&function_begin("${PREFIX}_ccm64_encrypt_blocks");
 	&mov	($inp,&wparam(0));
 	&mov	($out,&wparam(1));
 	&mov	($len,&wparam(2));
@@ -745,9 +746,9 @@
 	&pxor	("xmm5","xmm5");
 	&pxor	("xmm6","xmm6");
 	&pxor	("xmm7","xmm7");
-&function_end("aesni_ccm64_encrypt_blocks");
+&function_end("${PREFIX}_ccm64_encrypt_blocks");
 
-&function_begin("aesni_ccm64_decrypt_blocks");
+&function_begin("${PREFIX}_ccm64_decrypt_blocks");
 	&mov	($inp,&wparam(0));
 	&mov	($out,&wparam(1));
 	&mov	($len,&wparam(2));
@@ -854,11 +855,11 @@
 	&pxor	("xmm5","xmm5");
 	&pxor	("xmm6","xmm6");
 	&pxor	("xmm7","xmm7");
-&function_end("aesni_ccm64_decrypt_blocks");
+&function_end("${PREFIX}_ccm64_decrypt_blocks");
 }
 
 ######################################################################
-# void aesni_ctr32_encrypt_blocks (const void *in, void *out,
+# void aes_hw_ctr32_encrypt_blocks (const void *in, void *out,
 #                         size_t blocks, const AES_KEY *key,
 #                         const char *ivec);
 #
@@ -873,7 +874,7 @@
 #	64	2nd triplet of counter vector
 #	80	saved %esp
 
-&function_begin("aesni_ctr32_encrypt_blocks");
+&function_begin("${PREFIX}_ctr32_encrypt_blocks");
 	&mov	($inp,&wparam(0));
 	&mov	($out,&wparam(1));
 	&mov	($len,&wparam(2));
@@ -1115,16 +1116,16 @@
 	&movdqa	(&QWP(64,"esp"),"xmm0");
 	&pxor	("xmm7","xmm7");
 	&mov	("esp",&DWP(80,"esp"));
-&function_end("aesni_ctr32_encrypt_blocks");
+&function_end("${PREFIX}_ctr32_encrypt_blocks");
 
 ######################################################################
-# void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
+# void aes_hw_xts_[en|de]crypt(const char *inp,char *out,size_t len,
 #	const AES_KEY *key1, const AES_KEY *key2
 #	const unsigned char iv[16]);
 #
 { my ($tweak,$twtmp,$twres,$twmask)=($rndkey1,$rndkey0,$inout0,$inout1);
 
-&function_begin("aesni_xts_encrypt");
+&function_begin("${PREFIX}_xts_encrypt");
 	&mov	($key,&wparam(4));		# key2
 	&mov	($inp,&wparam(5));		# clear-text tweak
 
@@ -1470,9 +1471,9 @@
 	&pxor	("xmm7","xmm7");
 	&movdqa	(&QWP(16*5,"esp"),"xmm0");
 	&mov	("esp",&DWP(16*7+4,"esp"));	# restore %esp
-&function_end("aesni_xts_encrypt");
+&function_end("${PREFIX}_xts_encrypt");
 
-&function_begin("aesni_xts_decrypt");
+&function_begin("${PREFIX}_xts_decrypt");
 	&mov	($key,&wparam(4));		# key2
 	&mov	($inp,&wparam(5));		# clear-text tweak
 
@@ -1846,7 +1847,7 @@
 	&pxor	("xmm7","xmm7");
 	&movdqa	(&QWP(16*5,"esp"),"xmm0");
 	&mov	("esp",&DWP(16*7+4,"esp"));	# restore %esp
-&function_end("aesni_xts_decrypt");
+&function_end("${PREFIX}_xts_decrypt");
 }
 }
 
diff --git a/src/crypto/fipsmodule/aes/internal.h b/src/crypto/fipsmodule/aes/internal.h
index 7c19b9c..a9f8a8c 100644
--- a/src/crypto/fipsmodule/aes/internal.h
+++ b/src/crypto/fipsmodule/aes/internal.h
@@ -26,7 +26,7 @@
 
 #if !defined(OPENSSL_NO_ASM)
 
-#if defined(OPENSSL_X86_64)
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
 #define HWAES
 #define HWAES_ECB
 
diff --git a/src/crypto/perlasm/x86asm.pl b/src/crypto/perlasm/x86asm.pl
index c9f645e..3d2943b 100644
--- a/src/crypto/perlasm/x86asm.pl
+++ b/src/crypto/perlasm/x86asm.pl
@@ -262,7 +262,20 @@
 $comment source tree. Do not edit by hand.
 
 ___
-    print "#if defined(__i386__)\n" unless ($win32 || $netware);
+    if ($win32 || $netware) {
+        print <<___ unless $masm;
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
+___
+    } else {
+        print <<___;
+#if defined(__i386__)
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols_asm.h>
+#endif
+___
+    }
     print @out;
     print "#endif\n" unless ($win32 || $netware);
 }
@@ -288,7 +301,7 @@
     #elsif (($type eq "nw-mwasm"))
     #{	$netware=1; $mwerks=1;	require "x86nasm.pl";	}
     elsif (($type eq "win32"))
-    {	$win32=1;		require "x86masm.pl";	}
+    {	$win32=1; $masm=1;	require "x86masm.pl";	}
     elsif (($type eq "macosx"))
     {	$aout=1; $macosx=1;	require "x86gas.pl";	}
     elsif (($type eq "android"))
diff --git a/src/crypto/stack/stack_test.cc b/src/crypto/stack/stack_test.cc
index 8b26971..7be84ed 100644
--- a/src/crypto/stack/stack_test.cc
+++ b/src/crypto/stack/stack_test.cc
@@ -31,9 +31,9 @@
 
 static void TEST_INT_free(TEST_INT *x) { OPENSSL_free(x); }
 
-namespace bssl {
+BSSL_NAMESPACE_BEGIN
 BORINGSSL_MAKE_DELETER(TEST_INT, TEST_INT_free)
-}  // namespace bssl
+BSSL_NAMESPACE_END
 
 static bssl::UniquePtr<TEST_INT> TEST_INT_new(int x) {
   bssl::UniquePtr<TEST_INT> ret(
diff --git a/src/crypto/thread_win.c b/src/crypto/thread_win.c
index 8b2b2da..4501165 100644
--- a/src/crypto/thread_win.c
+++ b/src/crypto/thread_win.c
@@ -146,12 +146,18 @@
 // if it's not already there. (E.g. if __declspec(thread) is not used). Force
 // a reference to p_thread_callback_boringssl to prevent whole program
 // optimization from discarding the variable.
+//
+// Note, in the prefixed build, |p_thread_callback_boringssl| may be a macro.
+#define STRINGIFY(x) #x
+#define EXPAND_AND_STRINGIFY(x) STRINGIFY(x)
 #ifdef _WIN64
-#pragma comment(linker, "/INCLUDE:_tls_used")
-#pragma comment(linker, "/INCLUDE:p_thread_callback_boringssl")
+__pragma(comment(linker, "/INCLUDE:_tls_used"))
+__pragma(comment(
+    linker, "/INCLUDE:" EXPAND_AND_STRINGIFY(p_thread_callback_boringssl)))
 #else
-#pragma comment(linker, "/INCLUDE:__tls_used")
-#pragma comment(linker, "/INCLUDE:_p_thread_callback_boringssl")
+__pragma(comment(linker, "/INCLUDE:__tls_used"))
+__pragma(comment(
+    linker, "/INCLUDE:_" EXPAND_AND_STRINGIFY(p_thread_callback_boringssl)))
 #endif
 
 // .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are
diff --git a/src/crypto/x509/asn1_gen.c b/src/crypto/x509/asn1_gen.c
index 5b74cd1..98a6fac 100644
--- a/src/crypto/x509/asn1_gen.c
+++ b/src/crypto/x509/asn1_gen.c
@@ -65,6 +65,7 @@
 #include <openssl/x509v3.h>
 
 #include "../internal.h"
+#include "../x509v3/internal.h"
 
 /*
  * Although this file is in crypto/x509 for layering purposes, it emits
@@ -769,7 +770,7 @@
 
         if (format == ASN1_GEN_FORMAT_HEX) {
 
-            if (!(rdata = string_to_hex((char *)str, &rdlen))) {
+            if (!(rdata = x509v3_hex_to_bytes((char *)str, &rdlen))) {
                 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX);
                 goto bad_str;
             }
diff --git a/src/crypto/x509v3/internal.h b/src/crypto/x509v3/internal.h
new file mode 100644
index 0000000..e6be684
--- /dev/null
+++ b/src/crypto/x509v3/internal.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2018, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_X509V3_INTERNAL_H
+#define OPENSSL_HEADER_X509V3_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+// x509v3_bytes_to_hex encodes |len| bytes from |buffer| to hex and returns a
+// newly-allocated NUL-terminated string containing the result, or NULL on
+// allocation error.
+//
+// Note this function was historically named |hex_to_string| in OpenSSL, not
+// |string_to_hex|.
+char *x509v3_bytes_to_hex(const unsigned char *buffer, long len);
+
+// x509v3_hex_string_to_bytes decodes |str| in hex and returns a newly-allocated
+// array containing the result, or NULL on error. On success, it sets |*len| to
+// the length of the result. Colon separators between bytes in the input are
+// allowed and ignored.
+//
+// Note this function was historically named |string_to_hex| in OpenSSL, not
+// |hex_to_string|.
+unsigned char *x509v3_hex_to_bytes(const char *str, long *len);
+
+// x509v3_name_cmp returns zero if |name| is equal to |cmp| or begins with |cmp|
+// followed by '.'. Otherwise, it returns a non-zero number.
+int x509v3_name_cmp(const char *name, const char *cmp);
+
+
+#if defined(__cplusplus)
+}  /* extern C */
+#endif
+
+#endif  /* OPENSSL_HEADER_X509V3_INTERNAL_H */
diff --git a/src/crypto/x509v3/v3_akey.c b/src/crypto/x509v3/v3_akey.c
index 4503e61..30c02e2 100644
--- a/src/crypto/x509v3/v3_akey.c
+++ b/src/crypto/x509v3/v3_akey.c
@@ -66,6 +66,9 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+#include "internal.h"
+
+
 static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
                                                  AUTHORITY_KEYID *akeyid,
                                                  STACK_OF(CONF_VALUE)
@@ -92,14 +95,14 @@
 {
     char *tmp;
     if (akeyid->keyid) {
-        tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length);
+        tmp = x509v3_bytes_to_hex(akeyid->keyid->data, akeyid->keyid->length);
         X509V3_add_value("keyid", tmp, &extlist);
         OPENSSL_free(tmp);
     }
     if (akeyid->issuer)
         extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
     if (akeyid->serial) {
-        tmp = hex_to_string(akeyid->serial->data, akeyid->serial->length);
+        tmp = x509v3_bytes_to_hex(akeyid->serial->data, akeyid->serial->length);
         X509V3_add_value("serial", tmp, &extlist);
         OPENSSL_free(tmp);
     }
diff --git a/src/crypto/x509v3/v3_alt.c b/src/crypto/x509v3/v3_alt.c
index b78a410..5a4fadf 100644
--- a/src/crypto/x509v3/v3_alt.c
+++ b/src/crypto/x509v3/v3_alt.c
@@ -64,6 +64,9 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+#include "internal.h"
+
+
 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
                                       X509V3_CTX *ctx,
                                       STACK_OF(CONF_VALUE) *nval);
@@ -261,7 +264,7 @@
     }
     for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
         cnf = sk_CONF_VALUE_value(nval, i);
-        if (!name_cmp(cnf->name, "issuer") && cnf->value &&
+        if (!x509v3_name_cmp(cnf->name, "issuer") && cnf->value &&
             !strcmp(cnf->value, "copy")) {
             if (!copy_issuer(ctx, gens))
                 goto err;
@@ -331,11 +334,11 @@
     }
     for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
         cnf = sk_CONF_VALUE_value(nval, i);
-        if (!name_cmp(cnf->name, "email") && cnf->value &&
+        if (!x509v3_name_cmp(cnf->name, "email") && cnf->value &&
             !strcmp(cnf->value, "copy")) {
             if (!copy_email(ctx, gens, 0))
                 goto err;
-        } else if (!name_cmp(cnf->name, "email") && cnf->value &&
+        } else if (!x509v3_name_cmp(cnf->name, "email") && cnf->value &&
                    !strcmp(cnf->value, "move")) {
             if (!copy_email(ctx, gens, 1))
                 goto err;
@@ -545,19 +548,19 @@
         return NULL;
     }
 
-    if (!name_cmp(name, "email"))
+    if (!x509v3_name_cmp(name, "email"))
         type = GEN_EMAIL;
-    else if (!name_cmp(name, "URI"))
+    else if (!x509v3_name_cmp(name, "URI"))
         type = GEN_URI;
-    else if (!name_cmp(name, "DNS"))
+    else if (!x509v3_name_cmp(name, "DNS"))
         type = GEN_DNS;
-    else if (!name_cmp(name, "RID"))
+    else if (!x509v3_name_cmp(name, "RID"))
         type = GEN_RID;
-    else if (!name_cmp(name, "IP"))
+    else if (!x509v3_name_cmp(name, "IP"))
         type = GEN_IPADD;
-    else if (!name_cmp(name, "dirName"))
+    else if (!x509v3_name_cmp(name, "dirName"))
         type = GEN_DIRNAME;
-    else if (!name_cmp(name, "otherName"))
+    else if (!x509v3_name_cmp(name, "otherName"))
         type = GEN_OTHERNAME;
     else {
         OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
diff --git a/src/crypto/x509v3/v3_conf.c b/src/crypto/x509v3/v3_conf.c
index ff2eae1..e98d0fc 100644
--- a/src/crypto/x509v3/v3_conf.c
+++ b/src/crypto/x509v3/v3_conf.c
@@ -69,6 +69,7 @@
 #include <openssl/x509v3.h>
 
 #include "../internal.h"
+#include "internal.h"
 
 static int v3_check_critical(char **value);
 static int v3_check_generic(char **value);
@@ -278,7 +279,7 @@
     }
 
     if (gen_type == 1)
-        ext_der = string_to_hex(value, &ext_len);
+        ext_der = x509v3_hex_to_bytes(value, &ext_len);
     else if (gen_type == 2)
         ext_der = generic_asn1(value, ctx, &ext_len);
 
diff --git a/src/crypto/x509v3/v3_cpols.c b/src/crypto/x509v3/v3_cpols.c
index 4def530..18d260b 100644
--- a/src/crypto/x509v3/v3_cpols.c
+++ b/src/crypto/x509v3/v3_cpols.c
@@ -69,6 +69,7 @@
 #include <openssl/stack.h>
 #include <openssl/x509v3.h>
 
+#include "internal.h"
 #include "pcy_int.h"
 
 /* Certificate policies extension support: this one is a bit complex... */
@@ -231,7 +232,7 @@
             }
             pol->policyid = pobj;
 
-        } else if (!name_cmp(cnf->name, "CPS")) {
+        } else if (!x509v3_name_cmp(cnf->name, "CPS")) {
             if (!pol->qualifiers)
                 pol->qualifiers = sk_POLICYQUALINFO_new_null();
             if (!(qual = POLICYQUALINFO_new()))
@@ -251,7 +252,7 @@
             if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
                                  strlen(cnf->value)))
                 goto merr;
-        } else if (!name_cmp(cnf->name, "userNotice")) {
+        } else if (!x509v3_name_cmp(cnf->name, "userNotice")) {
             STACK_OF(CONF_VALUE) *unot;
             if (*cnf->value != '@') {
                 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME);
diff --git a/src/crypto/x509v3/v3_pci.c b/src/crypto/x509v3/v3_pci.c
index 4352abe..f9031c0 100644
--- a/src/crypto/x509v3/v3_pci.c
+++ b/src/crypto/x509v3/v3_pci.c
@@ -44,6 +44,7 @@
 #include <openssl/x509v3.h>
 
 #include "../internal.h"
+#include "internal.h"
 
 
 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
@@ -123,7 +124,7 @@
         }
         if (strncmp(val->value, "hex:", 4) == 0) {
             unsigned char *tmp_data2 =
-                string_to_hex(val->value + 4, &val_len);
+                x509v3_hex_to_bytes(val->value + 4, &val_len);
 
             if (!tmp_data2) {
                 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
diff --git a/src/crypto/x509v3/v3_skey.c b/src/crypto/x509v3/v3_skey.c
index 65f8287..6a16e78 100644
--- a/src/crypto/x509v3/v3_skey.c
+++ b/src/crypto/x509v3/v3_skey.c
@@ -63,6 +63,9 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+#include "internal.h"
+
+
 static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
                                       X509V3_CTX *ctx, char *str);
 const X509V3_EXT_METHOD v3_skey_id = {
@@ -76,7 +79,7 @@
 
 char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct)
 {
-    return hex_to_string(oct->data, oct->length);
+    return x509v3_bytes_to_hex(oct->data, oct->length);
 }
 
 ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
@@ -90,7 +93,7 @@
         return NULL;
     }
 
-    if (!(oct->data = string_to_hex(str, &length))) {
+    if (!(oct->data = x509v3_hex_to_bytes(str, &length))) {
         M_ASN1_OCTET_STRING_free(oct);
         return NULL;
     }
diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c
index 589e296..2a293dc 100644
--- a/src/crypto/x509v3/v3_utl.c
+++ b/src/crypto/x509v3/v3_utl.c
@@ -72,6 +72,7 @@
 
 #include "../conf/internal.h"
 #include "../internal.h"
+#include "internal.h"
 
 
 static char *strip_spaces(char *name);
@@ -446,7 +447,7 @@
  * on EBCDIC machines)
  */
 
-char *hex_to_string(const unsigned char *buffer, long len)
+char *x509v3_bytes_to_hex(const unsigned char *buffer, long len)
 {
     char *tmp, *q;
     const unsigned char *p;
@@ -469,11 +470,7 @@
     return tmp;
 }
 
-/*
- * Give a string of hex digits convert to a buffer
- */
-
-unsigned char *string_to_hex(const char *str, long *len)
+unsigned char *x509v3_hex_to_bytes(const char *str, long *len)
 {
     unsigned char *hexbuf, *q;
     unsigned char ch, cl, *p;
@@ -533,11 +530,7 @@
 
 }
 
-/*
- * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
- */
-
-int name_cmp(const char *name, const char *cmp)
+int x509v3_name_cmp(const char *name, const char *cmp)
 {
     int len, ret;
     char c;
diff --git a/src/include/openssl/x509v3.h b/src/include/openssl/x509v3.h
index 4a654b5..d2d39f8 100644
--- a/src/include/openssl/x509v3.h
+++ b/src/include/openssl/x509v3.h
@@ -666,10 +666,6 @@
 OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
 OPENSSL_EXPORT int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags);
 
-char *hex_to_string(const unsigned char *buffer, long len);
-unsigned char *string_to_hex(const char *str, long *len);
-int name_cmp(const char *name, const char *cmp);
-
 OPENSSL_EXPORT void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
 								 int ml);
 OPENSSL_EXPORT int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent);
diff --git a/src/util/ar/ar.go b/src/util/ar/ar.go
index f5dee62..756caf5 100644
--- a/src/util/ar/ar.go
+++ b/src/util/ar/ar.go
@@ -102,7 +102,9 @@
 			}
 
 			filename := longFilenameTable[offset:]
-			if i := bytes.IndexByte(filename, '/'); i < 0 {
+			// Windows terminates filenames with NUL characters,
+			// while sysv/GNU uses /.
+			if i := bytes.IndexAny(filename, "/\x00"); i < 0 {
 				return nil, errors.New("ar: unterminated filename in table")
 			} else {
 				filename = filename[:i]
@@ -141,6 +143,10 @@
 			name = name[:null]
 		}
 
+		if name == "__.SYMDEF" || name == "__.SYMDEF SORTED" {
+			continue
+		}
+
 		ret[name] = contents
 	}
 
diff --git a/src/util/ar/ar_test.go b/src/util/ar/ar_test.go
new file mode 100644
index 0000000..ef37d79
--- /dev/null
+++ b/src/util/ar/ar_test.go
@@ -0,0 +1,118 @@
+// Copyright (c) 2018, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package ar
+
+import (
+	"bytes"
+	"flag"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+)
+
+var testDataDir = flag.String("testdata", "testdata", "The path to the test data directory.")
+
+type arTest struct {
+	name string
+	in   string
+	out  map[string]string
+	// allowPadding is true if the contents may have trailing newlines at end.
+	// On macOS, ar calls ranlib which pads all inputs up to eight bytes with
+	// newlines. Unlike ar's native padding up to two bytes, this padding is
+	// included in the size field, so it is not removed when decoding.
+	allowPadding bool
+}
+
+func (test *arTest) Path(file string) string {
+	return filepath.Join(*testDataDir, test.name, file)
+}
+
+func removeTrailingNewlines(in []byte) []byte {
+	for len(in) > 0 && in[len(in)-1] == '\n' {
+		in = in[:len(in)-1]
+	}
+	return in
+}
+
+var arTests = []arTest{
+	{
+		"linux",
+		"libsample.a",
+		map[string]string{
+			"foo.c.o": "foo.c.o",
+			"bar.cc.o": "bar.cc.o",
+		},
+		false,
+	},
+	{
+		"mac",
+		"libsample.a",
+		map[string]string{
+			"foo.c.o": "foo.c.o",
+			"bar.cc.o": "bar.cc.o",
+		},
+		true,
+	},
+	{
+		"windows",
+		"sample.lib",
+		map[string]string{
+			"CMakeFiles\\sample.dir\\foo.c.obj": "foo.c.obj",
+			"CMakeFiles\\sample.dir\\bar.cc.obj": "bar.cc.obj",
+		},
+		false,
+	},
+}
+
+func TestAR(t *testing.T) {
+	for _, test := range arTests {
+		t.Run(test.name, func(t *testing.T) {
+			in, err := os.Open(test.Path(test.in))
+			if err != nil {
+				t.Fatalf("opening input failed: %s", err)
+			}
+			defer in.Close()
+
+			ret, err := ParseAR(in)
+			if err != nil {
+				t.Fatalf("reading input failed: %s", err)
+			}
+
+			for file, contentsPath := range test.out {
+				expected, err := ioutil.ReadFile(test.Path(contentsPath))
+				if err != nil {
+					t.Fatalf("error reading %s: %s", contentsPath, err)
+				}
+				got, ok := ret[file]
+				if test.allowPadding {
+					got = removeTrailingNewlines(got)
+					expected = removeTrailingNewlines(got)
+				}
+				if !ok {
+					t.Errorf("file %s missing from output", file)
+				} else if !bytes.Equal(got, expected) {
+					t.Errorf("contents for file %s did not match", file)
+				}
+			}
+
+			for file, _ := range ret {
+				if _, ok := test.out[file]; !ok {
+					t.Errorf("output contained unexpected file %q", file)
+				}
+			}
+		})
+	}
+}
diff --git a/src/util/ar/testdata/linux/bar.cc.o b/src/util/ar/testdata/linux/bar.cc.o
new file mode 100644
index 0000000..92e83a9
--- /dev/null
+++ b/src/util/ar/testdata/linux/bar.cc.o
Binary files differ
diff --git a/src/util/ar/testdata/linux/foo.c.o b/src/util/ar/testdata/linux/foo.c.o
new file mode 100644
index 0000000..6423c1d
--- /dev/null
+++ b/src/util/ar/testdata/linux/foo.c.o
Binary files differ
diff --git a/src/util/ar/testdata/linux/libsample.a b/src/util/ar/testdata/linux/libsample.a
new file mode 100644
index 0000000..cae6ae7
--- /dev/null
+++ b/src/util/ar/testdata/linux/libsample.a
Binary files differ
diff --git a/src/util/ar/testdata/mac/bar.cc.o b/src/util/ar/testdata/mac/bar.cc.o
new file mode 100644
index 0000000..9c60798
--- /dev/null
+++ b/src/util/ar/testdata/mac/bar.cc.o
Binary files differ
diff --git a/src/util/ar/testdata/mac/foo.c.o b/src/util/ar/testdata/mac/foo.c.o
new file mode 100644
index 0000000..0f96a0a
--- /dev/null
+++ b/src/util/ar/testdata/mac/foo.c.o
Binary files differ
diff --git a/src/util/ar/testdata/mac/libsample.a b/src/util/ar/testdata/mac/libsample.a
new file mode 100644
index 0000000..b7d8eb5
--- /dev/null
+++ b/src/util/ar/testdata/mac/libsample.a
Binary files differ
diff --git a/src/util/ar/testdata/sample/CMakeLists.txt b/src/util/ar/testdata/sample/CMakeLists.txt
new file mode 100644
index 0000000..9ea2fe8
--- /dev/null
+++ b/src/util/ar/testdata/sample/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.0)
+project(Sample)
+add_library(sample STATIC foo.c bar.cc)
diff --git a/src/util/ar/testdata/sample/bar.cc b/src/util/ar/testdata/sample/bar.cc
new file mode 100644
index 0000000..a0ac7e1
--- /dev/null
+++ b/src/util/ar/testdata/sample/bar.cc
@@ -0,0 +1,15 @@
+extern "C" {
+void foo();
+void bar() {}
+}
+
+namespace bar_namespace {
+
+void SomeExternalFunction();
+
+void SomeFunction() {
+  foo();
+  SomeExternalFunction();
+}
+
+}  // namespace bar_namespace
diff --git a/src/util/ar/testdata/sample/foo.c b/src/util/ar/testdata/sample/foo.c
new file mode 100644
index 0000000..fed596c
--- /dev/null
+++ b/src/util/ar/testdata/sample/foo.c
@@ -0,0 +1,7 @@
+extern void external_symbol(void);
+extern void bar(void);
+
+void foo(void) {
+  external_symbol();
+  bar();
+}
diff --git a/src/util/ar/testdata/windows/bar.cc.obj b/src/util/ar/testdata/windows/bar.cc.obj
new file mode 100644
index 0000000..4a315cd
--- /dev/null
+++ b/src/util/ar/testdata/windows/bar.cc.obj
Binary files differ
diff --git a/src/util/ar/testdata/windows/foo.c.obj b/src/util/ar/testdata/windows/foo.c.obj
new file mode 100644
index 0000000..9b4aad7
--- /dev/null
+++ b/src/util/ar/testdata/windows/foo.c.obj
Binary files differ
diff --git a/src/util/ar/testdata/windows/sample.lib b/src/util/ar/testdata/windows/sample.lib
new file mode 100644
index 0000000..efeebb2
--- /dev/null
+++ b/src/util/ar/testdata/windows/sample.lib
Binary files differ
diff --git a/src/util/make_prefix_headers.go b/src/util/make_prefix_headers.go
index a5e5441..b536f14 100644
--- a/src/util/make_prefix_headers.go
+++ b/src/util/make_prefix_headers.go
@@ -172,16 +172,32 @@
 ; OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 ; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+; 32-bit Windows adds underscores to C functions, while 64-bit Windows does not.
+%ifidn __OUTPUT_FORMAT__, win32
 `); err != nil {
 		return err
 	}
 
 	for _, symbol := range symbols {
-		if _, err := fmt.Fprintf(f, "%%define %s BORINGSSL_PREFIX %%+ %s\n", symbol, symbol); err != nil {
+		if _, err := fmt.Fprintf(f, "%%xdefine _%s _ %%+ BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil {
 			return err
 		}
 	}
 
+	if _, err := fmt.Fprintf(f, "%%else\n"); err != nil {
+		return err
+	}
+
+	for _, symbol := range symbols {
+		if _, err := fmt.Fprintf(f, "%%xdefine %s BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil {
+			return err
+		}
+	}
+
+	if _, err := fmt.Fprintf(f, "%%endif\n"); err != nil {
+		return err
+	}
+
 	return nil
 }
 
diff --git a/src/util/read_symbols.go b/src/util/read_symbols.go
index 5e3a177..791ea5d 100644
--- a/src/util/read_symbols.go
+++ b/src/util/read_symbols.go
@@ -12,7 +12,7 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-// read_symbols.go scans one or more .a files and, for each object contained in
+// read_symbols scans one or more .a files and, for each object contained in
 // the .a files, reads the list of symbols in that object file.
 package main
 
@@ -20,6 +20,7 @@
 	"bytes"
 	"debug/elf"
 	"debug/macho"
+	"debug/pe"
 	"flag"
 	"fmt"
 	"os"
@@ -33,10 +34,13 @@
 const (
 	ObjFileFormatELF   = "elf"
 	ObjFileFormatMachO = "macho"
+	ObjFileFormatPE    = "pe"
 )
 
-var outFlag = flag.String("out", "-", "File to write output symbols")
-var objFileFormat = flag.String("obj-file-format", defaultObjFileFormat(runtime.GOOS), "Object file format to expect (options are elf, macho)")
+var (
+	outFlag       = flag.String("out", "-", "File to write output symbols")
+	objFileFormat = flag.String("obj-file-format", defaultObjFileFormat(runtime.GOOS), "Object file format to expect (options are elf, macho, pe)")
+)
 
 func defaultObjFileFormat(goos string) string {
 	switch goos {
@@ -44,6 +48,8 @@
 		return ObjFileFormatELF
 	case "darwin":
 		return ObjFileFormatMachO
+	case "windows":
+		return ObjFileFormatPE
 	default:
 		// By returning a value here rather than panicking, the user can still
 		// cross-compile from an unsupported platform to a supported platform by
@@ -53,11 +59,16 @@
 	}
 }
 
+func printAndExit(format string, args ...interface{}) {
+	s := fmt.Sprintf(format, args...)
+	fmt.Fprintln(os.Stderr, s)
+	os.Exit(1)
+}
+
 func main() {
 	flag.Parse()
 	if flag.NArg() < 1 {
-		fmt.Fprintf(os.Stderr, "Usage: %s [-out OUT] [-obj-file-format FORMAT] ARCHIVE_FILE [ARCHIVE_FILE [...]]\n", os.Args[0])
-		os.Exit(1)
+		printAndExit("Usage: %s [-out OUT] [-obj-file-format FORMAT] ARCHIVE_FILE [ARCHIVE_FILE [...]]", os.Args[0])
 	}
 	archiveFiles := flag.Args()
 
@@ -65,61 +76,109 @@
 	if *outFlag != "-" {
 		var err error
 		out, err = os.Create(*outFlag)
-		nilOrPanic(err, "failed to open output file")
+		if err != nil {
+			printAndExit("Error opening %q: %s", *outFlag, err)
+		}
 		defer out.Close()
 	}
 
 	var symbols []string
 	// Only add first instance of any symbol; keep track of them in this map.
-	added := make(map[string]bool)
+	added := make(map[string]struct{})
 	for _, archive := range archiveFiles {
 		f, err := os.Open(archive)
-		nilOrPanic(err, "failed to open archive file %s", archive)
+		if err != nil {
+			printAndExit("Error opening %s: %s", archive, err)
+		}
 		objectFiles, err := ar.ParseAR(f)
-		nilOrPanic(err, "failed to read archive file %s", archive)
+		f.Close()
+		if err != nil {
+			printAndExit("Error parsing %s: %s", archive, err)
+		}
 
 		for name, contents := range objectFiles {
-			if !strings.HasSuffix(name, ".o") {
-				continue
+			syms, err := listSymbols(contents)
+			if err != nil {
+				printAndExit("Error listing symbols from %q in %q: %s", name, archive, err)
 			}
-			for _, s := range listSymbols(name, contents) {
-				if !added[s] {
-					added[s] = true
+			for _, s := range syms {
+				if _, ok := added[s]; !ok {
+					added[s] = struct{}{}
 					symbols = append(symbols, s)
 				}
 			}
 		}
 	}
+
 	sort.Strings(symbols)
 	for _, s := range symbols {
-		// Filter out C++ mangled names.
-		prefix := "_Z"
-		if runtime.GOOS == "darwin" {
-			prefix = "__Z"
+		var skipSymbols = []string{
+			// Inline functions, etc., from the compiler or language
+			// runtime will naturally end up in the library, to be
+			// deduplicated against other object files. Such symbols
+			// should not be prefixed. It is a limitation of this
+			// symbol-prefixing strategy that we cannot distinguish
+			// our own inline symbols (which should be prefixed)
+			// from the system's (which should not), so we blacklist
+			// known system symbols.
+			"__local_stdio_printf_options",
+			"__local_stdio_scanf_options",
+			"_vscprintf",
+			"_vscprintf_l",
+			"_vsscanf_l",
+			"_xmm",
+			"sscanf",
+			"vsnprintf",
+			// sdallocx is a weak symbol and intended to merge with
+			// the real one, if present.
+			"sdallocx",
 		}
-		if !strings.HasPrefix(s, prefix) {
-			fmt.Fprintln(out, s)
+		var skip bool
+		for _, sym := range skipSymbols {
+			if sym == s {
+				skip = true
+				break
+			}
+		}
+		if skip || isCXXSymbol(s) || strings.HasPrefix(s, "__real@") || strings.HasPrefix(s, "__x86.get_pc_thunk.") {
+			continue
+		}
+		if _, err := fmt.Fprintln(out, s); err != nil {
+			printAndExit("Error writing to %s: %s", *outFlag, err)
 		}
 	}
 }
 
+func isCXXSymbol(s string) bool {
+	if *objFileFormat == ObjFileFormatPE {
+		return strings.HasPrefix(s, "?")
+	}
+	return strings.HasPrefix(s, "_Z")
+}
+
 // listSymbols lists the exported symbols from an object file.
-func listSymbols(name string, contents []byte) []string {
+func listSymbols(contents []byte) ([]string, error) {
 	switch *objFileFormat {
 	case ObjFileFormatELF:
-		return listSymbolsELF(name, contents)
+		return listSymbolsELF(contents)
 	case ObjFileFormatMachO:
-		return listSymbolsMachO(name, contents)
+		return listSymbolsMachO(contents)
+	case ObjFileFormatPE:
+		return listSymbolsPE(contents)
 	default:
-		panic(fmt.Errorf("unsupported object file format %v", *objFileFormat))
+		return nil, fmt.Errorf("unsupported object file format %q", *objFileFormat)
 	}
 }
 
-func listSymbolsELF(name string, contents []byte) []string {
+func listSymbolsELF(contents []byte) ([]string, error) {
 	f, err := elf.NewFile(bytes.NewReader(contents))
-	nilOrPanic(err, "failed to parse ELF file %s", name)
+	if err != nil {
+		return nil, err
+	}
 	syms, err := f.Symbols()
-	nilOrPanic(err, "failed to read symbol names from ELF file %s", name)
+	if err != nil {
+		return nil, err
+	}
 
 	var names []string
 	for _, sym := range syms {
@@ -128,14 +187,16 @@
 			names = append(names, sym.Name)
 		}
 	}
-	return names
+	return names, nil
 }
 
-func listSymbolsMachO(name string, contents []byte) []string {
+func listSymbolsMachO(contents []byte) ([]string, error) {
 	f, err := macho.NewFile(bytes.NewReader(contents))
-	nilOrPanic(err, "failed to parse Mach-O file %s", name)
+	if err != nil {
+		return nil, err
+	}
 	if f.Symtab == nil {
-		return nil
+		return nil, nil
 	}
 	var names []string
 	for _, sym := range f.Symtab.Syms {
@@ -155,16 +216,47 @@
 		// Only include exported, defined symbols.
 		if sym.Type&N_EXT != 0 && sym.Type&N_TYPE != N_UNDF {
 			if len(sym.Name) == 0 || sym.Name[0] != '_' {
-				panic(fmt.Errorf("unexpected symbol without underscore prefix: %v", sym.Name))
+				return nil, fmt.Errorf("unexpected symbol without underscore prefix: %q", sym.Name)
 			}
 			names = append(names, sym.Name[1:])
 		}
 	}
-	return names
+	return names, nil
 }
 
-func nilOrPanic(err error, f string, args ...interface{}) {
+func listSymbolsPE(contents []byte) ([]string, error) {
+	f, err := pe.NewFile(bytes.NewReader(contents))
 	if err != nil {
-		panic(fmt.Errorf(f+": %v", append(args, err)...))
+		return nil, err
 	}
+	var ret []string
+	for _, sym := range f.Symbols {
+		const (
+			// https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#section-number-values
+			IMAGE_SYM_UNDEFINED = 0
+			// https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#storage-class
+			IMAGE_SYM_CLASS_EXTERNAL = 2
+		)
+		if sym.SectionNumber != IMAGE_SYM_UNDEFINED && sym.StorageClass == IMAGE_SYM_CLASS_EXTERNAL {
+			name := sym.Name
+			if f.Machine == pe.IMAGE_FILE_MACHINE_I386 {
+				// On 32-bit Windows, C symbols are decorated by calling
+				// convention.
+				// https://msdn.microsoft.com/en-us/library/56h2zst2.aspx#FormatC
+				if strings.HasPrefix(name, "_") || strings.HasPrefix(name, "@") {
+					// __cdecl, __stdcall, or __fastcall. Remove the prefix and
+					// suffix, if present.
+					name = name[1:]
+					if idx := strings.LastIndex(name, "@"); idx >= 0 {
+						name = name[:idx]
+					}
+				} else if idx := strings.LastIndex(name, "@@"); idx >= 0 {
+					// __vectorcall. Remove the suffix.
+					name = name[:idx]
+				}
+			}
+			ret = append(ret, name)
+		}
+	}
+	return ret, nil
 }
diff --git a/win-x86/crypto/chacha/chacha-x86.asm b/win-x86/crypto/chacha/chacha-x86.asm
index 639a3cb..7b59adf 100644
--- a/win-x86/crypto/chacha/chacha-x86.asm
+++ b/win-x86/crypto/chacha/chacha-x86.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/aes-586.asm b/win-x86/crypto/fipsmodule/aes-586.asm
index 80e4826..c3a47d8 100644
--- a/win-x86/crypto/fipsmodule/aes-586.asm
+++ b/win-x86/crypto/fipsmodule/aes-586.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/aesni-x86.asm b/win-x86/crypto/fipsmodule/aesni-x86.asm
index 9ed8932..602d0b4 100644
--- a/win-x86/crypto/fipsmodule/aesni-x86.asm
+++ b/win-x86/crypto/fipsmodule/aesni-x86.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
@@ -18,10 +21,10 @@
 section	.text	code
 %endif
 ;extern	_OPENSSL_ia32cap_P
-global	_aesni_encrypt
+global	_aes_hw_encrypt
 align	16
-_aesni_encrypt:
-L$_aesni_encrypt_begin:
+_aes_hw_encrypt:
+L$_aes_hw_encrypt_begin:
 	mov	eax,DWORD [4+esp]
 	mov	edx,DWORD [12+esp]
 	movups	xmm2,[eax]
@@ -43,10 +46,10 @@
 	movups	[eax],xmm2
 	pxor	xmm2,xmm2
 	ret
-global	_aesni_decrypt
+global	_aes_hw_decrypt
 align	16
-_aesni_decrypt:
-L$_aesni_decrypt_begin:
+_aes_hw_decrypt:
+L$_aes_hw_decrypt_begin:
 	mov	eax,DWORD [4+esp]
 	mov	edx,DWORD [12+esp]
 	movups	xmm2,[eax]
@@ -354,10 +357,10 @@
 db	102,15,56,223,240
 db	102,15,56,223,248
 	ret
-global	_aesni_ecb_encrypt
+global	_aes_hw_ecb_encrypt
 align	16
-_aesni_ecb_encrypt:
-L$_aesni_ecb_encrypt_begin:
+_aes_hw_ecb_encrypt:
+L$_aes_hw_ecb_encrypt_begin:
 	push	ebp
 	push	ebx
 	push	esi
@@ -587,10 +590,10 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_aesni_ccm64_encrypt_blocks
+global	_aes_hw_ccm64_encrypt_blocks
 align	16
-_aesni_ccm64_encrypt_blocks:
-L$_aesni_ccm64_encrypt_blocks_begin:
+_aes_hw_ccm64_encrypt_blocks:
+L$_aes_hw_ccm64_encrypt_blocks_begin:
 	push	ebp
 	push	ebx
 	push	esi
@@ -673,10 +676,10 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_aesni_ccm64_decrypt_blocks
+global	_aes_hw_ccm64_decrypt_blocks
 align	16
-_aesni_ccm64_decrypt_blocks:
-L$_aesni_ccm64_decrypt_blocks_begin:
+_aes_hw_ccm64_decrypt_blocks:
+L$_aes_hw_ccm64_decrypt_blocks_begin:
 	push	ebp
 	push	ebx
 	push	esi
@@ -794,10 +797,10 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_aesni_ctr32_encrypt_blocks
+global	_aes_hw_ctr32_encrypt_blocks
 align	16
-_aesni_ctr32_encrypt_blocks:
-L$_aesni_ctr32_encrypt_blocks_begin:
+_aes_hw_ctr32_encrypt_blocks:
+L$_aes_hw_ctr32_encrypt_blocks_begin:
 	push	ebp
 	push	ebx
 	push	esi
@@ -1030,10 +1033,10 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_aesni_xts_encrypt
+global	_aes_hw_xts_encrypt
 align	16
-_aesni_xts_encrypt:
-L$_aesni_xts_encrypt_begin:
+_aes_hw_xts_encrypt:
+L$_aes_hw_xts_encrypt_begin:
 	push	ebp
 	push	ebx
 	push	esi
@@ -1388,10 +1391,10 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_aesni_xts_decrypt
+global	_aes_hw_xts_decrypt
 align	16
-_aesni_xts_decrypt:
-L$_aesni_xts_decrypt_begin:
+_aes_hw_xts_decrypt:
+L$_aes_hw_xts_decrypt_begin:
 	push	ebp
 	push	ebx
 	push	esi
@@ -1776,10 +1779,10 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_aesni_cbc_encrypt
+global	_aes_hw_cbc_encrypt
 align	16
-_aesni_cbc_encrypt:
-L$_aesni_cbc_encrypt_begin:
+_aes_hw_cbc_encrypt:
+L$_aes_hw_cbc_encrypt_begin:
 	push	ebp
 	push	ebx
 	push	esi
@@ -2366,19 +2369,19 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_aesni_set_encrypt_key
+global	_aes_hw_set_encrypt_key
 align	16
-_aesni_set_encrypt_key:
-L$_aesni_set_encrypt_key_begin:
+_aes_hw_set_encrypt_key:
+L$_aes_hw_set_encrypt_key_begin:
 	mov	eax,DWORD [4+esp]
 	mov	ecx,DWORD [8+esp]
 	mov	edx,DWORD [12+esp]
 	call	__aesni_set_encrypt_key
 	ret
-global	_aesni_set_decrypt_key
+global	_aes_hw_set_decrypt_key
 align	16
-_aesni_set_decrypt_key:
-L$_aesni_set_decrypt_key_begin:
+_aes_hw_set_decrypt_key:
+L$_aes_hw_set_decrypt_key_begin:
 	mov	eax,DWORD [4+esp]
 	mov	ecx,DWORD [8+esp]
 	mov	edx,DWORD [12+esp]
diff --git a/win-x86/crypto/fipsmodule/bn-586.asm b/win-x86/crypto/fipsmodule/bn-586.asm
index 20c3ddf..a87f86d 100644
--- a/win-x86/crypto/fipsmodule/bn-586.asm
+++ b/win-x86/crypto/fipsmodule/bn-586.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/co-586.asm b/win-x86/crypto/fipsmodule/co-586.asm
index 0f89d1b..b6784bf 100644
--- a/win-x86/crypto/fipsmodule/co-586.asm
+++ b/win-x86/crypto/fipsmodule/co-586.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/ghash-x86.asm b/win-x86/crypto/fipsmodule/ghash-x86.asm
index faa7344..753c472 100644
--- a/win-x86/crypto/fipsmodule/ghash-x86.asm
+++ b/win-x86/crypto/fipsmodule/ghash-x86.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/md5-586.asm b/win-x86/crypto/fipsmodule/md5-586.asm
index 9060060..c051923 100644
--- a/win-x86/crypto/fipsmodule/md5-586.asm
+++ b/win-x86/crypto/fipsmodule/md5-586.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/sha1-586.asm b/win-x86/crypto/fipsmodule/sha1-586.asm
index 7888ea2..0afe894 100644
--- a/win-x86/crypto/fipsmodule/sha1-586.asm
+++ b/win-x86/crypto/fipsmodule/sha1-586.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/sha256-586.asm b/win-x86/crypto/fipsmodule/sha256-586.asm
index e48cb0d..b5dc26b 100644
--- a/win-x86/crypto/fipsmodule/sha256-586.asm
+++ b/win-x86/crypto/fipsmodule/sha256-586.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/sha512-586.asm b/win-x86/crypto/fipsmodule/sha512-586.asm
index a6acc55..3e6b068 100644
--- a/win-x86/crypto/fipsmodule/sha512-586.asm
+++ b/win-x86/crypto/fipsmodule/sha512-586.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/vpaes-x86.asm b/win-x86/crypto/fipsmodule/vpaes-x86.asm
index e3e4238..5f1dce4 100644
--- a/win-x86/crypto/fipsmodule/vpaes-x86.asm
+++ b/win-x86/crypto/fipsmodule/vpaes-x86.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32
diff --git a/win-x86/crypto/fipsmodule/x86-mont.asm b/win-x86/crypto/fipsmodule/x86-mont.asm
index f8800c6..6a15ed9 100644
--- a/win-x86/crypto/fipsmodule/x86-mont.asm
+++ b/win-x86/crypto/fipsmodule/x86-mont.asm
@@ -1,6 +1,9 @@
 ; This file is generated from a similarly-named Perl script in the BoringSSL
 ; source tree. Do not edit by hand.
 
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
 %ifidn __OUTPUT_FORMAT__,obj
 section	code	use32 class=code align=64
 %elifidn __OUTPUT_FORMAT__,win32