4 * Copyright (C) 2017-2018 "IoT.bzh"
5 * Author Sebastien Douheret <sebastien@iot.bzh>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
31 "github.com/Sirupsen/logrus"
35 // GdbNative - Implementation of IGDB used to interfacing native gdb
36 type GdbNative struct {
46 cbOnDisconnect func(error)
47 cbRead func(timestamp, stdout, stderr string)
48 cbInferiorRead func(timestamp, stdout, stderr string)
49 cbOnExit func(code int, err error)
54 // NewGdbNative creates a new instance of GdbNative
55 func NewGdbNative(log *logrus.Logger, args []string, env []string) *GdbNative {
64 // SetConfig set additional config fields
65 func (g *GdbNative) SetConfig(name string, value interface{}) error {
66 return fmt.Errorf("Unknown %s field", name)
69 // Init initializes gdb XDS
70 func (g *GdbNative) Init() (int, error) {
72 // Create the exec command
73 g.exeCmd = exec.Command(g.ccmd, g.aargs...)
78 // Close frees allocated objects and close opened connections
79 func (g *GdbNative) Close() error {
80 g.cbOnDisconnect = nil
83 g.cbInferiorRead = nil
90 // Start sends a request to start remotely gdb within xds-server
91 func (g *GdbNative) Start(inferiorTTY bool) (int, error) {
94 // Start pty and consequently gdb process
95 if g.fdPty, err = pty.Start(g.exeCmd); err != nil {
96 return int(syscall.ESPIPE), err
101 // Monitor gdb process EOF
103 // Execute command and wait EOF
104 err := g.exeCmd.Wait()
105 g.cbOnDisconnect(err)
111 sc := bufio.NewScanner(g.fdPty)
115 g.cbRead(time.Now().String(), sc.Text(), "")
126 // Cmd returns the command name
127 func (g *GdbNative) Cmd() string {
131 // Args returns the list of arguments
132 func (g *GdbNative) Args() []string {
136 // Env returns the list of environment variables
137 func (g *GdbNative) Env() []string {
141 // OnError doesn't make sens
142 func (g *GdbNative) OnError(f func(error)) {
146 // OnDisconnect is called when stdin is disconnected
147 func (g *GdbNative) OnDisconnect(f func(error)) {
151 // OnExit calls when exit event is received
152 func (g *GdbNative) OnExit(f func(code int, err error)) {
156 // Read calls when a message/string event is received on stdout or stderr
157 func (g *GdbNative) Read(f func(timestamp, stdout, stderr string)) {
161 // InferiorRead calls when a message/string event is received on stdout or stderr of the debugged program (IOW inferior)
162 func (g *GdbNative) InferiorRead(f func(timestamp, stdout, stderr string)) {
166 // Write writes message/string into gdb stdin
167 func (g *GdbNative) Write(args ...interface{}) error {
168 s := fmt.Sprint(args...)
169 _, err := g.fdPty.Write([]byte(s))
173 // SendSignal is used to send a signal to remote process/gdb
174 func (g *GdbNative) SendSignal(sig os.Signal) error {
176 return fmt.Errorf("exeCmd not initialized")
178 return g.exeCmd.Process.Signal(sig)
181 //***** Private functions *****
183 func split(data []byte, atEOF bool) (advance int, token []byte, err error) {
184 if atEOF && len(data) == 0 {
187 return len(data), data, nil