github.com/neilgarb/delve@v1.9.2-nobreaks/service/rpc2/server.go (about) 1 package rpc2 2 3 import ( 4 "errors" 5 "fmt" 6 "sort" 7 "time" 8 9 "github.com/go-delve/delve/pkg/dwarf/op" 10 "github.com/go-delve/delve/pkg/proc" 11 "github.com/go-delve/delve/service" 12 "github.com/go-delve/delve/service/api" 13 "github.com/go-delve/delve/service/debugger" 14 ) 15 16 type RPCServer struct { 17 // config is all the information necessary to start the debugger and server. 18 config *service.Config 19 // debugger is a debugger service. 20 debugger *debugger.Debugger 21 } 22 23 func NewServer(config *service.Config, debugger *debugger.Debugger) *RPCServer { 24 return &RPCServer{config, debugger} 25 } 26 27 type ProcessPidIn struct { 28 } 29 30 type ProcessPidOut struct { 31 Pid int 32 } 33 34 // ProcessPid returns the pid of the process we are debugging. 35 func (s *RPCServer) ProcessPid(arg ProcessPidIn, out *ProcessPidOut) error { 36 out.Pid = s.debugger.ProcessPid() 37 return nil 38 } 39 40 type LastModifiedIn struct { 41 } 42 43 type LastModifiedOut struct { 44 Time time.Time 45 } 46 47 func (s *RPCServer) LastModified(arg LastModifiedIn, out *LastModifiedOut) error { 48 out.Time = s.debugger.LastModified() 49 return nil 50 } 51 52 type DetachIn struct { 53 Kill bool 54 } 55 56 type DetachOut struct { 57 } 58 59 // Detach detaches the debugger, optionally killing the process. 60 func (s *RPCServer) Detach(arg DetachIn, out *DetachOut) error { 61 return s.debugger.Detach(arg.Kill) 62 } 63 64 type RestartIn struct { 65 // Position to restart from, if it starts with 'c' it's a checkpoint ID, 66 // otherwise it's an event number. Only valid for recorded targets. 67 Position string 68 69 // ResetArgs tell whether NewArgs and NewRedirects should take effect. 70 ResetArgs bool 71 // NewArgs are arguments to launch a new process. They replace only the 72 // argv[1] and later. Argv[0] cannot be changed. 73 NewArgs []string 74 75 // When Rerecord is set the target will be rerecorded 76 Rerecord bool 77 78 // When Rebuild is set the process will be build again 79 Rebuild bool 80 81 NewRedirects [3]string 82 } 83 84 type RestartOut struct { 85 DiscardedBreakpoints []api.DiscardedBreakpoint 86 } 87 88 // Restart restarts program. 89 func (s *RPCServer) Restart(arg RestartIn, cb service.RPCCallback) { 90 close(cb.SetupDoneChan()) 91 if s.config.Debugger.AttachPid != 0 { 92 cb.Return(nil, errors.New("cannot restart process Delve did not create")) 93 return 94 } 95 var out RestartOut 96 var err error 97 out.DiscardedBreakpoints, err = s.debugger.Restart(arg.Rerecord, arg.Position, arg.ResetArgs, arg.NewArgs, arg.NewRedirects, arg.Rebuild) 98 cb.Return(out, err) 99 } 100 101 type StateIn struct { 102 // If NonBlocking is true State will return immediately even if the target process is running. 103 NonBlocking bool 104 } 105 106 type StateOut struct { 107 State *api.DebuggerState 108 } 109 110 // State returns the current debugger state. 111 func (s *RPCServer) State(arg StateIn, cb service.RPCCallback) { 112 close(cb.SetupDoneChan()) 113 var out StateOut 114 st, err := s.debugger.State(arg.NonBlocking) 115 if err != nil { 116 cb.Return(nil, err) 117 return 118 } 119 out.State = st 120 cb.Return(out, nil) 121 } 122 123 type CommandOut struct { 124 State api.DebuggerState 125 } 126 127 // Command interrupts, continues and steps through the program. 128 func (s *RPCServer) Command(command api.DebuggerCommand, cb service.RPCCallback) { 129 st, err := s.debugger.Command(&command, cb.SetupDoneChan()) 130 if err != nil { 131 cb.Return(nil, err) 132 return 133 } 134 var out CommandOut 135 out.State = *st 136 cb.Return(out, nil) 137 } 138 139 type GetBufferedTracepointsIn struct { 140 } 141 142 type GetBufferedTracepointsOut struct { 143 TracepointResults []api.TracepointResult 144 } 145 146 func (s *RPCServer) GetBufferedTracepoints(arg GetBufferedTracepointsIn, out *GetBufferedTracepointsOut) error { 147 out.TracepointResults = s.debugger.GetBufferedTracepoints() 148 return nil 149 } 150 151 type GetBreakpointIn struct { 152 Id int 153 Name string 154 } 155 156 type GetBreakpointOut struct { 157 Breakpoint api.Breakpoint 158 } 159 160 // GetBreakpoint gets a breakpoint by Name (if Name is not an empty string) or by ID. 161 func (s *RPCServer) GetBreakpoint(arg GetBreakpointIn, out *GetBreakpointOut) error { 162 var bp *api.Breakpoint 163 if arg.Name != "" { 164 bp = s.debugger.FindBreakpointByName(arg.Name) 165 if bp == nil { 166 return fmt.Errorf("no breakpoint with name %s", arg.Name) 167 } 168 } else { 169 bp = s.debugger.FindBreakpoint(arg.Id) 170 if bp == nil { 171 return fmt.Errorf("no breakpoint with id %d", arg.Id) 172 } 173 } 174 out.Breakpoint = *bp 175 return nil 176 } 177 178 type StacktraceIn struct { 179 Id int 180 Depth int 181 Full bool 182 Defers bool // read deferred functions (equivalent to passing StacktraceReadDefers in Opts) 183 Opts api.StacktraceOptions 184 Cfg *api.LoadConfig 185 } 186 187 type StacktraceOut struct { 188 Locations []api.Stackframe 189 } 190 191 // Stacktrace returns stacktrace of goroutine Id up to the specified Depth. 192 // 193 // If Full is set it will also the variable of all local variables 194 // and function arguments of all stack frames. 195 func (s *RPCServer) Stacktrace(arg StacktraceIn, out *StacktraceOut) error { 196 cfg := arg.Cfg 197 if cfg == nil && arg.Full { 198 cfg = &api.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1} 199 } 200 if arg.Defers { 201 arg.Opts |= api.StacktraceReadDefers 202 } 203 var err error 204 rawlocs, err := s.debugger.Stacktrace(arg.Id, arg.Depth, arg.Opts) 205 if err != nil { 206 return err 207 } 208 out.Locations, err = s.debugger.ConvertStacktrace(rawlocs, api.LoadConfigToProc(cfg)) 209 return err 210 } 211 212 type AncestorsIn struct { 213 GoroutineID int 214 NumAncestors int 215 Depth int 216 } 217 218 type AncestorsOut struct { 219 Ancestors []api.Ancestor 220 } 221 222 // Ancestors returns the stacktraces for the ancestors of a goroutine. 223 func (s *RPCServer) Ancestors(arg AncestorsIn, out *AncestorsOut) error { 224 var err error 225 out.Ancestors, err = s.debugger.Ancestors(arg.GoroutineID, arg.NumAncestors, arg.Depth) 226 return err 227 } 228 229 type ListBreakpointsIn struct { 230 All bool 231 } 232 233 type ListBreakpointsOut struct { 234 Breakpoints []*api.Breakpoint 235 } 236 237 // ListBreakpoints gets all breakpoints. 238 func (s *RPCServer) ListBreakpoints(arg ListBreakpointsIn, out *ListBreakpointsOut) error { 239 out.Breakpoints = s.debugger.Breakpoints(arg.All) 240 return nil 241 } 242 243 type CreateBreakpointIn struct { 244 Breakpoint api.Breakpoint 245 } 246 247 type CreateBreakpointOut struct { 248 Breakpoint api.Breakpoint 249 } 250 251 // CreateBreakpoint creates a new breakpoint. The client is expected to populate `CreateBreakpointIn` 252 // with an `api.Breakpoint` struct describing where to set the breakpoing. For more information on 253 // how to properly request a breakpoint via the `api.Breakpoint` struct see the documentation for 254 // `debugger.CreateBreakpoint` here: https://pkg.go.dev/github.com/go-delve/delve/service/debugger#Debugger.CreateBreakpoint. 255 func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpointOut) error { 256 if err := api.ValidBreakpointName(arg.Breakpoint.Name); err != nil { 257 return err 258 } 259 createdbp, err := s.debugger.CreateBreakpoint(&arg.Breakpoint) 260 if err != nil { 261 return err 262 } 263 out.Breakpoint = *createdbp 264 return nil 265 } 266 267 type CreateEBPFTracepointIn struct { 268 FunctionName string 269 } 270 271 type CreateEBPFTracepointOut struct { 272 Breakpoint api.Breakpoint 273 } 274 275 func (s *RPCServer) CreateEBPFTracepoint(arg CreateEBPFTracepointIn, out *CreateEBPFTracepointOut) error { 276 return s.debugger.CreateEBPFTracepoint(arg.FunctionName) 277 } 278 279 type ClearBreakpointIn struct { 280 Id int 281 Name string 282 } 283 284 type ClearBreakpointOut struct { 285 Breakpoint *api.Breakpoint 286 } 287 288 // ClearBreakpoint deletes a breakpoint by Name (if Name is not an 289 // empty string) or by ID. 290 func (s *RPCServer) ClearBreakpoint(arg ClearBreakpointIn, out *ClearBreakpointOut) error { 291 var bp *api.Breakpoint 292 if arg.Name != "" { 293 bp = s.debugger.FindBreakpointByName(arg.Name) 294 if bp == nil { 295 return fmt.Errorf("no breakpoint with name %s", arg.Name) 296 } 297 } else { 298 bp = s.debugger.FindBreakpoint(arg.Id) 299 if bp == nil { 300 return fmt.Errorf("no breakpoint with id %d", arg.Id) 301 } 302 } 303 deleted, err := s.debugger.ClearBreakpoint(bp) 304 if err != nil { 305 return err 306 } 307 out.Breakpoint = deleted 308 return nil 309 } 310 311 type ToggleBreakpointIn struct { 312 Id int 313 Name string 314 } 315 316 type ToggleBreakpointOut struct { 317 Breakpoint *api.Breakpoint 318 } 319 320 // ToggleBreakpoint toggles on or off a breakpoint by Name (if Name is not an 321 // empty string) or by ID. 322 func (s *RPCServer) ToggleBreakpoint(arg ToggleBreakpointIn, out *ToggleBreakpointOut) error { 323 var bp *api.Breakpoint 324 if arg.Name != "" { 325 bp = s.debugger.FindBreakpointByName(arg.Name) 326 if bp == nil { 327 return fmt.Errorf("no breakpoint with name %s", arg.Name) 328 } 329 } else { 330 bp = s.debugger.FindBreakpoint(arg.Id) 331 if bp == nil { 332 return fmt.Errorf("no breakpoint with id %d", arg.Id) 333 } 334 } 335 bp.Disabled = !bp.Disabled 336 if err := api.ValidBreakpointName(bp.Name); err != nil { 337 return err 338 } 339 if err := s.debugger.AmendBreakpoint(bp); err != nil { 340 return err 341 } 342 out.Breakpoint = bp 343 return nil 344 } 345 346 type AmendBreakpointIn struct { 347 Breakpoint api.Breakpoint 348 } 349 350 type AmendBreakpointOut struct { 351 } 352 353 // AmendBreakpoint allows user to update an existing breakpoint 354 // for example to change the information retrieved when the 355 // breakpoint is hit or to change, add or remove the break condition. 356 // 357 // arg.Breakpoint.ID must be a valid breakpoint ID 358 func (s *RPCServer) AmendBreakpoint(arg AmendBreakpointIn, out *AmendBreakpointOut) error { 359 if err := api.ValidBreakpointName(arg.Breakpoint.Name); err != nil { 360 return err 361 } 362 return s.debugger.AmendBreakpoint(&arg.Breakpoint) 363 } 364 365 type CancelNextIn struct { 366 } 367 368 type CancelNextOut struct { 369 } 370 371 func (s *RPCServer) CancelNext(arg CancelNextIn, out *CancelNextOut) error { 372 return s.debugger.CancelNext() 373 } 374 375 type ListThreadsIn struct { 376 } 377 378 type ListThreadsOut struct { 379 Threads []*api.Thread 380 } 381 382 // ListThreads lists all threads. 383 func (s *RPCServer) ListThreads(arg ListThreadsIn, out *ListThreadsOut) (err error) { 384 threads, err := s.debugger.Threads() 385 if err != nil { 386 return err 387 } 388 s.debugger.LockTarget() 389 defer s.debugger.UnlockTarget() 390 out.Threads = api.ConvertThreads(threads, s.debugger.ConvertThreadBreakpoint) 391 return nil 392 } 393 394 type GetThreadIn struct { 395 Id int 396 } 397 398 type GetThreadOut struct { 399 Thread *api.Thread 400 } 401 402 // GetThread gets a thread by its ID. 403 func (s *RPCServer) GetThread(arg GetThreadIn, out *GetThreadOut) error { 404 t, err := s.debugger.FindThread(arg.Id) 405 if err != nil { 406 return err 407 } 408 if t == nil { 409 return fmt.Errorf("no thread with id %d", arg.Id) 410 } 411 s.debugger.LockTarget() 412 defer s.debugger.UnlockTarget() 413 out.Thread = api.ConvertThread(t, s.debugger.ConvertThreadBreakpoint(t)) 414 return nil 415 } 416 417 type ListPackageVarsIn struct { 418 Filter string 419 Cfg api.LoadConfig 420 } 421 422 type ListPackageVarsOut struct { 423 Variables []api.Variable 424 } 425 426 // ListPackageVars lists all package variables in the context of the current thread. 427 func (s *RPCServer) ListPackageVars(arg ListPackageVarsIn, out *ListPackageVarsOut) error { 428 vars, err := s.debugger.PackageVariables(arg.Filter, *api.LoadConfigToProc(&arg.Cfg)) 429 if err != nil { 430 return err 431 } 432 out.Variables = api.ConvertVars(vars) 433 return nil 434 } 435 436 type ListRegistersIn struct { 437 ThreadID int 438 IncludeFp bool 439 Scope *api.EvalScope 440 } 441 442 type ListRegistersOut struct { 443 Registers string 444 Regs api.Registers 445 } 446 447 // ListRegisters lists registers and their values. 448 // If ListRegistersIn.Scope is not nil the registers of that eval scope will 449 // be returned, otherwise ListRegistersIn.ThreadID will be used. 450 func (s *RPCServer) ListRegisters(arg ListRegistersIn, out *ListRegistersOut) error { 451 if arg.ThreadID == 0 && arg.Scope == nil { 452 state, err := s.debugger.State(false) 453 if err != nil { 454 return err 455 } 456 arg.ThreadID = state.CurrentThread.ID 457 } 458 459 var regs *op.DwarfRegisters 460 var err error 461 462 if arg.Scope != nil { 463 regs, err = s.debugger.ScopeRegisters(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.IncludeFp) 464 } else { 465 regs, err = s.debugger.ThreadRegisters(arg.ThreadID, arg.IncludeFp) 466 } 467 if err != nil { 468 return err 469 } 470 out.Regs = api.ConvertRegisters(regs, s.debugger.DwarfRegisterToString, arg.IncludeFp) 471 out.Registers = out.Regs.String() 472 473 return nil 474 } 475 476 type ListLocalVarsIn struct { 477 Scope api.EvalScope 478 Cfg api.LoadConfig 479 } 480 481 type ListLocalVarsOut struct { 482 Variables []api.Variable 483 } 484 485 // ListLocalVars lists all local variables in scope. 486 func (s *RPCServer) ListLocalVars(arg ListLocalVarsIn, out *ListLocalVarsOut) error { 487 vars, err := s.debugger.LocalVariables(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg)) 488 if err != nil { 489 return err 490 } 491 out.Variables = api.ConvertVars(vars) 492 return nil 493 } 494 495 type ListFunctionArgsIn struct { 496 Scope api.EvalScope 497 Cfg api.LoadConfig 498 } 499 500 type ListFunctionArgsOut struct { 501 Args []api.Variable 502 } 503 504 // ListFunctionArgs lists all arguments to the current function 505 func (s *RPCServer) ListFunctionArgs(arg ListFunctionArgsIn, out *ListFunctionArgsOut) error { 506 vars, err := s.debugger.FunctionArguments(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg)) 507 if err != nil { 508 return err 509 } 510 out.Args = api.ConvertVars(vars) 511 return nil 512 } 513 514 type EvalIn struct { 515 Scope api.EvalScope 516 Expr string 517 Cfg *api.LoadConfig 518 } 519 520 type EvalOut struct { 521 Variable *api.Variable 522 } 523 524 // Eval returns a variable in the specified context. 525 // 526 // See https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md 527 // for a description of acceptable values of arg.Expr. 528 func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error { 529 cfg := arg.Cfg 530 if cfg == nil { 531 cfg = &api.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1} 532 } 533 v, err := s.debugger.EvalVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Expr, *api.LoadConfigToProc(cfg)) 534 if err != nil { 535 return err 536 } 537 out.Variable = api.ConvertVar(v) 538 return nil 539 } 540 541 type SetIn struct { 542 Scope api.EvalScope 543 Symbol string 544 Value string 545 } 546 547 type SetOut struct { 548 } 549 550 // Set sets the value of a variable. Only numerical types and 551 // pointers are currently supported. 552 func (s *RPCServer) Set(arg SetIn, out *SetOut) error { 553 return s.debugger.SetVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Symbol, arg.Value) 554 } 555 556 type ListSourcesIn struct { 557 Filter string 558 } 559 560 type ListSourcesOut struct { 561 Sources []string 562 } 563 564 // ListSources lists all source files in the process matching filter. 565 func (s *RPCServer) ListSources(arg ListSourcesIn, out *ListSourcesOut) error { 566 ss, err := s.debugger.Sources(arg.Filter) 567 if err != nil { 568 return err 569 } 570 out.Sources = ss 571 return nil 572 } 573 574 type ListFunctionsIn struct { 575 Filter string 576 } 577 578 type ListFunctionsOut struct { 579 Funcs []string 580 } 581 582 // ListFunctions lists all functions in the process matching filter. 583 func (s *RPCServer) ListFunctions(arg ListFunctionsIn, out *ListFunctionsOut) error { 584 fns, err := s.debugger.Functions(arg.Filter) 585 if err != nil { 586 return err 587 } 588 out.Funcs = fns 589 return nil 590 } 591 592 type ListTypesIn struct { 593 Filter string 594 } 595 596 type ListTypesOut struct { 597 Types []string 598 } 599 600 // ListTypes lists all types in the process matching filter. 601 func (s *RPCServer) ListTypes(arg ListTypesIn, out *ListTypesOut) error { 602 tps, err := s.debugger.Types(arg.Filter) 603 if err != nil { 604 return err 605 } 606 out.Types = tps 607 return nil 608 } 609 610 type ListGoroutinesIn struct { 611 Start int 612 Count int 613 614 Filters []api.ListGoroutinesFilter 615 api.GoroutineGroupingOptions 616 } 617 618 type ListGoroutinesOut struct { 619 Goroutines []*api.Goroutine 620 Nextg int 621 Groups []api.GoroutineGroup 622 TooManyGroups bool 623 } 624 625 // ListGoroutines lists all goroutines. 626 // If Count is specified ListGoroutines will return at the first Count 627 // goroutines and an index in Nextg, that can be passed as the Start 628 // parameter, to get more goroutines from ListGoroutines. 629 // Passing a value of Start that wasn't returned by ListGoroutines will skip 630 // an undefined number of goroutines. 631 // 632 // If arg.Filters are specified the list of returned goroutines is filtered 633 // applying the specified filters. 634 // For example: 635 // 636 // ListGoroutinesFilter{ Kind: ListGoroutinesFilterUserLoc, Negated: false, Arg: "afile.go" } 637 // 638 // will only return goroutines whose UserLoc contains "afile.go" as a substring. 639 // More specifically a goroutine matches a location filter if the specified 640 // location, formatted like this: 641 // 642 // filename:lineno in function 643 // 644 // contains Arg[0] as a substring. 645 // 646 // Filters can also be applied to goroutine labels: 647 // 648 // ListGoroutineFilter{ Kind: ListGoroutinesFilterLabel, Negated: false, Arg: "key=value" } 649 // 650 // this filter will only return goroutines that have a key=value label. 651 // 652 // If arg.GroupBy is not GoroutineFieldNone then the goroutines will 653 // be grouped with the specified criterion. 654 // If the value of arg.GroupBy is GoroutineLabel goroutines will 655 // be grouped by the value of the label with key GroupByKey. 656 // For each group a maximum of MaxExamples example goroutines are 657 // returned, as well as the total number of goroutines in the group. 658 func (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut) error { 659 //TODO(aarzilli): if arg contains a running goroutines filter (not negated) 660 // and start == 0 and count == 0 then we can optimize this by just looking 661 // at threads directly. 662 gs, nextg, err := s.debugger.Goroutines(arg.Start, arg.Count) 663 if err != nil { 664 return err 665 } 666 gs = s.debugger.FilterGoroutines(gs, arg.Filters) 667 gs, out.Groups, out.TooManyGroups = s.debugger.GroupGoroutines(gs, &arg.GoroutineGroupingOptions) 668 s.debugger.LockTarget() 669 defer s.debugger.UnlockTarget() 670 out.Goroutines = api.ConvertGoroutines(s.debugger.Target(), gs) 671 out.Nextg = nextg 672 return nil 673 } 674 675 type AttachedToExistingProcessIn struct { 676 } 677 678 type AttachedToExistingProcessOut struct { 679 Answer bool 680 } 681 682 // AttachedToExistingProcess returns whether we attached to a running process or not 683 func (c *RPCServer) AttachedToExistingProcess(arg AttachedToExistingProcessIn, out *AttachedToExistingProcessOut) error { 684 if c.config.Debugger.AttachPid != 0 { 685 out.Answer = true 686 } 687 return nil 688 } 689 690 type FindLocationIn struct { 691 Scope api.EvalScope 692 Loc string 693 IncludeNonExecutableLines bool 694 695 // SubstitutePathRules is a slice of source code path substitution rules, 696 // the first entry of each pair is the path of a directory as it appears in 697 // the executable file (i.e. the location of a source file when the program 698 // was compiled), the second entry of each pair is the location of the same 699 // directory on the client system. 700 SubstitutePathRules [][2]string 701 } 702 703 type FindLocationOut struct { 704 Locations []api.Location 705 } 706 707 // FindLocation returns concrete location information described by a location expression. 708 // 709 // loc ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address> 710 // * <filename> can be the full path of a file or just a suffix 711 // * <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name> 712 // <function> must be unambiguous 713 // * /<regex>/ will return a location for each function matched by regex 714 // * +<offset> returns a location for the line that is <offset> lines after the current line 715 // * -<offset> returns a location for the line that is <offset> lines before the current line 716 // * <line> returns a location for a line in the current file 717 // * *<address> returns the location corresponding to the specified address 718 // 719 // NOTE: this function does not actually set breakpoints. 720 func (c *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error { 721 var err error 722 out.Locations, err = c.debugger.FindLocation(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Loc, arg.IncludeNonExecutableLines, arg.SubstitutePathRules) 723 return err 724 } 725 726 type DisassembleIn struct { 727 Scope api.EvalScope 728 StartPC, EndPC uint64 729 Flavour api.AssemblyFlavour 730 } 731 732 type DisassembleOut struct { 733 Disassemble api.AsmInstructions 734 } 735 736 // Disassemble code. 737 // 738 // If both StartPC and EndPC are non-zero the specified range will be disassembled, otherwise the function containing StartPC will be disassembled. 739 // 740 // Scope is used to mark the instruction the specified goroutine is stopped at. 741 // 742 // 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. 743 func (c *RPCServer) Disassemble(arg DisassembleIn, out *DisassembleOut) error { 744 var err error 745 insts, err := c.debugger.Disassemble(arg.Scope.GoroutineID, arg.StartPC, arg.EndPC) 746 if err != nil { 747 return err 748 } 749 out.Disassemble = make(api.AsmInstructions, len(insts)) 750 for i := range insts { 751 out.Disassemble[i] = api.ConvertAsmInstruction(insts[i], c.debugger.AsmInstructionText(&insts[i], proc.AssemblyFlavour(arg.Flavour))) 752 } 753 return nil 754 } 755 756 type RecordedIn struct { 757 } 758 759 type RecordedOut struct { 760 Recorded bool 761 TraceDirectory string 762 } 763 764 func (s *RPCServer) Recorded(arg RecordedIn, out *RecordedOut) error { 765 out.Recorded, out.TraceDirectory = s.debugger.Recorded() 766 return nil 767 } 768 769 type CheckpointIn struct { 770 Where string 771 } 772 773 type CheckpointOut struct { 774 ID int 775 } 776 777 func (s *RPCServer) Checkpoint(arg CheckpointIn, out *CheckpointOut) error { 778 var err error 779 out.ID, err = s.debugger.Checkpoint(arg.Where) 780 return err 781 } 782 783 type ListCheckpointsIn struct { 784 } 785 786 type ListCheckpointsOut struct { 787 Checkpoints []api.Checkpoint 788 } 789 790 func (s *RPCServer) ListCheckpoints(arg ListCheckpointsIn, out *ListCheckpointsOut) error { 791 var err error 792 cps, err := s.debugger.Checkpoints() 793 if err != nil { 794 return err 795 } 796 out.Checkpoints = make([]api.Checkpoint, len(cps)) 797 for i := range cps { 798 out.Checkpoints[i] = api.Checkpoint(cps[i]) 799 } 800 return nil 801 } 802 803 type ClearCheckpointIn struct { 804 ID int 805 } 806 807 type ClearCheckpointOut struct { 808 } 809 810 func (s *RPCServer) ClearCheckpoint(arg ClearCheckpointIn, out *ClearCheckpointOut) error { 811 return s.debugger.ClearCheckpoint(arg.ID) 812 } 813 814 type IsMulticlientIn struct { 815 } 816 817 type IsMulticlientOut struct { 818 // IsMulticlient returns true if the headless instance was started with --accept-multiclient 819 IsMulticlient bool 820 } 821 822 func (s *RPCServer) IsMulticlient(arg IsMulticlientIn, out *IsMulticlientOut) error { 823 *out = IsMulticlientOut{ 824 IsMulticlient: s.config.AcceptMulti, 825 } 826 return nil 827 } 828 829 // FunctionReturnLocationsIn holds arguments for the 830 // FunctionReturnLocationsRPC call. It holds the name of 831 // the function for which all return locations should be 832 // given. 833 type FunctionReturnLocationsIn struct { 834 // FnName is the name of the function for which all 835 // return locations should be given. 836 FnName string 837 } 838 839 // FunctionReturnLocationsOut holds the result of the FunctionReturnLocations 840 // RPC call. It provides the list of addresses that the given function returns, 841 // for example with a `RET` instruction or `CALL runtime.deferreturn`. 842 type FunctionReturnLocationsOut struct { 843 // Addrs is the list of all locations where the given function returns. 844 Addrs []uint64 845 } 846 847 // FunctionReturnLocations is the implements the client call of the same name. Look at client documentation for more information. 848 func (s *RPCServer) FunctionReturnLocations(in FunctionReturnLocationsIn, out *FunctionReturnLocationsOut) error { 849 addrs, err := s.debugger.FunctionReturnLocations(in.FnName) 850 if err != nil { 851 return err 852 } 853 *out = FunctionReturnLocationsOut{ 854 Addrs: addrs, 855 } 856 return nil 857 } 858 859 // ListDynamicLibrariesIn holds the arguments of ListDynamicLibraries 860 type ListDynamicLibrariesIn struct { 861 } 862 863 // ListDynamicLibrariesOut holds the return values of ListDynamicLibraries 864 type ListDynamicLibrariesOut struct { 865 List []api.Image 866 } 867 868 func (s *RPCServer) ListDynamicLibraries(in ListDynamicLibrariesIn, out *ListDynamicLibrariesOut) error { 869 imgs := s.debugger.ListDynamicLibraries() 870 out.List = make([]api.Image, 0, len(imgs)) 871 for i := range imgs { 872 out.List = append(out.List, api.ConvertImage(imgs[i])) 873 } 874 return nil 875 } 876 877 // ListPackagesBuildInfoIn holds the arguments of ListPackages. 878 type ListPackagesBuildInfoIn struct { 879 IncludeFiles bool 880 } 881 882 // ListPackagesBuildInfoOut holds the return values of ListPackages. 883 type ListPackagesBuildInfoOut struct { 884 List []api.PackageBuildInfo 885 } 886 887 // ListPackagesBuildInfo returns the list of packages used by the program along with 888 // the directory where each package was compiled and optionally the list of 889 // files constituting the package. 890 // Note that the directory path is a best guess and may be wrong is a tool 891 // other than cmd/go is used to perform the build. 892 func (s *RPCServer) ListPackagesBuildInfo(in ListPackagesBuildInfoIn, out *ListPackagesBuildInfoOut) error { 893 pkgs := s.debugger.ListPackagesBuildInfo(in.IncludeFiles) 894 out.List = make([]api.PackageBuildInfo, 0, len(pkgs)) 895 for _, pkg := range pkgs { 896 var files []string 897 898 if len(pkg.Files) > 0 { 899 files = make([]string, 0, len(pkg.Files)) 900 for file := range pkg.Files { 901 files = append(files, file) 902 } 903 } 904 905 sort.Strings(files) 906 907 out.List = append(out.List, api.PackageBuildInfo{ 908 ImportPath: pkg.ImportPath, 909 DirectoryPath: pkg.DirectoryPath, 910 Files: files, 911 }) 912 } 913 return nil 914 } 915 916 // ExamineMemoryIn holds the arguments of ExamineMemory 917 type ExamineMemoryIn struct { 918 Address uint64 919 Length int 920 } 921 922 // ExaminedMemoryOut holds the return values of ExamineMemory 923 type ExaminedMemoryOut struct { 924 Mem []byte 925 IsLittleEndian bool 926 } 927 928 func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error { 929 if arg.Length > 1000 { 930 return fmt.Errorf("len must be less than or equal to 1000") 931 } 932 Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length) 933 if err != nil { 934 return err 935 } 936 937 out.Mem = Mem 938 out.IsLittleEndian = true //TODO: get byte order from debugger.target.BinInfo().Arch 939 940 return nil 941 } 942 943 type StopRecordingIn struct { 944 } 945 946 type StopRecordingOut struct { 947 } 948 949 func (s *RPCServer) StopRecording(arg StopRecordingIn, cb service.RPCCallback) { 950 close(cb.SetupDoneChan()) 951 var out StopRecordingOut 952 err := s.debugger.StopRecording() 953 if err != nil { 954 cb.Return(nil, err) 955 return 956 } 957 cb.Return(out, nil) 958 } 959 960 type DumpStartIn struct { 961 Destination string 962 } 963 964 type DumpStartOut struct { 965 State api.DumpState 966 } 967 968 // DumpStart starts a core dump to arg.Destination. 969 func (s *RPCServer) DumpStart(arg DumpStartIn, out *DumpStartOut) error { 970 err := s.debugger.DumpStart(arg.Destination) 971 if err != nil { 972 return err 973 } 974 out.State = *api.ConvertDumpState(s.debugger.DumpWait(0)) 975 return nil 976 } 977 978 type DumpWaitIn struct { 979 Wait int 980 } 981 982 type DumpWaitOut struct { 983 State api.DumpState 984 } 985 986 // DumpWait waits for the core dump to finish or for arg.Wait milliseconds. 987 // Wait == 0 means return immediately. 988 // Returns the core dump status 989 func (s *RPCServer) DumpWait(arg DumpWaitIn, out *DumpWaitOut) error { 990 out.State = *api.ConvertDumpState(s.debugger.DumpWait(time.Duration(arg.Wait) * time.Millisecond)) 991 return nil 992 } 993 994 type DumpCancelIn struct { 995 } 996 997 type DumpCancelOut struct { 998 } 999 1000 // DumpCancel cancels the core dump. 1001 func (s *RPCServer) DumpCancel(arg DumpCancelIn, out *DumpCancelOut) error { 1002 return s.debugger.DumpCancel() 1003 } 1004 1005 type CreateWatchpointIn struct { 1006 Scope api.EvalScope 1007 Expr string 1008 Type api.WatchType 1009 } 1010 1011 type CreateWatchpointOut struct { 1012 *api.Breakpoint 1013 } 1014 1015 func (s *RPCServer) CreateWatchpoint(arg CreateWatchpointIn, out *CreateWatchpointOut) error { 1016 var err error 1017 out.Breakpoint, err = s.debugger.CreateWatchpoint(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Expr, arg.Type) 1018 return err 1019 } 1020 1021 type BuildIDIn struct { 1022 } 1023 1024 type BuildIDOut struct { 1025 BuildID string 1026 } 1027 1028 func (s *RPCServer) BuildID(arg BuildIDIn, out *BuildIDOut) error { 1029 out.BuildID = s.debugger.BuildID() 1030 return nil 1031 }