documentation: API documentation improvements (#507)
* documentation: headless invocation should specify --api-version=2 * documentation: More API documentation * documentation: copied documentation from client.go to rpc2/server.go Fixes #164
This commit is contained in:
parent
473b66387c
commit
f7cb6053d2
@ -7,7 +7,7 @@ Delve exposes an API interface so that other programs, mostly IDEs and editors,
|
||||
In order to run Delve in "API mode", simply invoke with one of the standard commands, providing the `--headless` flag, like so:
|
||||
|
||||
```
|
||||
$ dlv debug --headless --log --listen=127.0.0.1:8181
|
||||
$ dlv debug --headless --api-version=2 --log --listen=127.0.0.1:8181
|
||||
```
|
||||
|
||||
This will start the debugger in a non-interactive mode, listening on the specified address, and will enable logging. The last two flags are optional, of course.
|
||||
|
@ -1,3 +1,44 @@
|
||||
# JSON-RPC interface
|
||||
|
||||
Delve exposes a [JSON-RPC](http://json-rpc.org/) API interface. Here is an (incomplete) [list of language implementations](http://json-rpc.org/wiki/implementations).
|
||||
Delve exposes a [JSON-RPC](http://json-rpc.org/) API interface.
|
||||
|
||||
Note that this JSON-RPC interface is served over a streaming socket, *not* over HTTP.
|
||||
|
||||
Here is an (incomplete) [list of language implementations](http://json-rpc.org/wiki/implementations).
|
||||
|
||||
# API versions
|
||||
|
||||
Delve currently supports two versions of its API. By default a headless instance of `dlv` will serve APIv1, however new clients should use APIv2 as new features will only be made available through version 2. To select APIv2 use `--api-version=2` command line argument.
|
||||
|
||||
# API version 2 documentation
|
||||
|
||||
All the methods of the type `service/rpc2.RPCServer` can be called using JSON-RPC, the documentation for these calls is [available on godoc](https://godoc.org/github.com/derekparker/delve/service/rpc2#RPCServer).
|
||||
|
||||
Note that all exposed methods take one single input parameter (usually called `args`) of a struct type and also return a result of a struct type. Also note that the method name should be prefixed with `RPCServer.` in JSON-RPC.
|
||||
|
||||
# Example
|
||||
|
||||
Your client wants to set a breakpoint on the function `main.main`.
|
||||
The first step will be calling the method `FindLocation` with `Scope = api.EvalScope{ GoroutineID: -1, Frame: 0}` and `Loc = "main.main"`. The JSON-RPC request packet should look like this:
|
||||
|
||||
```
|
||||
{"method":"RPCServer.FindLocation","params":[{"Scope":{"GoroutineID":-1,"Frame":0},"Loc":"main.main"}],"id":2}
|
||||
```
|
||||
|
||||
the response packet will look like this:
|
||||
|
||||
```
|
||||
{"id":2,"result":{"Locations":[{"pc":4199019,"file":"/home/a/temp/callme/callme.go","line":31,"function":{"name":"main.main","value":4198992,"type":84,"goType":0}}]},"error":null}
|
||||
```
|
||||
|
||||
Now your client should call the method `CreateBreakpoint` and specify `4199019` (the `pc` field in the response object) as the target address:
|
||||
|
||||
```
|
||||
{"method":"RPCServer.CreateBreakpoint","params":[{"Breakpoint":{"addr":4199019}}],"id":3}
|
||||
```
|
||||
|
||||
if this request is successful your client will receive the following response:
|
||||
|
||||
```
|
||||
{"id":3,"result":{"Breakpoint":{"id":1,"name":"","addr":4199019,"file":"/home/a/temp/callme/callme.go","line":31,"functionName":"main.main","Cond":"","continue":false,"goroutine":false,"stacktrace":0,"LoadArgs":null,"LoadLocals":null,"hitCount":{},"totalHitCount":0}},"error":null}
|
||||
```
|
||||
|
@ -107,6 +107,7 @@ type ProcessPidOut struct {
|
||||
Pid int
|
||||
}
|
||||
|
||||
// ProcessPid returns the pid of the process we are debugging.
|
||||
func (s *RPCServer) ProcessPid(arg ProcessPidIn, out *ProcessPidOut) error {
|
||||
out.Pid = s.debugger.ProcessPid()
|
||||
return nil
|
||||
@ -119,6 +120,7 @@ type DetachIn struct {
|
||||
type DetachOut struct {
|
||||
}
|
||||
|
||||
// Detach detaches the debugger, optionally killing the process.
|
||||
func (s *RPCServer) Detach(arg DetachIn, out *DetachOut) error {
|
||||
return s.debugger.Detach(arg.Kill)
|
||||
}
|
||||
@ -129,6 +131,7 @@ type RestartIn struct {
|
||||
type RestartOut struct {
|
||||
}
|
||||
|
||||
// Restart restarts program.
|
||||
func (s *RPCServer) Restart(arg RestartIn, out *RestartOut) error {
|
||||
if s.config.AttachPid != 0 {
|
||||
return errors.New("cannot restart process Delve did not create")
|
||||
@ -143,6 +146,7 @@ type StateOut struct {
|
||||
State *api.DebuggerState
|
||||
}
|
||||
|
||||
// State returns the current debugger state.
|
||||
func (s *RPCServer) State(arg StateIn, out *StateOut) error {
|
||||
st, err := s.debugger.State()
|
||||
if err != nil {
|
||||
@ -156,6 +160,7 @@ type CommandOut struct {
|
||||
State api.DebuggerState
|
||||
}
|
||||
|
||||
// Command interrupts, continues and steps through the program.
|
||||
func (s *RPCServer) Command(command api.DebuggerCommand, out *CommandOut) error {
|
||||
st, err := s.debugger.Command(&command)
|
||||
if err != nil {
|
||||
@ -174,6 +179,7 @@ type GetBreakpointOut struct {
|
||||
Breakpoint api.Breakpoint
|
||||
}
|
||||
|
||||
// GetBreakpoint gets a breakpoint by Name (if Name is not an empty string) or by ID.
|
||||
func (s *RPCServer) GetBreakpoint(arg GetBreakpointIn, out *GetBreakpointOut) error {
|
||||
var bp *api.Breakpoint
|
||||
if arg.Name != "" {
|
||||
@ -202,6 +208,10 @@ type StacktraceOut struct {
|
||||
Locations []api.Stackframe
|
||||
}
|
||||
|
||||
// Stacktrace returns stacktrace of goroutine Id up to the specified Depth.
|
||||
//
|
||||
// If Full is set it will also the variable of all local variables
|
||||
// and function arguments of all stack frames.
|
||||
func (s *RPCServer) Stacktrace(arg StacktraceIn, out *StacktraceOut) error {
|
||||
cfg := arg.Cfg
|
||||
if cfg == nil && arg.Full {
|
||||
@ -222,6 +232,7 @@ type ListBreakpointsOut struct {
|
||||
Breakpoints []*api.Breakpoint
|
||||
}
|
||||
|
||||
// ListBreakpoints gets all breakpoints.
|
||||
func (s *RPCServer) ListBreakpoints(arg ListBreakpointsIn, out *ListBreakpointsOut) error {
|
||||
out.Breakpoints = s.debugger.Breakpoints()
|
||||
return nil
|
||||
@ -235,6 +246,18 @@ type CreateBreakpointOut struct {
|
||||
Breakpoint api.Breakpoint
|
||||
}
|
||||
|
||||
// CreateBreakpoint creates a new breakpoint.
|
||||
//
|
||||
// - If arg.Breakpoint.File is not an empty string the breakpoint
|
||||
// will be created on the specified file:line location
|
||||
//
|
||||
// - If arg.Breakpoint.FunctionName is not an empty string
|
||||
// the breakpoint will be created on the specified function:line
|
||||
// location. Note that setting a breakpoint on a function's entry point
|
||||
// (line == 0) can have surprising consequences, it is advisable to
|
||||
// use line = -1 instead which will skip the prologue.
|
||||
//
|
||||
// - Otherwise the value specified by arg.Breakpoint.Addr will be used.
|
||||
func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpointOut) error {
|
||||
createdbp, err := s.debugger.CreateBreakpoint(&arg.Breakpoint)
|
||||
if err != nil {
|
||||
@ -253,6 +276,8 @@ type ClearBreakpointOut struct {
|
||||
Breakpoint *api.Breakpoint
|
||||
}
|
||||
|
||||
// ClearBreakpoint deletes a breakpoint by Name (if Name is not an
|
||||
// empty string) or by ID.
|
||||
func (s *RPCServer) ClearBreakpoint(arg ClearBreakpointIn, out *ClearBreakpointOut) error {
|
||||
var bp *api.Breakpoint
|
||||
if arg.Name != "" {
|
||||
@ -281,6 +306,11 @@ type AmendBreakpointIn struct {
|
||||
type AmendBreakpointOut struct {
|
||||
}
|
||||
|
||||
// AmendBreakpoint allows user to update an existing breakpoint
|
||||
// for example to change the information retrieved when the
|
||||
// breakpoint is hit or to change, add or remove the break condition.
|
||||
//
|
||||
// arg.Breakpoint.ID must be a valid breakpoint ID
|
||||
func (s *RPCServer) AmendBreakpoint(arg AmendBreakpointIn, out *AmendBreakpointOut) error {
|
||||
return s.debugger.AmendBreakpoint(&arg.Breakpoint)
|
||||
}
|
||||
@ -292,6 +322,7 @@ type ListThreadsOut struct {
|
||||
Threads []*api.Thread
|
||||
}
|
||||
|
||||
// ListThreads lists all threads.
|
||||
func (s *RPCServer) ListThreads(arg ListThreadsIn, out *ListThreadsOut) (err error) {
|
||||
out.Threads, err = s.debugger.Threads()
|
||||
return err
|
||||
@ -305,6 +336,7 @@ type GetThreadOut struct {
|
||||
Thread *api.Thread
|
||||
}
|
||||
|
||||
// GetThread gets a thread by its ID.
|
||||
func (s *RPCServer) GetThread(arg GetThreadIn, out *GetThreadOut) error {
|
||||
t, err := s.debugger.FindThread(arg.Id)
|
||||
if err != nil {
|
||||
@ -326,6 +358,7 @@ type ListPackageVarsOut struct {
|
||||
Variables []api.Variable
|
||||
}
|
||||
|
||||
// ListPackageVars lists all package variables in the context of the current thread.
|
||||
func (s *RPCServer) ListPackageVars(arg ListPackageVarsIn, out *ListPackageVarsOut) error {
|
||||
state, err := s.debugger.State()
|
||||
if err != nil {
|
||||
@ -352,6 +385,7 @@ type ListRegistersOut struct {
|
||||
Registers string
|
||||
}
|
||||
|
||||
// ListRegisters lists registers and their values.
|
||||
func (s *RPCServer) ListRegisters(arg ListRegistersIn, out *ListRegistersOut) error {
|
||||
state, err := s.debugger.State()
|
||||
if err != nil {
|
||||
@ -375,6 +409,7 @@ type ListLocalVarsOut struct {
|
||||
Variables []api.Variable
|
||||
}
|
||||
|
||||
// ListLocalVars lists all local variables in scope.
|
||||
func (s *RPCServer) ListLocalVars(arg ListLocalVarsIn, out *ListLocalVarsOut) error {
|
||||
vars, err := s.debugger.LocalVariables(arg.Scope, *api.LoadConfigToProc(&arg.Cfg))
|
||||
if err != nil {
|
||||
@ -393,6 +428,7 @@ type ListFunctionArgsOut struct {
|
||||
Args []api.Variable
|
||||
}
|
||||
|
||||
// ListFunctionArgs lists all arguments to the current function
|
||||
func (s *RPCServer) ListFunctionArgs(arg ListFunctionArgsIn, out *ListFunctionArgsOut) error {
|
||||
vars, err := s.debugger.FunctionArguments(arg.Scope, *api.LoadConfigToProc(&arg.Cfg))
|
||||
if err != nil {
|
||||
@ -412,6 +448,10 @@ type EvalOut struct {
|
||||
Variable *api.Variable
|
||||
}
|
||||
|
||||
// EvalVariable returns a variable in the specified context.
|
||||
//
|
||||
// See https://github.com/derekparker/delve/wiki/Expressions for
|
||||
// a description of acceptable values of arg.Expr.
|
||||
func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error {
|
||||
cfg := arg.Cfg
|
||||
if cfg == nil {
|
||||
@ -434,6 +474,8 @@ type SetIn struct {
|
||||
type SetOut struct {
|
||||
}
|
||||
|
||||
// Set sets the value of a variable. Only numerical types and
|
||||
// pointers are currently supported.
|
||||
func (s *RPCServer) Set(arg SetIn, out *SetOut) error {
|
||||
return s.debugger.SetVariableInScope(arg.Scope, arg.Symbol, arg.Value)
|
||||
}
|
||||
@ -446,6 +488,7 @@ type ListSourcesOut struct {
|
||||
Sources []string
|
||||
}
|
||||
|
||||
// ListSources lists all source files in the process matching filter.
|
||||
func (s *RPCServer) ListSources(arg ListSourcesIn, out *ListSourcesOut) error {
|
||||
ss, err := s.debugger.Sources(arg.Filter)
|
||||
if err != nil {
|
||||
@ -463,6 +506,7 @@ type ListFunctionsOut struct {
|
||||
Funcs []string
|
||||
}
|
||||
|
||||
// ListFunctions lists all functions in the process matching filter.
|
||||
func (s *RPCServer) ListFunctions(arg ListFunctionsIn, out *ListFunctionsOut) error {
|
||||
fns, err := s.debugger.Functions(arg.Filter)
|
||||
if err != nil {
|
||||
@ -480,6 +524,7 @@ type ListTypesOut struct {
|
||||
Types []string
|
||||
}
|
||||
|
||||
// ListTypes lists all types in the process matching filter.
|
||||
func (s *RPCServer) ListTypes(arg ListTypesIn, out *ListTypesOut) error {
|
||||
tps, err := s.debugger.Types(arg.Filter)
|
||||
if err != nil {
|
||||
@ -496,6 +541,7 @@ type ListGoroutinesOut struct {
|
||||
Goroutines []*api.Goroutine
|
||||
}
|
||||
|
||||
// ListGoroutines lists all goroutines.
|
||||
func (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut) error {
|
||||
gs, err := s.debugger.Goroutines()
|
||||
if err != nil {
|
||||
@ -512,6 +558,7 @@ type AttachedToExistingProcessOut struct {
|
||||
Answer bool
|
||||
}
|
||||
|
||||
// AttachedToExistingProcess returns whether we attached to a running process or not
|
||||
func (c *RPCServer) AttachedToExistingProcess(arg AttachedToExistingProcessIn, out *AttachedToExistingProcessOut) error {
|
||||
if c.config.AttachPid != 0 {
|
||||
out.Answer = true
|
||||
@ -528,6 +575,19 @@ type FindLocationOut struct {
|
||||
Locations []api.Location
|
||||
}
|
||||
|
||||
// FindLocation returns concrete location information described by a location expression
|
||||
//
|
||||
// loc ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address>
|
||||
// * <filename> can be the full path of a file or just a suffix
|
||||
// * <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name>
|
||||
// * <function> must be unambiguous
|
||||
// * /<regex>/ will return a location for each function matched by regex
|
||||
// * +<offset> returns a location for the line that is <offset> lines after the current line
|
||||
// * -<offset> returns a location for the line that is <offset> lines before the current line
|
||||
// * <line> returns a location for a line in the current file
|
||||
// * *<address> returns the location corresponding to the specified address
|
||||
//
|
||||
// NOTE: this function does not actually set breakpoints.
|
||||
func (c *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error {
|
||||
var err error
|
||||
out.Locations, err = c.debugger.FindLocation(arg.Scope, arg.Loc)
|
||||
@ -544,6 +604,13 @@ type DisassembleOut struct {
|
||||
Disassemble api.AsmInstructions
|
||||
}
|
||||
|
||||
// Disassemble code.
|
||||
//
|
||||
// If both StartPC and EndPC are non-zero the specified range will be disassembled, otherwise the function containing StartPC will be disassembled.
|
||||
//
|
||||
// Scope is used to mark the instruction the specified gorutine is stopped at.
|
||||
//
|
||||
// Disassemble will also try to calculate the destination address of an absolute indirect CALL if it happens to be the instruction the selected goroutine is stopped at.
|
||||
func (c *RPCServer) Disassemble(arg DisassembleIn, out *DisassembleOut) error {
|
||||
var err error
|
||||
out.Disassemble, err = c.debugger.Disassemble(arg.Scope, arg.StartPC, arg.EndPC, arg.Flavour)
|
||||
|
Loading…
Reference in New Issue
Block a user