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
}