[dump_breakpad_symbols] Drop symbolize pkg usage.
These APIs are deprecated in favor of using elflib.ReadIdsFile
to read IDs files.
TC-168
Change-Id: I85d5bb7df077b39229df32cd0fa94442790efaed
diff --git a/cmd/dump_breakpad_symbols/main.go b/cmd/dump_breakpad_symbols/main.go
index d54a0da..8026f72 100755
--- a/cmd/dump_breakpad_symbols/main.go
+++ b/cmd/dump_breakpad_symbols/main.go
@@ -5,6 +5,7 @@
package main
import (
+ "fuchsia.googlesource.com/tools/elflib"
// TODO(kjharland): Use a safer hash algorithm. sha256 or sha2, etc.
"crypto/sha1"
"encoding/hex"
@@ -18,8 +19,6 @@
"path"
"path/filepath"
"strings"
-
- "fuchsia.googlesource.com/tools/symbolize"
)
const usage = `usage: dump_breakpad_symbols [options] file1 file2 ... fileN
@@ -101,12 +100,6 @@
}
defer summaryFile.Close()
- // Create a symbolize.Source from each IDs file.
- var IDsFiles []symbolize.BinaryFileSource
- for _, path := range flag.Args() {
- IDsFiles = append(IDsFiles, symbolize.NewIDsSource(path))
- }
-
// Callback to run breakpad `dump_syms` command.
execDumpSyms := func(args []string) ([]byte, error) {
return exec.Command(dumpSymsPath, args...).Output()
@@ -117,8 +110,22 @@
return os.Create(path)
}
+ // Open the input files for reading. In practice there are very few files,
+ // so it's fine to open them all at once.
+ var inputReaders []io.Reader
+ inputPaths := flag.Args()
+ for _, path := range inputPaths {
+ file, err := os.Open(path)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "ERROR: Failed to open %s: %v\n", path, err)
+ os.Exit(1)
+ }
+ defer file.Close()
+ inputReaders = append(inputReaders, file)
+ }
+
// Process the IDsFiles.
- summary := processIdsFiles(IDsFiles, outdir, execDumpSyms, createFile)
+ summary := processIdsFiles(inputReaders, outdir, execDumpSyms, createFile)
// Write the summary.
if err := writeSummary(summaryFile, summary); err != nil {
@@ -126,14 +133,14 @@
os.Exit(1)
}
// Write the dep file.
- if err := writeDepFile(depFile, summaryFilename, IDsFiles); err != nil {
+ if err := writeDepFile(depFile, summaryFilename, inputPaths); err != nil {
fmt.Fprintf(os.Stderr, "failed to write depfile %s: %v", depFilename, err)
os.Exit(1)
}
}
// processIdsFiles dumps symbol data for each executable in a set of ids files.
-func processIdsFiles(idsFiles []symbolize.BinaryFileSource, outdir string, execDumpSyms ExecDumpSyms, createFile CreateFile) map[string]string {
+func processIdsFiles(idsFiles []io.Reader, outdir string, execDumpSyms ExecDumpSyms, createFile CreateFile) map[string]string {
// Binary paths we've already seen. Duplicates are skipped.
visited := make(map[string]bool)
binaryToSymbolFile := make(map[string]string)
@@ -141,12 +148,13 @@
// Iterate through the given set of filepaths.
for _, idsFile := range idsFiles {
// Extract the paths to each binary from the IDs file.
- binaries, err := idsFile.GetBinaries()
+ binaries, err := elflib.ReadIDsFile(idsFile)
if err != nil {
- log.Printf("ERROR: failed to extract paths from %s: %v", idsFile, err)
+ fmt.Fprintln(os.Stderr, err)
continue
}
+ // Generate the symbol file for each binary.
for _, bin := range binaries {
binaryPath := bin.Filepath
@@ -213,19 +221,10 @@
//
// summaryPath is the summary file generated by this command.
// IDsFiles are the input sources to this command.
-func writeDepFile(w io.Writer, summaryFilename string, IDsFiles []symbolize.BinaryFileSource) error {
- // Write the dep file.
- var idsFileNames []string
- for _, f := range IDsFiles {
- idsFileNames = append(idsFileNames, f.Name())
- }
-
- contents := []byte(fmt.Sprintf("%s: %s\n", summaryFilename, strings.Join(idsFileNames, " ")))
- if _, err := w.Write(contents); err != nil {
- return err
- }
-
- return nil
+func writeDepFile(w io.Writer, summaryFilename string, IDsFiles []string) error {
+ contents := []byte(fmt.Sprintf("%s: %s\n", summaryFilename, strings.Join(IDsFiles, " ")))
+ _, err := w.Write(contents)
+ return err
}
// Writes the given symbol file data to the given writer after massaging the data.
diff --git a/cmd/dump_breakpad_symbols/main_test.go b/cmd/dump_breakpad_symbols/main_test.go
index 3ab9003..15d7cf3 100644
--- a/cmd/dump_breakpad_symbols/main_test.go
+++ b/cmd/dump_breakpad_symbols/main_test.go
@@ -9,58 +9,69 @@
"fmt"
"io"
"io/ioutil"
+ "strings"
"testing"
-
- "fuchsia.googlesource.com/tools/elflib"
- "fuchsia.googlesource.com/tools/symbolize"
)
-// TestReadWriteCloser helps mimic io.ReadWriteCloser for file-like objects during tests.
-type TestReadWriteCloser struct {
+// FakeFile is a file-like io.ReadWriteCloser for testing.
+type FakeFile struct {
+ path string
*bytes.Buffer
}
+// The filepath of this FakeFile.
+func (f *FakeFile) Name() string {
+ return f.path
+}
+
// Close implements io.WriteCloser
-func (wc *TestReadWriteCloser) Close() error {
+func (f *FakeFile) Close() error {
// Noop
return nil
}
-func NewTestReadWriteCloser() io.ReadWriteCloser {
- return &TestReadWriteCloser{
- new(bytes.Buffer),
+func NewFakeFile(path string, contents string) *FakeFile {
+ return &FakeFile{
+ Buffer: bytes.NewBuffer([]byte(contents)),
+ path: path,
}
}
func TestRunCommand(t *testing.T) {
// Expects dump_breakpad_symbols to produce the specified summary and
// ninja depfile from the given input sources.
- expectOutputs := func(inputSources []symbolize.BinaryFileSource, expectedSummary string, expectedDepFile string) {
- // The dep file to write.
- depFile := NewTestReadWriteCloser()
-
- // The summary file to write.
- summaryFile := NewTestReadWriteCloser()
+ expectOutputs := func(t *testing.T, inputs []*FakeFile, expectedSummary string, expectedDepFile string) {
+ depFile := NewFakeFile("deps.d", "")
+ summaryFile := NewFakeFile("summary.json", "")
// Callback to mock executing the breakpad dump_syms binary.
execDumpSyms := func(args []string) ([]byte, error) {
return []byte("FAKE_SYMBOL_DATA_LINE_1\nFAKE_SYMBOL_DATA_LINE_2"), nil
}
- // Mock file I/O.
+ // Callback to perform file I/O.
createFile := func(path string) (io.ReadWriteCloser, error) {
- return NewTestReadWriteCloser(), nil
+ return NewFakeFile(path, ""), nil
}
- // Do what main() does...
-
- // Process the IDsFiles.
- summary := processIdsFiles(inputSources, "/out/", execDumpSyms, createFile)
- summaryFilename := "summary.json"
+ // Convert input files from `[]FakeFile` to `[]io.Reader`
+ fileReaders := make([]io.Reader, len(inputs))
+ for i := range inputs {
+ fileReaders[i] = inputs[i]
+ }
+ // Process the input files.
+ summary := processIdsFiles(fileReaders, "/out/", execDumpSyms, createFile)
if err := writeSummary(summaryFile, summary); err != nil {
- t.Fatalf("failed to write summary %s: %v", summaryFilename, err)
+ t.Fatalf("failed to write summary %s: %v", summaryFile.Name(), err)
}
- if err := writeDepFile(depFile, summaryFilename, inputSources); err != nil {
+
+ // Extract input filepaths.
+ inputPaths := make([]string, len(inputs))
+ for i := range inputs {
+ inputPaths[i] = inputs[i].Name()
+ }
+ // Write the dep file
+ if err := writeDepFile(depFile, summaryFile.Name(), inputPaths); err != nil {
t.Fatalf("failed to write depfile %s: %v", depFilename, err)
}
@@ -84,50 +95,49 @@
}
t.Run("should produce an emtpy summary if no data is provided", func(t *testing.T) {
- inputSources := []symbolize.BinaryFileSource{
- symbolize.NewMockSource("idsA.txt", []elflib.BinaryFileRef{}),
- symbolize.NewMockSource("idsB.txt", []elflib.BinaryFileRef{}),
+ inputSources := []*FakeFile{
+ NewFakeFile("idsA.txt", ""),
+ NewFakeFile("idsB.txt", ""),
}
expectedSummary := "{}"
expectedDepFile := fmt.Sprintf("summary.json: %s %s\n", "idsA.txt", "idsB.txt")
-
- expectOutputs(inputSources, expectedSummary, expectedDepFile)
+ expectOutputs(t, inputSources, expectedSummary, expectedDepFile)
})
t.Run("should handle a single input file", func(t *testing.T) {
// Create a testing input file with fake hash values and binary paths.
- inputSources := []symbolize.BinaryFileSource{
- symbolize.NewMockSource("ids.txt", []elflib.BinaryFileRef{
- {BuildID: "01634b09", Filepath: "/path/to/binaryA.elf"},
- {BuildID: "02298167", Filepath: "/path/to/binaryB"},
- {BuildID: "025abbbc", Filepath: "/path/to/binaryC.so"},
- }),
+ inputSources := []*FakeFile{
+ NewFakeFile("ids.txt", strings.TrimSpace(`
+ 01634b09 /path/to/binaryA.elf
+ 02298167 /path/to/binaryB
+ 025abbbc /path/to/binaryC.so
+ `)),
}
expectedSummary, err := json.MarshalIndent(map[string]string{
"/path/to/binaryA.elf": "/out/fe9881defb9ed1ddb9a89c38be973515f6ad7f0f.sym",
"/path/to/binaryB": "/out/f03de72df78157dd14ae1cc031ddba9873947179.sym",
"/path/to/binaryC.so": "/out/edbe4e45241c98dcde3538160073a0d6b097b780.sym",
}, "", " ")
+
if err != nil {
t.Fatal(err)
}
expectedDepFile := "summary.json: ids.txt\n"
-
- expectOutputs(inputSources, string(expectedSummary), expectedDepFile)
+ expectOutputs(t, inputSources, string(expectedSummary), expectedDepFile)
})
t.Run("should handle multiple input files", func(t *testing.T) {
- inputSources := []symbolize.BinaryFileSource{
- symbolize.NewMockSource("idsA.txt", []elflib.BinaryFileRef{
- {BuildID: "01634b09", Filepath: "/path/to/binaryA.elf"},
- {BuildID: "02298167", Filepath: "/path/to/binaryB"},
- {BuildID: "025abbbc", Filepath: "/path/to/binaryC.so"},
- }),
- symbolize.NewMockSource("idsB.txt", []elflib.BinaryFileRef{
- {BuildID: "01634b09", Filepath: "/path/to/binaryD"},
- {BuildID: "02298167", Filepath: "/path/to/binaryE"},
- {BuildID: "025abbbc", Filepath: "/path/to/binaryF"},
- }),
+ inputSources := []*FakeFile{
+ NewFakeFile("idsA.txt", strings.TrimSpace(`
+ 01634b09 /path/to/binaryA.elf
+ 02298167 /path/to/binaryB
+ 025abbbc /path/to/binaryC.so
+ `)),
+ NewFakeFile("idsB.txt", strings.TrimSpace(`
+ 01634b09 /path/to/binaryD
+ 02298167 /path/to/binaryE
+ 025abbbc /path/to/binaryF
+ `)),
}
expectedSummary, err := json.MarshalIndent(map[string]string{
"/path/to/binaryA.elf": "/out/fe9881defb9ed1ddb9a89c38be973515f6ad7f0f.sym",
@@ -142,26 +152,26 @@
}
expectedDepFile := "summary.json: idsA.txt idsB.txt\n"
- expectOutputs(inputSources, string(expectedSummary), expectedDepFile)
+ expectOutputs(t, inputSources, string(expectedSummary), expectedDepFile)
})
t.Run("should skip duplicate binary paths", func(t *testing.T) {
- inputSources := []symbolize.BinaryFileSource{
- symbolize.NewMockSource("idsA.txt", []elflib.BinaryFileRef{
- {BuildID: "01634b09", Filepath: "/path/to/binaryA"},
- {BuildID: "02298167", Filepath: "/path/to/binaryB"},
- {BuildID: "asdf87fs", Filepath: "/path/to/binaryC"},
- }),
- symbolize.NewMockSource("idsB.txt", []elflib.BinaryFileRef{
- {BuildID: "01634b09", Filepath: "/path/to/binaryA"},
- {BuildID: "02298167", Filepath: "/path/to/binaryB"},
- {BuildID: "asdf87fs", Filepath: "/path/to/binaryC"},
- }),
- symbolize.NewMockSource("idsC.txt", []elflib.BinaryFileRef{
- {BuildID: "01634b09", Filepath: "/path/to/binaryA"},
- {BuildID: "02298167", Filepath: "/path/to/binaryB"},
- {BuildID: "asdf87fs", Filepath: "/path/to/binaryC"},
- }),
+ inputSources := []*FakeFile{
+ NewFakeFile("idsA.txt", strings.TrimSpace(`
+ 01634b09 /path/to/binaryA
+ 02298167 /path/to/binaryB
+ asdf87fs /path/to/binaryC
+ `)),
+ NewFakeFile("idsB.txt", strings.TrimSpace(`
+ 01634b09 /path/to/binaryA
+ 02298167 /path/to/binaryB
+ asdf87fs /path/to/binaryC
+ `)),
+ NewFakeFile("idsC.txt", strings.TrimSpace(`
+ 01634b09 /path/to/binaryA
+ 02298167 /path/to/binaryB
+ asdf87fs /path/to/binaryC
+ `)),
}
expectedSummary, err := json.MarshalIndent(map[string]string{
"/path/to/binaryA": "/out/43e5a3c9eb9829f2eb11007223de1fb0b721a909.sym",
@@ -173,7 +183,7 @@
}
expectedDepFile := "summary.json: idsA.txt idsB.txt idsC.txt\n"
- expectOutputs(inputSources, string(expectedSummary), expectedDepFile)
+ expectOutputs(t, inputSources, string(expectedSummary), expectedDepFile)
})
}