delve/cmd/dlv/main.go

175 lines
3.6 KiB
Go
Raw Normal View History

2014-05-20 21:29:01 +00:00
package main
import (
"flag"
2014-05-20 21:29:01 +00:00
"fmt"
"net"
2014-05-20 21:29:01 +00:00
"os"
"os/exec"
"os/signal"
"path/filepath"
"strconv"
2014-05-20 21:29:01 +00:00
2015-05-08 22:26:09 +00:00
sys "golang.org/x/sys/unix"
2015-06-21 03:47:44 +00:00
"github.com/derekparker/delve/service"
"github.com/derekparker/delve/service/rpc"
"github.com/derekparker/delve/terminal"
2014-05-20 21:29:01 +00:00
)
const version string = "0.5.0.beta"
2014-11-10 12:53:33 +00:00
2015-04-25 14:49:12 +00:00
var usage string = `Delve version %s
2015-03-09 02:26:45 +00:00
flags:
2015-04-25 14:49:12 +00:00
%s
2015-03-09 02:26:45 +00:00
Invoke with the path to a binary:
2015-03-09 03:01:14 +00:00
dlv ./path/to/prog
2015-03-09 02:26:45 +00:00
or use the following commands:
run - Build, run, and attach to program
test - Build test binary, run and attach to it
2015-03-09 02:26:45 +00:00
attach - Attach to running process
2015-04-25 14:49:12 +00:00
`
2015-03-09 02:26:45 +00:00
2014-11-23 16:22:04 +00:00
func init() {
2015-04-25 14:49:12 +00:00
flag.Usage = help
2014-11-23 16:22:04 +00:00
}
2014-11-23 16:22:04 +00:00
func main() {
2015-04-25 14:49:12 +00:00
var printv, printhelp bool
var addr string
var logEnabled bool
var headless bool
2015-03-09 02:26:45 +00:00
flag.BoolVar(&printv, "version", false, "Print version number and exit.")
flag.StringVar(&addr, "addr", "localhost:0", "Debugging server listen address.")
flag.BoolVar(&logEnabled, "log", false, "Enable debugging server logging.")
flag.BoolVar(&headless, "headless", false, "Run in headless mode.")
flag.Parse()
2014-05-20 23:11:00 +00:00
if flag.NFlag() == 0 && len(flag.Args()) == 0 {
2015-04-25 14:49:12 +00:00
help()
os.Exit(0)
2014-05-20 23:11:00 +00:00
}
2014-11-10 12:53:33 +00:00
if printv {
fmt.Printf("Delve version: %s\n", version)
os.Exit(0)
}
2015-04-25 14:49:12 +00:00
if printhelp {
help()
os.Exit(0)
}
defer func() {
if err := recover(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}()
status := run(addr, logEnabled, headless)
2015-06-13 23:16:09 +00:00
fmt.Println("[Hope I was of service hunting your bug!]")
os.Exit(status)
}
func run(addr string, logEnabled, headless bool) int {
// Collect launch arguments
var processArgs []string
var attachPid int
switch flag.Args()[0] {
case "run":
const debugname = "debug"
cmd := exec.Command("go", "build", "-o", debugname, "-gcflags", "-N -l")
err := cmd.Run()
if err != nil {
2015-06-13 23:16:09 +00:00
fmt.Println("Could not compile program:", err)
return 1
}
2015-06-13 23:16:09 +00:00
fp, err := filepath.Abs("./" + debugname)
if err != nil {
fmt.Println(err)
return 1
}
defer os.Remove(fp)
processArgs = append([]string{"./" + debugname}, flag.Args()[1:]...)
case "test":
wd, err := os.Getwd()
if err != nil {
fmt.Println(err)
2015-06-13 23:16:09 +00:00
return 1
}
base := filepath.Base(wd)
cmd := exec.Command("go", "test", "-c", "-gcflags", "-N -l")
err = cmd.Run()
if err != nil {
fmt.Errorf("Could not compile program: %s\n", err)
2015-06-13 23:16:09 +00:00
return 1
}
debugname := "./" + base + ".test"
defer os.Remove(debugname)
processArgs = append([]string{debugname}, flag.Args()[1:]...)
case "attach":
pid, err := strconv.Atoi(flag.Args()[1])
if err != nil {
fmt.Errorf("Invalid pid: %d", flag.Args()[1])
2015-06-13 23:16:09 +00:00
return 1
}
attachPid = pid
default:
processArgs = flag.Args()
}
// Make a TCP listener
listener, err := net.Listen("tcp", addr)
if err != nil {
fmt.Printf("couldn't start listener: %s\n", err)
2015-06-13 23:16:09 +00:00
return 1
}
defer listener.Close()
2015-06-21 03:47:44 +00:00
// Create and start a debugger server
var server service.Server
server = rpc.NewServer(&service.Config{
Listener: listener,
ProcessArgs: processArgs,
AttachPid: attachPid,
}, logEnabled)
if err := server.Run(); err != nil {
fmt.Fprintln(os.Stderr, err)
return 1
}
2015-06-13 23:16:09 +00:00
var status int
if !headless {
// Create and start a terminal
2015-06-21 03:47:44 +00:00
var client service.Client
client = rpc.NewClient(listener.Addr().String())
term := terminal.New(client)
err, status = term.Run()
} else {
ch := make(chan os.Signal)
signal.Notify(ch, sys.SIGINT)
<-ch
err = server.Stop(true)
}
if err != nil {
fmt.Println(err)
}
2015-06-13 23:16:09 +00:00
return status
2014-05-20 21:29:01 +00:00
}
2015-04-25 14:49:12 +00:00
// help prints help text to os.Stderr.
func help() {
flags := ""
flag.VisitAll(func(f *flag.Flag) {
doc := fmt.Sprintf(" -%s=%s: %s\n", f.Name, f.DefValue, f.Usage)
flags += doc
})
fmt.Fprintf(os.Stderr, usage, version, flags)
}