blob: fe713046a77db508918bc78991da3e0a17c820fb [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package main
import (
// TODO(kjharland): change crypto/sha1 to a safer hash algorithm. sha256 or sha2, etc.
"archive/tar"
"compress/gzip"
"context"
"flag"
"fmt"
"log"
"os"
"fuchsia.googlesource.com/tools/breakpad/generator"
"fuchsia.googlesource.com/tools/elflib"
"fuchsia.googlesource.com/tools/tarutil"
)
const usage = `usage: dump_breakpad_symbols [options] paths...
Generates breakpad symbol files by running dump_syms on a collection of binaries. Produces
a tar archive containing all generated files. Expects a list of paths to .build-id dirs as
input.
Example invocation:
$ dump_breakpad_symbols -dump-syms-path=dump_syms -tar-file=out.tar.gz -depfile=dep.out ./.build-ids
`
// Command line flag values
var (
depFilepath string
dumpSymsPath string
tarFilepath string
)
func init() {
flag.Usage = func() {
fmt.Fprint(os.Stderr, usage)
flag.PrintDefaults()
os.Exit(0)
}
var unused string
flag.StringVar(&unused, "out-dir", "", "DEPRECATED. This is not used")
flag.StringVar(&dumpSymsPath, "dump-syms-path", "", "Path to the breakpad tools `dump_syms` executable")
flag.StringVar(&depFilepath, "depfile", "", "Path to the ninja depfile to generate")
flag.StringVar(&tarFilepath, "tar-file", "", "Path where the tar archive containing symbol files is written")
}
func main() {
flag.Parse()
if err := execute(context.Background(), flag.Args()...); err != nil {
log.Fatal(err)
}
}
func execute(ctx context.Context, dirs ...string) error {
// Collect all binary file refs from each directory
var bfrs []elflib.BinaryFileRef
for _, dir := range dirs {
newbfrs, err := elflib.WalkBuildIDDir(dir)
if err != nil {
return err
}
bfrs = append(bfrs, newbfrs...)
}
// Generate all symbol files.
path, err := generator.Generate(bfrs, dumpSymsPath)
if err != nil {
log.Fatalf("failed to generate symbols: %v", err)
}
// Write all files to the specified tar archive.
tarfd, err := os.Create(tarFilepath)
if err != nil {
return fmt.Errorf("failed to create %q: %v", tarFilepath, err)
}
gzw := gzip.NewWriter(tarfd)
defer gzw.Close()
tw := tar.NewWriter(gzw)
defer tw.Close()
log.Printf("archiving %q to %q", path, tarFilepath)
if err := tarutil.TarDirectory(tw, path); err != nil {
return fmt.Errorf("failed to write %q: %v", tarFilepath, err)
}
// Write the Ninja dep file.
depfile := depfile{outputPath: tarFilepath, inputPaths: dirs}
depfd, err := os.Create(depFilepath)
if err != nil {
return fmt.Errorf("failed to create %q: %v", depFilepath, err)
}
n, err := depfile.WriteTo(depfd)
if err != nil {
return fmt.Errorf("failed to write %q: %v", depFilepath, err)
}
if n == 0 {
return fmt.Errorf("wrote 0 bytes to %q", depFilepath)
}
return nil
}