-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmain.go
173 lines (146 loc) · 3.86 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package main
import (
"bufio"
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
"github.com/ilmari-h/dlvtui/nav"
"github.com/go-delve/delve/service/rpc2"
"github.com/rivo/tview"
log "github.com/sirupsen/logrus"
)
func execDebuggerCmd(executable string, exArgs []string, port string) []string {
log.Printf("Debugging executable at path: %s", executable)
allArgs := []string{
"exec",
"--headless",
"--accept-multiclient",
"--api-version=2",
"--listen=127.0.0.1:" + port,
executable,
}
if exArgs != nil && len(exArgs) > 0 {
allArgs = append(allArgs, "--")
allArgs = append(allArgs, exArgs...)
}
return allArgs
}
func attachDebuggerCmd(pid string, exArgs []string, port string) []string {
log.Printf("Debugging process with PID: %s", pid)
allArgs := []string{
"attach",
"--headless",
"--accept-multiclient",
"--api-version=2",
"--listen=127.0.0.1:" + port,
pid,
}
if exArgs != nil && len(exArgs) > 0 {
allArgs = append(allArgs, "--")
allArgs = append(allArgs, exArgs...)
}
return allArgs
}
func startDebugger(commandArgs []string) int {
log.Printf("Starting dlv-backend: dlv %s", strings.Join(commandArgs, " "))
cmd := exec.Command(
"dlv",
commandArgs...,
)
cmd.SysProcAttr = &syscall.SysProcAttr{
Pdeathsig: syscall.SIGKILL,
}
stdout, _ := cmd.StdoutPipe()
if err := cmd.Start(); err != nil {
log.Printf("Error starting dlv-backend: %s", string(err.Error()))
panic(err)
}
log.Printf("dlv-backend running with pid %d", cmd.Process.Pid)
go func() {
in := bufio.NewScanner(stdout)
for in.Scan() {
log.Printf("dlv-backend:%s", in.Text())
}
if err := in.Err(); err != nil {
log.Printf("Error: %s", err)
}
}()
return cmd.Process.Pid
}
// Used for autosuggestions for now, a browser window in the future.
func getFileList(client *rpc2.RPCClient) chan []string {
filesListC := make(chan []string)
go func() {
files, err := client.ListSources("")
if err != nil {
log.Fatalf("Error tracing directory: %s", err)
}
filesListC <- files
}()
return filesListC
}
var (
port string
logfile string
attachMode bool
)
func init() {
// Parse flags after first argument.
exFlags := flag.NewFlagSet("", flag.ExitOnError)
exFlags.StringVar(&port, "port", "8181", "The port dlv rpc server will listen to.")
exFlags.BoolVar(&attachMode, "attach", false, "If enabled, attach debugger to process. Interpret first argument as PID.")
exFlags.StringVar(&logfile, "logfile", "$XDG_DATA_HOME/dlvtui.log", "Path to the log file.")
if len(os.Args) < 2 {
fmt.Println("No debug target provided.\n" +
"The first argument should be an executable or a PID if the flag `attach` is set.")
exFlags.Usage()
os.Exit(1)
return
}
exFlags.Parse(os.Args[2:])
log.SetLevel(log.InfoLevel)
file, err := os.OpenFile(os.ExpandEnv(logfile), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
file.Truncate(0)
if err == nil {
log.SetOutput(file)
} else {
log.Fatal("Failed to log to file: " + err.Error())
}
}
func main() {
getConfig()
target := os.Args[1]
clientC := make(chan *rpc2.RPCClient)
if attachMode {
startDebugger(attachDebuggerCmd(target, []string{}, port))
} else {
targetFile, _ := filepath.Abs(target)
startDebugger(execDebuggerCmd(targetFile, []string{}, port))
}
go NewClient("127.0.0.1:"+port, clientC)
rpcClient := <-clientC
fileList := <-getFileList(rpcClient)
if fileList == nil || len(fileList) == 0 {
log.Fatalf("Error: empty source list.")
}
// Resolve dir. For now just find by assuming it's the one prefixed by /home.
var dir string
for _, f := range fileList {
if strings.HasPrefix(f, "/home/") && !strings.Contains(f, "/go/pkg") {
dir = filepath.Dir(f)
break
}
}
log.Printf("Using dir: %s", dir)
app := tview.NewApplication()
nav := nav.NewNav(dir)
nav.SourceFiles = fileList
CreateTui(app, &nav, rpcClient)
if err := app.Run(); err != nil {
panic(err)
}
}