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/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
 }