// Copyright 2019 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 generator

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sync"

	"go.fuchsia.dev/fuchsia/tools/debug/breakpad"
	"go.fuchsia.dev/fuchsia/tools/debug/elflib"
)

// The default module name for modules that don't have a soname, e.g., executables and
// loadable modules. This allows us to use the same module name at runtime as sonames are
// the only names that are guaranteed to be available at build and run times. This value
// must be kept in sync with what Crashpad uses at run time for symbol resolution to work
// properly.
const defaultModuleName = "<_>"

// The module OS used to overwrite existing OS values in generated symbol files, even if
// they're already set to something else.
const replacementModuleOS = "Fuchsia"

// Generate generates breakpad symbol data for each of the input elflib.BinaryFileRefs.
// Returns the path to a directory containing the generated files, or the empty string if
// an error occurred.
func Generate(bfrs []elflib.BinaryFileRef, dumpSymsPath string) (path string, err error) {
	outc := make(chan string)
	errc := make(chan error)
	defer close(outc)
	defer close(errc)

	g := &generator{
		dumpSymsPath: dumpSymsPath,
		visited:      make(map[string]struct{}),
		visitedMutex: &sync.Mutex{},
	}

	jobs := make(chan elflib.BinaryFileRef)
	go g.run(jobs, outc, errc)
	for _, bfr := range bfrs {
		jobs <- bfr
	}
	close(jobs)

	select {
	case err = <-errc:
		return "", err
	case path = <-outc:
		return path, nil
	}
}

// Generator is a helper class for executing Breakpad's dump_syms tool.
//
// The run method is meant to be executed as a go-routine. It will manage its own working
// directory, and publish the path to that directory only on success.
//
// The run method is threadsafe, and will skip files that have already been processed.
type generator struct {
	// The path to the Breakpad dump_syms executable.
	dumpSymsPath string

	// Filepaths that have already been processed by this generator.
	visited      map[string]struct{}
	visitedMutex *sync.Mutex
}

// Run executes this generator on the given channel of elflib.BinarFileRefs.
//
// A temp directory is created to store generated files. On success, the directory is
// emitted on out. On the first encountered error, the generator will emit the error on
// errs, delete the output directory, and exit.
func (g *generator) run(in <-chan elflib.BinaryFileRef, out chan<- string, errs chan<- error) {
	outdir, err := ioutil.TempDir("", "breakpad")
	if err != nil {
		errs <- err
		return
	}
	if err := g.generate(in, outdir); err != nil {
		errs <- err
		os.RemoveAll(outdir)
		return
	}
	out <- outdir
}

func (g *generator) generate(in <-chan elflib.BinaryFileRef, outdir string) error {
	for bfr := range in {
		if !g.markVisited(bfr.Filepath) {
			continue
		}
		sf, err := g.genFromBinaryFileRef(bfr)
		if err != nil {
			return err
		}
		fd, err := os.Create(filepath.Join(outdir, fmt.Sprintf("%s.sym", bfr.BuildID)))
		if err != nil {
			return err
		}
		defer fd.Close()
		if _, err := sf.WriteTo(fd); err != nil {
			return err
		}
	}
	return nil
}

func (g *generator) genFromBinaryFileRef(bfr elflib.BinaryFileRef) (*breakpad.SymbolFile, error) {
	log.Printf("generating symbols for %q", bfr.Filepath)
	sf, err := g.genSymbolFile(bfr)
	if err != nil {
		return nil, err
	}
	sf.ModuleSection.OS = replacementModuleOS
	sf.ModuleSection.ModuleName = defaultModuleName
	soname, err := g.readSoName(bfr.Filepath)
	if err == nil && soname != "" {
		sf.ModuleSection.ModuleName = soname
	}
	return sf, nil
}

func (g *generator) genSymbolFile(bfr elflib.BinaryFileRef) (*breakpad.SymbolFile, error) {
	var stdout bytes.Buffer
	cmd := exec.Cmd{
		Path:   g.dumpSymsPath,
		Args:   []string{g.dumpSymsPath, bfr.Filepath},
		Stdout: &stdout,
	}
	if err := cmd.Run(); err != nil {
		return nil, fmt.Errorf("command failed %v: %w", cmd.Args, err)
	}
	return breakpad.ParseSymbolFile(&stdout)
}

func (g *generator) readSoName(path string) (string, error) {
	fd, err := os.Open(path)
	if err != nil {
		return "", fmt.Errorf("open failed %q: %w", path, err)
	}
	defer fd.Close()
	return elflib.GetSoName(path, fd)
}

// Marks that path has been visited and returs true iff this generator has not alread
// visited path. Otherwise returns false.
func (g *generator) markVisited(path string) (succeeded bool) {
	g.visitedMutex.Lock()
	defer g.visitedMutex.Unlock()
	if _, ok := g.visited[path]; ok {
		return false
	}
	g.visited[path] = struct{}{}
	return true
}
