Make read_symbols.go a bit more idiomatic. It's more verbose, but trimming the panics should make it easier to move to a library (e.g. a symbol checker) or unit test later. Change-Id: Iab37eff2689955e58057528be092d6dd5d8d26bc Reviewed-on: https://boringssl-review.googlesource.com/c/33344 Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/util/read_symbols.go b/util/read_symbols.go index 5e3a177..e9a8eae 100644 --- a/util/read_symbols.go +++ b/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 @@ -35,8 +35,10 @@ ObjFileFormatMachO = "macho" ) -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)") +) func defaultObjFileFormat(goos string) string { switch goos { @@ -53,11 +55,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,26 +72,37 @@ 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 } - for _, s := range listSymbols(name, contents) { - if !added[s] { - added[s] = true + syms, err := listSymbols(contents) + if err != nil { + printAndExit("Error listing symbols from %q in %q: %s", name, archive, err) + } + for _, s := range syms { + if _, ok := added[s]; !ok { + added[s] = struct{}{} symbols = append(symbols, s) } } @@ -98,28 +116,34 @@ prefix = "__Z" } if !strings.HasPrefix(s, prefix) { - fmt.Fprintln(out, s) + if _, err := fmt.Fprintln(out, s); err != nil { + printAndExit("Error writing to %s: %s", *outFlag, err) + } } } } // 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) 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 +152,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 +181,10 @@ // 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 -} - -func nilOrPanic(err error, f string, args ...interface{}) { - if err != nil { - panic(fmt.Errorf(f+": %v", append(args, err)...)) - } + return names, nil }