mirror of
https://github.com/beego/bee.git
synced 2024-11-25 20:10:55 +00:00
Update vendor folder (support for Delve RPC)
This commit is contained in:
parent
427541fcd9
commit
ad641afb34
25
vendor/github.com/derekparker/delve/pkg/version/version.go
generated
vendored
Normal file
25
vendor/github.com/derekparker/delve/pkg/version/version.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Version represents the current version of Delve.
|
||||||
|
type Version struct {
|
||||||
|
Major string
|
||||||
|
Minor string
|
||||||
|
Patch string
|
||||||
|
Metadata string
|
||||||
|
Build string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DelveVersion is the current version of Delve.
|
||||||
|
DelveVersion = Version{Major: "0", Minor: "12", Patch: "1", Metadata: ""}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v Version) String() string {
|
||||||
|
ver := fmt.Sprintf("Version: %s.%s.%s", v.Major, v.Minor, v.Patch)
|
||||||
|
if v.Metadata != "" {
|
||||||
|
ver += "-" + v.Metadata
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s\nBuild: %s", ver, v.Build)
|
||||||
|
}
|
312
vendor/github.com/derekparker/delve/service/rpc1/client.go
generated
vendored
Normal file
312
vendor/github.com/derekparker/delve/service/rpc1/client.go
generated
vendored
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
package rpc1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/rpc"
|
||||||
|
"net/rpc/jsonrpc"
|
||||||
|
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/derekparker/delve/service/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client is a RPC service.Client.
|
||||||
|
type RPCClient struct {
|
||||||
|
addr string
|
||||||
|
processPid int
|
||||||
|
client *rpc.Client
|
||||||
|
haltMu sync.Mutex
|
||||||
|
haltReq bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var unsupportedApiError = errors.New("unsupported")
|
||||||
|
|
||||||
|
// NewClient creates a new RPCClient.
|
||||||
|
func NewClient(addr string) *RPCClient {
|
||||||
|
client, err := jsonrpc.Dial("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("dialing:", err)
|
||||||
|
}
|
||||||
|
return &RPCClient{
|
||||||
|
addr: addr,
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ProcessPid() int {
|
||||||
|
var pid int
|
||||||
|
c.call("ProcessPid", nil, &pid)
|
||||||
|
return pid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) Detach(kill bool) error {
|
||||||
|
return c.call("Detach", kill, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) Restart() error {
|
||||||
|
return c.call("Restart", nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) GetState() (*api.DebuggerState, error) {
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
err := c.call("State", nil, state)
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) Continue() <-chan *api.DebuggerState {
|
||||||
|
ch := make(chan *api.DebuggerState)
|
||||||
|
c.haltMu.Lock()
|
||||||
|
c.haltReq = false
|
||||||
|
c.haltMu.Unlock()
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
c.haltMu.Lock()
|
||||||
|
if c.haltReq {
|
||||||
|
c.haltMu.Unlock()
|
||||||
|
close(ch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.haltMu.Unlock()
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
err := c.call("Command", &api.DebuggerCommand{Name: api.Continue}, state)
|
||||||
|
if err != nil {
|
||||||
|
state.Err = err
|
||||||
|
}
|
||||||
|
if state.Exited {
|
||||||
|
// Error types apparently cannot be marshalled by Go correctly. Must reset error here.
|
||||||
|
state.Err = fmt.Errorf("Process %d has exited with status %d", c.ProcessPid(), state.ExitStatus)
|
||||||
|
}
|
||||||
|
ch <- state
|
||||||
|
if err != nil || state.Exited {
|
||||||
|
close(ch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isbreakpoint := false
|
||||||
|
istracepoint := true
|
||||||
|
for i := range state.Threads {
|
||||||
|
if state.Threads[i].Breakpoint != nil {
|
||||||
|
isbreakpoint = true
|
||||||
|
istracepoint = istracepoint && state.Threads[i].Breakpoint.Tracepoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isbreakpoint || !istracepoint {
|
||||||
|
close(ch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) Next() (*api.DebuggerState, error) {
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
err := c.call("Command", &api.DebuggerCommand{Name: api.Next}, state)
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) Step() (*api.DebuggerState, error) {
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
err := c.call("Command", &api.DebuggerCommand{Name: api.Step}, state)
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) StepInstruction() (*api.DebuggerState, error) {
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
err := c.call("Command", &api.DebuggerCommand{Name: api.StepInstruction}, state)
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) SwitchThread(threadID int) (*api.DebuggerState, error) {
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
cmd := &api.DebuggerCommand{
|
||||||
|
Name: api.SwitchThread,
|
||||||
|
ThreadID: threadID,
|
||||||
|
}
|
||||||
|
err := c.call("Command", cmd, state)
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) SwitchGoroutine(goroutineID int) (*api.DebuggerState, error) {
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
cmd := &api.DebuggerCommand{
|
||||||
|
Name: api.SwitchGoroutine,
|
||||||
|
GoroutineID: goroutineID,
|
||||||
|
}
|
||||||
|
err := c.call("Command", cmd, state)
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) Halt() (*api.DebuggerState, error) {
|
||||||
|
state := new(api.DebuggerState)
|
||||||
|
c.haltMu.Lock()
|
||||||
|
c.haltReq = true
|
||||||
|
c.haltMu.Unlock()
|
||||||
|
err := c.call("Command", &api.DebuggerCommand{Name: api.Halt}, state)
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) GetBreakpoint(id int) (*api.Breakpoint, error) {
|
||||||
|
breakpoint := new(api.Breakpoint)
|
||||||
|
err := c.call("GetBreakpoint", id, breakpoint)
|
||||||
|
return breakpoint, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) GetBreakpointByName(name string) (*api.Breakpoint, error) {
|
||||||
|
breakpoint := new(api.Breakpoint)
|
||||||
|
err := c.call("GetBreakpointByName", name, breakpoint)
|
||||||
|
return breakpoint, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) {
|
||||||
|
newBreakpoint := new(api.Breakpoint)
|
||||||
|
err := c.call("CreateBreakpoint", breakPoint, &newBreakpoint)
|
||||||
|
return newBreakpoint, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListBreakpoints() ([]*api.Breakpoint, error) {
|
||||||
|
var breakpoints []*api.Breakpoint
|
||||||
|
err := c.call("ListBreakpoints", nil, &breakpoints)
|
||||||
|
return breakpoints, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ClearBreakpoint(id int) (*api.Breakpoint, error) {
|
||||||
|
bp := new(api.Breakpoint)
|
||||||
|
err := c.call("ClearBreakpoint", id, bp)
|
||||||
|
return bp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ClearBreakpointByName(name string) (*api.Breakpoint, error) {
|
||||||
|
bp := new(api.Breakpoint)
|
||||||
|
err := c.call("ClearBreakpointByName", name, bp)
|
||||||
|
return bp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) AmendBreakpoint(bp *api.Breakpoint) error {
|
||||||
|
err := c.call("AmendBreakpoint", bp, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) CancelNext() error {
|
||||||
|
return unsupportedApiError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListThreads() ([]*api.Thread, error) {
|
||||||
|
var threads []*api.Thread
|
||||||
|
err := c.call("ListThreads", nil, &threads)
|
||||||
|
return threads, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) GetThread(id int) (*api.Thread, error) {
|
||||||
|
thread := new(api.Thread)
|
||||||
|
err := c.call("GetThread", id, &thread)
|
||||||
|
return thread, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) EvalVariable(scope api.EvalScope, symbol string) (*api.Variable, error) {
|
||||||
|
v := new(api.Variable)
|
||||||
|
err := c.call("EvalSymbol", EvalSymbolArgs{scope, symbol}, v)
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) SetVariable(scope api.EvalScope, symbol, value string) error {
|
||||||
|
var unused int
|
||||||
|
return c.call("SetSymbol", SetSymbolArgs{scope, symbol, value}, &unused)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListSources(filter string) ([]string, error) {
|
||||||
|
var sources []string
|
||||||
|
err := c.call("ListSources", filter, &sources)
|
||||||
|
return sources, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListFunctions(filter string) ([]string, error) {
|
||||||
|
var funcs []string
|
||||||
|
err := c.call("ListFunctions", filter, &funcs)
|
||||||
|
return funcs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListTypes(filter string) ([]string, error) {
|
||||||
|
var types []string
|
||||||
|
err := c.call("ListTypes", filter, &types)
|
||||||
|
return types, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListPackageVariables(filter string) ([]api.Variable, error) {
|
||||||
|
var vars []api.Variable
|
||||||
|
err := c.call("ListPackageVars", filter, &vars)
|
||||||
|
return vars, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListPackageVariablesFor(threadID int, filter string) ([]api.Variable, error) {
|
||||||
|
var vars []api.Variable
|
||||||
|
err := c.call("ListThreadPackageVars", &ThreadListArgs{Id: threadID, Filter: filter}, &vars)
|
||||||
|
return vars, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListLocalVariables(scope api.EvalScope) ([]api.Variable, error) {
|
||||||
|
var vars []api.Variable
|
||||||
|
err := c.call("ListLocalVars", scope, &vars)
|
||||||
|
return vars, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListRegisters() (string, error) {
|
||||||
|
var regs string
|
||||||
|
err := c.call("ListRegisters", nil, ®s)
|
||||||
|
return regs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListFunctionArgs(scope api.EvalScope) ([]api.Variable, error) {
|
||||||
|
var vars []api.Variable
|
||||||
|
err := c.call("ListFunctionArgs", scope, &vars)
|
||||||
|
return vars, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) ListGoroutines() ([]*api.Goroutine, error) {
|
||||||
|
var goroutines []*api.Goroutine
|
||||||
|
err := c.call("ListGoroutines", nil, &goroutines)
|
||||||
|
return goroutines, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) Stacktrace(goroutineId, depth int, full bool) ([]api.Stackframe, error) {
|
||||||
|
var locations []api.Stackframe
|
||||||
|
err := c.call("StacktraceGoroutine", &StacktraceGoroutineArgs{Id: goroutineId, Depth: depth, Full: full}, &locations)
|
||||||
|
return locations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) AttachedToExistingProcess() bool {
|
||||||
|
var answer bool
|
||||||
|
c.call("AttachedToExistingProcess", nil, &answer)
|
||||||
|
return answer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) FindLocation(scope api.EvalScope, loc string) ([]api.Location, error) {
|
||||||
|
var answer []api.Location
|
||||||
|
err := c.call("FindLocation", FindLocationArgs{scope, loc}, &answer)
|
||||||
|
return answer, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disassemble code between startPC and endPC
|
||||||
|
func (c *RPCClient) DisassembleRange(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
|
||||||
|
var r api.AsmInstructions
|
||||||
|
err := c.call("Disassemble", DisassembleRequest{scope, startPC, endPC, flavour}, &r)
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disassemble function containing pc
|
||||||
|
func (c *RPCClient) DisassemblePC(scope api.EvalScope, pc uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
|
||||||
|
var r api.AsmInstructions
|
||||||
|
err := c.call("Disassemble", DisassembleRequest{scope, pc, 0, flavour}, &r)
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) url(path string) string {
|
||||||
|
return fmt.Sprintf("http://%s%s", c.addr, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCClient) call(method string, args, reply interface{}) error {
|
||||||
|
return c.client.Call("RPCServer."+method, args, reply)
|
||||||
|
}
|
5
vendor/github.com/derekparker/delve/service/rpc1/readme.txtr
generated
vendored
Normal file
5
vendor/github.com/derekparker/delve/service/rpc1/readme.txtr
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
This package implements version 1 of Delve's API and is only
|
||||||
|
kept here for backwards compatibility. Client.go is the old
|
||||||
|
client code used by Delve's frontend (delve/cmd/dlv), it is
|
||||||
|
only preserved here for the backwards compatibility tests in
|
||||||
|
service/test/integration1_test.go.
|
318
vendor/github.com/derekparker/delve/service/rpc1/server.go
generated
vendored
Normal file
318
vendor/github.com/derekparker/delve/service/rpc1/server.go
generated
vendored
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
package rpc1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/derekparker/delve/pkg/proc"
|
||||||
|
"github.com/derekparker/delve/service"
|
||||||
|
"github.com/derekparker/delve/service/api"
|
||||||
|
"github.com/derekparker/delve/service/debugger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultLoadConfig = proc.LoadConfig{true, 1, 64, 64, -1}
|
||||||
|
|
||||||
|
type RPCServer struct {
|
||||||
|
// config is all the information necessary to start the debugger and server.
|
||||||
|
config *service.Config
|
||||||
|
// debugger is a debugger service.
|
||||||
|
debugger *debugger.Debugger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(config *service.Config, debugger *debugger.Debugger) *RPCServer {
|
||||||
|
return &RPCServer{config, debugger}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ProcessPid(arg1 interface{}, pid *int) error {
|
||||||
|
*pid = s.debugger.ProcessPid()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) Detach(kill bool, ret *int) error {
|
||||||
|
return s.debugger.Detach(kill)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) Restart(arg1 interface{}, arg2 *int) error {
|
||||||
|
if s.config.AttachPid != 0 {
|
||||||
|
return errors.New("cannot restart process Delve did not create")
|
||||||
|
}
|
||||||
|
_, err := s.debugger.Restart()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) State(arg interface{}, state *api.DebuggerState) error {
|
||||||
|
st, err := s.debugger.State()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*state = *st
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) Command(command *api.DebuggerCommand, cb service.RPCCallback) {
|
||||||
|
st, err := s.debugger.Command(command)
|
||||||
|
cb.Return(st, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) GetBreakpoint(id int, breakpoint *api.Breakpoint) error {
|
||||||
|
bp := s.debugger.FindBreakpoint(id)
|
||||||
|
if bp == nil {
|
||||||
|
return fmt.Errorf("no breakpoint with id %d", id)
|
||||||
|
}
|
||||||
|
*breakpoint = *bp
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) GetBreakpointByName(name string, breakpoint *api.Breakpoint) error {
|
||||||
|
bp := s.debugger.FindBreakpointByName(name)
|
||||||
|
if bp == nil {
|
||||||
|
return fmt.Errorf("no breakpoint with name %s", name)
|
||||||
|
}
|
||||||
|
*breakpoint = *bp
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StacktraceGoroutineArgs struct {
|
||||||
|
Id int
|
||||||
|
Depth int
|
||||||
|
Full bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) StacktraceGoroutine(args *StacktraceGoroutineArgs, locations *[]api.Stackframe) error {
|
||||||
|
var loadcfg *proc.LoadConfig = nil
|
||||||
|
if args.Full {
|
||||||
|
loadcfg = &defaultLoadConfig
|
||||||
|
}
|
||||||
|
locs, err := s.debugger.Stacktrace(args.Id, args.Depth, loadcfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*locations = locs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListBreakpoints(arg interface{}, breakpoints *[]*api.Breakpoint) error {
|
||||||
|
*breakpoints = s.debugger.Breakpoints()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) CreateBreakpoint(bp, newBreakpoint *api.Breakpoint) error {
|
||||||
|
createdbp, err := s.debugger.CreateBreakpoint(bp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*newBreakpoint = *createdbp
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ClearBreakpoint(id int, breakpoint *api.Breakpoint) error {
|
||||||
|
bp := s.debugger.FindBreakpoint(id)
|
||||||
|
if bp == nil {
|
||||||
|
return fmt.Errorf("no breakpoint with id %d", id)
|
||||||
|
}
|
||||||
|
deleted, err := s.debugger.ClearBreakpoint(bp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*breakpoint = *deleted
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ClearBreakpointByName(name string, breakpoint *api.Breakpoint) error {
|
||||||
|
bp := s.debugger.FindBreakpointByName(name)
|
||||||
|
if bp == nil {
|
||||||
|
return fmt.Errorf("no breakpoint with name %s", name)
|
||||||
|
}
|
||||||
|
deleted, err := s.debugger.ClearBreakpoint(bp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*breakpoint = *deleted
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) AmendBreakpoint(amend *api.Breakpoint, unused *int) error {
|
||||||
|
*unused = 0
|
||||||
|
return s.debugger.AmendBreakpoint(amend)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListThreads(arg interface{}, threads *[]*api.Thread) (err error) {
|
||||||
|
*threads, err = s.debugger.Threads()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) GetThread(id int, thread *api.Thread) error {
|
||||||
|
t, err := s.debugger.FindThread(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if t == nil {
|
||||||
|
return fmt.Errorf("no thread with id %d", id)
|
||||||
|
}
|
||||||
|
*thread = *t
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListPackageVars(filter string, variables *[]api.Variable) error {
|
||||||
|
state, err := s.debugger.State()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
current := state.CurrentThread
|
||||||
|
if current == nil {
|
||||||
|
return fmt.Errorf("no current thread")
|
||||||
|
}
|
||||||
|
|
||||||
|
vars, err := s.debugger.PackageVariables(current.ID, filter, defaultLoadConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*variables = vars
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThreadListArgs struct {
|
||||||
|
Id int
|
||||||
|
Filter string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListThreadPackageVars(args *ThreadListArgs, variables *[]api.Variable) error {
|
||||||
|
thread, err := s.debugger.FindThread(args.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if thread == nil {
|
||||||
|
return fmt.Errorf("no thread with id %d", args.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
vars, err := s.debugger.PackageVariables(args.Id, args.Filter, defaultLoadConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*variables = vars
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListRegisters(arg interface{}, registers *string) error {
|
||||||
|
state, err := s.debugger.State()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
regs, err := s.debugger.Registers(state.CurrentThread.ID, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*registers = regs.String()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListLocalVars(scope api.EvalScope, variables *[]api.Variable) error {
|
||||||
|
vars, err := s.debugger.LocalVariables(scope, defaultLoadConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*variables = vars
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListFunctionArgs(scope api.EvalScope, variables *[]api.Variable) error {
|
||||||
|
vars, err := s.debugger.FunctionArguments(scope, defaultLoadConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*variables = vars
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type EvalSymbolArgs struct {
|
||||||
|
Scope api.EvalScope
|
||||||
|
Symbol string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) EvalSymbol(args EvalSymbolArgs, variable *api.Variable) error {
|
||||||
|
v, err := s.debugger.EvalVariableInScope(args.Scope, args.Symbol, defaultLoadConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*variable = *v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetSymbolArgs struct {
|
||||||
|
Scope api.EvalScope
|
||||||
|
Symbol string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) SetSymbol(args SetSymbolArgs, unused *int) error {
|
||||||
|
*unused = 0
|
||||||
|
return s.debugger.SetVariableInScope(args.Scope, args.Symbol, args.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListSources(filter string, sources *[]string) error {
|
||||||
|
ss, err := s.debugger.Sources(filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*sources = ss
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListFunctions(filter string, funcs *[]string) error {
|
||||||
|
fns, err := s.debugger.Functions(filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*funcs = fns
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListTypes(filter string, types *[]string) error {
|
||||||
|
tps, err := s.debugger.Types(filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*types = tps
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) ListGoroutines(arg interface{}, goroutines *[]*api.Goroutine) error {
|
||||||
|
gs, err := s.debugger.Goroutines()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*goroutines = gs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCServer) AttachedToExistingProcess(arg interface{}, answer *bool) error {
|
||||||
|
if c.config.AttachPid != 0 {
|
||||||
|
*answer = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindLocationArgs struct {
|
||||||
|
Scope api.EvalScope
|
||||||
|
Loc string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCServer) FindLocation(args FindLocationArgs, answer *[]api.Location) error {
|
||||||
|
var err error
|
||||||
|
*answer, err = c.debugger.FindLocation(args.Scope, args.Loc)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisassembleRequest struct {
|
||||||
|
Scope api.EvalScope
|
||||||
|
StartPC, EndPC uint64
|
||||||
|
Flavour api.AssemblyFlavour
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RPCServer) Disassemble(args DisassembleRequest, answer *api.AsmInstructions) error {
|
||||||
|
var err error
|
||||||
|
*answer, err = c.debugger.Disassemble(args.Scope, args.StartPC, args.EndPC, args.Flavour)
|
||||||
|
return err
|
||||||
|
}
|
409
vendor/github.com/derekparker/delve/service/rpccommon/server.go
generated
vendored
Normal file
409
vendor/github.com/derekparker/delve/service/rpccommon/server.go
generated
vendored
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
package rpccommon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/rpc"
|
||||||
|
"net/rpc/jsonrpc"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/derekparker/delve/pkg/version"
|
||||||
|
"github.com/derekparker/delve/service"
|
||||||
|
"github.com/derekparker/delve/service/api"
|
||||||
|
"github.com/derekparker/delve/service/debugger"
|
||||||
|
"github.com/derekparker/delve/service/rpc1"
|
||||||
|
"github.com/derekparker/delve/service/rpc2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServerImpl implements a JSON-RPC server that can switch between two
|
||||||
|
// versions of the API.
|
||||||
|
type ServerImpl struct {
|
||||||
|
// config is all the information necessary to start the debugger and server.
|
||||||
|
config *service.Config
|
||||||
|
// listener is used to serve HTTP.
|
||||||
|
listener net.Listener
|
||||||
|
// stopChan is used to stop the listener goroutine.
|
||||||
|
stopChan chan struct{}
|
||||||
|
// debugger is the debugger service.
|
||||||
|
debugger *debugger.Debugger
|
||||||
|
// s1 is APIv1 server.
|
||||||
|
s1 *rpc1.RPCServer
|
||||||
|
// s2 is APIv2 server.
|
||||||
|
s2 *rpc2.RPCServer
|
||||||
|
// maps of served methods, one for each supported API.
|
||||||
|
methodMaps []map[string]*methodType
|
||||||
|
}
|
||||||
|
|
||||||
|
type RPCCallback struct {
|
||||||
|
s *ServerImpl
|
||||||
|
sending *sync.Mutex
|
||||||
|
codec rpc.ServerCodec
|
||||||
|
req rpc.Request
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCServer implements the RPC method calls common to all versions of the API.
|
||||||
|
type RPCServer struct {
|
||||||
|
s *ServerImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
type methodType struct {
|
||||||
|
method reflect.Method
|
||||||
|
Rcvr reflect.Value
|
||||||
|
ArgType reflect.Type
|
||||||
|
ReplyType reflect.Type
|
||||||
|
Synchronous bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer creates a new RPCServer.
|
||||||
|
func NewServer(config *service.Config, logEnabled bool) *ServerImpl {
|
||||||
|
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||||
|
if !logEnabled {
|
||||||
|
log.SetOutput(ioutil.Discard)
|
||||||
|
}
|
||||||
|
if config.APIVersion < 2 {
|
||||||
|
log.Printf("Using API v1")
|
||||||
|
}
|
||||||
|
return &ServerImpl{
|
||||||
|
config: config,
|
||||||
|
listener: config.Listener,
|
||||||
|
stopChan: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops the JSON-RPC server.
|
||||||
|
func (s *ServerImpl) Stop(kill bool) error {
|
||||||
|
if s.config.AcceptMulti {
|
||||||
|
close(s.stopChan)
|
||||||
|
s.listener.Close()
|
||||||
|
}
|
||||||
|
return s.debugger.Detach(kill)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restart restarts the debugger.
|
||||||
|
func (s *ServerImpl) Restart() error {
|
||||||
|
if s.config.AttachPid != 0 {
|
||||||
|
return errors.New("cannot restart process Delve did not create")
|
||||||
|
}
|
||||||
|
return s.s2.Restart(rpc2.RestartIn{}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run starts a debugger and exposes it with an HTTP server. The debugger
|
||||||
|
// itself can be stopped with the `detach` API. Run blocks until the HTTP
|
||||||
|
// server stops.
|
||||||
|
func (s *ServerImpl) Run() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if s.config.APIVersion < 2 {
|
||||||
|
s.config.APIVersion = 1
|
||||||
|
}
|
||||||
|
if s.config.APIVersion > 2 {
|
||||||
|
return fmt.Errorf("unknown API version")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and start the debugger
|
||||||
|
if s.debugger, err = debugger.New(&debugger.Config{
|
||||||
|
ProcessArgs: s.config.ProcessArgs,
|
||||||
|
AttachPid: s.config.AttachPid,
|
||||||
|
WorkingDir: s.config.WorkingDir,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.s1 = rpc1.NewServer(s.config, s.debugger)
|
||||||
|
s.s2 = rpc2.NewServer(s.config, s.debugger)
|
||||||
|
|
||||||
|
rpcServer := &RPCServer{s}
|
||||||
|
|
||||||
|
s.methodMaps = make([]map[string]*methodType, 2)
|
||||||
|
|
||||||
|
s.methodMaps[0] = map[string]*methodType{}
|
||||||
|
s.methodMaps[1] = map[string]*methodType{}
|
||||||
|
suitableMethods(s.s1, s.methodMaps[0])
|
||||||
|
suitableMethods(rpcServer, s.methodMaps[0])
|
||||||
|
suitableMethods(s.s2, s.methodMaps[1])
|
||||||
|
suitableMethods(rpcServer, s.methodMaps[1])
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer s.listener.Close()
|
||||||
|
for {
|
||||||
|
c, err := s.listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
select {
|
||||||
|
case <-s.stopChan:
|
||||||
|
// We were supposed to exit, do nothing and return
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go s.serveJSONCodec(c)
|
||||||
|
if !s.config.AcceptMulti {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precompute the reflect type for error. Can't use error directly
|
||||||
|
// because Typeof takes an empty interface value. This is annoying.
|
||||||
|
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
|
||||||
|
|
||||||
|
// Is this an exported - upper case - name?
|
||||||
|
func isExported(name string) bool {
|
||||||
|
rune, _ := utf8.DecodeRuneInString(name)
|
||||||
|
return unicode.IsUpper(rune)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this type exported or a builtin?
|
||||||
|
func isExportedOrBuiltinType(t reflect.Type) bool {
|
||||||
|
for t.Kind() == reflect.Ptr {
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
// PkgPath will be non-empty even for an exported type,
|
||||||
|
// so we need to check the type name as well.
|
||||||
|
return isExported(t.Name()) || t.PkgPath() == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fills methods map with the methods of receiver that should be made
|
||||||
|
// available through the RPC interface.
|
||||||
|
// These are all the public methods of rcvr that have one of those
|
||||||
|
// two signatures:
|
||||||
|
// func (rcvr ReceiverType) Method(in InputType, out *ReplyType) error
|
||||||
|
// func (rcvr ReceiverType) Method(in InputType, cb service.RPCCallback)
|
||||||
|
func suitableMethods(rcvr interface{}, methods map[string]*methodType) {
|
||||||
|
typ := reflect.TypeOf(rcvr)
|
||||||
|
rcvrv := reflect.ValueOf(rcvr)
|
||||||
|
sname := reflect.Indirect(rcvrv).Type().Name()
|
||||||
|
if sname == "" {
|
||||||
|
log.Printf("rpc.Register: no service name for type %s", typ)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for m := 0; m < typ.NumMethod(); m++ {
|
||||||
|
method := typ.Method(m)
|
||||||
|
mname := method.Name
|
||||||
|
mtype := method.Type
|
||||||
|
// method must be exported
|
||||||
|
if method.PkgPath != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Method needs three ins: (receive, *args, *reply) or (receiver, *args, *RPCCallback)
|
||||||
|
if mtype.NumIn() != 3 {
|
||||||
|
log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// First arg need not be a pointer.
|
||||||
|
argType := mtype.In(1)
|
||||||
|
if !isExportedOrBuiltinType(argType) {
|
||||||
|
log.Println(mname, "argument type not exported:", argType)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
replyType := mtype.In(2)
|
||||||
|
synchronous := replyType.String() != "service.RPCCallback"
|
||||||
|
|
||||||
|
if synchronous {
|
||||||
|
// Second arg must be a pointer.
|
||||||
|
if replyType.Kind() != reflect.Ptr {
|
||||||
|
log.Println("method", mname, "reply type not a pointer:", replyType)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Reply type must be exported.
|
||||||
|
if !isExportedOrBuiltinType(replyType) {
|
||||||
|
log.Println("method", mname, "reply type not exported:", replyType)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method needs one out.
|
||||||
|
if mtype.NumOut() != 1 {
|
||||||
|
log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The return type of the method must be error.
|
||||||
|
if returnType := mtype.Out(0); returnType != typeOfError {
|
||||||
|
log.Println("method", mname, "returns", returnType.String(), "not error")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Method needs zero outs.
|
||||||
|
if mtype.NumOut() != 0 {
|
||||||
|
log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
methods[sname+"."+mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType, Synchronous: synchronous, Rcvr: rcvrv}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerImpl) serveJSONCodec(conn io.ReadWriteCloser) {
|
||||||
|
sending := new(sync.Mutex)
|
||||||
|
codec := jsonrpc.NewServerCodec(conn)
|
||||||
|
var req rpc.Request
|
||||||
|
var resp rpc.Response
|
||||||
|
for {
|
||||||
|
req = rpc.Request{}
|
||||||
|
err := codec.ReadRequestHeader(&req)
|
||||||
|
if err != nil {
|
||||||
|
if err != io.EOF {
|
||||||
|
log.Println("rpc:", err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
mtype, ok := s.methodMaps[s.config.APIVersion-1][req.ServiceMethod]
|
||||||
|
if !ok {
|
||||||
|
log.Printf("rpc: can't find method %s", req.ServiceMethod)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var argv, replyv reflect.Value
|
||||||
|
|
||||||
|
// Decode the argument value.
|
||||||
|
argIsValue := false // if true, need to indirect before calling.
|
||||||
|
if mtype.ArgType.Kind() == reflect.Ptr {
|
||||||
|
argv = reflect.New(mtype.ArgType.Elem())
|
||||||
|
} else {
|
||||||
|
argv = reflect.New(mtype.ArgType)
|
||||||
|
argIsValue = true
|
||||||
|
}
|
||||||
|
// argv guaranteed to be a pointer now.
|
||||||
|
if err = codec.ReadRequestBody(argv.Interface()); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if argIsValue {
|
||||||
|
argv = argv.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if mtype.Synchronous {
|
||||||
|
replyv = reflect.New(mtype.ReplyType.Elem())
|
||||||
|
function := mtype.method.Func
|
||||||
|
var returnValues []reflect.Value
|
||||||
|
var errInter interface{}
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
if ierr := recover(); ierr != nil {
|
||||||
|
errInter = newInternalError(ierr, 2)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
returnValues = function.Call([]reflect.Value{mtype.Rcvr, argv, replyv})
|
||||||
|
errInter = returnValues[0].Interface()
|
||||||
|
}()
|
||||||
|
|
||||||
|
errmsg := ""
|
||||||
|
if errInter != nil {
|
||||||
|
errmsg = errInter.(error).Error()
|
||||||
|
}
|
||||||
|
resp = rpc.Response{}
|
||||||
|
s.sendResponse(sending, &req, &resp, replyv.Interface(), codec, errmsg)
|
||||||
|
} else {
|
||||||
|
function := mtype.method.Func
|
||||||
|
ctl := &RPCCallback{s, sending, codec, req}
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if ierr := recover(); ierr != nil {
|
||||||
|
ctl.Return(nil, newInternalError(ierr, 2))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
function.Call([]reflect.Value{mtype.Rcvr, argv, reflect.ValueOf(ctl)})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
codec.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A value sent as a placeholder for the server's response value when the server
|
||||||
|
// receives an invalid request. It is never decoded by the client since the Response
|
||||||
|
// contains an error when it is used.
|
||||||
|
var invalidRequest = struct{}{}
|
||||||
|
|
||||||
|
func (s *ServerImpl) sendResponse(sending *sync.Mutex, req *rpc.Request, resp *rpc.Response, reply interface{}, codec rpc.ServerCodec, errmsg string) {
|
||||||
|
resp.ServiceMethod = req.ServiceMethod
|
||||||
|
if errmsg != "" {
|
||||||
|
resp.Error = errmsg
|
||||||
|
reply = invalidRequest
|
||||||
|
}
|
||||||
|
resp.Seq = req.Seq
|
||||||
|
sending.Lock()
|
||||||
|
defer sending.Unlock()
|
||||||
|
err := codec.WriteResponse(resp, reply)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("rpc: writing response:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cb *RPCCallback) Return(out interface{}, err error) {
|
||||||
|
errmsg := ""
|
||||||
|
if err != nil {
|
||||||
|
errmsg = err.Error()
|
||||||
|
}
|
||||||
|
var resp rpc.Response
|
||||||
|
cb.s.sendResponse(cb.sending, &cb.req, &resp, out, cb.codec, errmsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVersion returns the version of delve as well as the API version
|
||||||
|
// currently served.
|
||||||
|
func (s *RPCServer) GetVersion(args api.GetVersionIn, out *api.GetVersionOut) error {
|
||||||
|
out.DelveVersion = version.DelveVersion.String()
|
||||||
|
out.APIVersion = s.s.config.APIVersion
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changes version of the API being served.
|
||||||
|
func (s *RPCServer) SetApiVersion(args api.SetAPIVersionIn, out *api.SetAPIVersionOut) error {
|
||||||
|
if args.APIVersion < 2 {
|
||||||
|
args.APIVersion = 1
|
||||||
|
}
|
||||||
|
if args.APIVersion > 2 {
|
||||||
|
return fmt.Errorf("unknown API version")
|
||||||
|
}
|
||||||
|
s.s.config.APIVersion = args.APIVersion
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type internalError struct {
|
||||||
|
Err interface{}
|
||||||
|
Stack []internalErrorFrame
|
||||||
|
}
|
||||||
|
|
||||||
|
type internalErrorFrame struct {
|
||||||
|
Pc uintptr
|
||||||
|
Func string
|
||||||
|
File string
|
||||||
|
Line int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInternalError(ierr interface{}, skip int) *internalError {
|
||||||
|
r := &internalError{ierr, nil}
|
||||||
|
for i := skip; ; i++ {
|
||||||
|
pc, file, line, ok := runtime.Caller(i)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fname := "<unknown>"
|
||||||
|
fn := runtime.FuncForPC(pc)
|
||||||
|
if fn != nil {
|
||||||
|
fname = fn.Name()
|
||||||
|
}
|
||||||
|
r.Stack = append(r.Stack, internalErrorFrame{pc, fname, file, line})
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *internalError) Error() string {
|
||||||
|
var out bytes.Buffer
|
||||||
|
fmt.Fprintf(&out, "Internal debugger error: %v\n", err.Err)
|
||||||
|
for _, frame := range err.Stack {
|
||||||
|
fmt.Fprintf(&out, "%s (%#x)\n\t%s:%d\n", frame.Func, frame.Pc, frame.File, frame.Line)
|
||||||
|
}
|
||||||
|
return out.String()
|
||||||
|
}
|
18
vendor/vendor.json
vendored
18
vendor/vendor.json
vendored
@ -68,6 +68,12 @@
|
|||||||
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
||||||
"revisionTime": "2017-03-13T17:59:34Z"
|
"revisionTime": "2017-03-13T17:59:34Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "xRa64kuzCXVktmGscs1vCz9jIHs=",
|
||||||
|
"path": "github.com/derekparker/delve/pkg/version",
|
||||||
|
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
||||||
|
"revisionTime": "2017-03-13T17:59:34Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "BPHre0My8iszpkoNcX4ljtrz1dA=",
|
"checksumSHA1": "BPHre0My8iszpkoNcX4ljtrz1dA=",
|
||||||
"path": "github.com/derekparker/delve/service",
|
"path": "github.com/derekparker/delve/service",
|
||||||
@ -86,12 +92,24 @@
|
|||||||
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
||||||
"revisionTime": "2017-03-13T17:59:34Z"
|
"revisionTime": "2017-03-13T17:59:34Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "d73mTsiCuYYpDaVs9QtozhzMDU0=",
|
||||||
|
"path": "github.com/derekparker/delve/service/rpc1",
|
||||||
|
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
||||||
|
"revisionTime": "2017-03-13T17:59:34Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "B+J0KRNuX0anRlif3mWXhBQhnVo=",
|
"checksumSHA1": "B+J0KRNuX0anRlif3mWXhBQhnVo=",
|
||||||
"path": "github.com/derekparker/delve/service/rpc2",
|
"path": "github.com/derekparker/delve/service/rpc2",
|
||||||
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
||||||
"revisionTime": "2017-03-13T17:59:34Z"
|
"revisionTime": "2017-03-13T17:59:34Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "PsNfnfv8GS79AG225Q/h57q/6F4=",
|
||||||
|
"path": "github.com/derekparker/delve/service/rpccommon",
|
||||||
|
"revision": "ab7367ed2bf15044f7bca97147a802f77b875797",
|
||||||
|
"revisionTime": "2017-03-13T17:59:34Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "hveFTNQ9YEyYRs6SWuXM+XU9qRI=",
|
"checksumSHA1": "hveFTNQ9YEyYRs6SWuXM+XU9qRI=",
|
||||||
"path": "github.com/fsnotify/fsnotify",
|
"path": "github.com/fsnotify/fsnotify",
|
||||||
|
Loading…
Reference in New Issue
Block a user