Skip to content

Commit

Permalink
*: function call injection for go 1.11
Browse files Browse the repository at this point in the history
Implements the function call injection protocol introduced in go 1.11
by https://go-review.googlesource.com/c/go/+/109699.

This is only the basic support, see TODO comments in pkg/proc/fncall.go
for a list of missing features.

Updates go-delve#119
  • Loading branch information
aarzilli committed Jun 18, 2018
1 parent 2a2d104 commit 7ffc215
Show file tree
Hide file tree
Showing 43 changed files with 1,064 additions and 132 deletions.
5 changes: 5 additions & 0 deletions Documentation/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Command | Description
[args](#args) | Print function arguments.
[break](#break) | Sets a breakpoint.
[breakpoints](#breakpoints) | Print out info for active breakpoints.
[call](#call) | Resumes process, injecting a function call (EXPERIMENTAL!!!)
[check](#check) | Creates a checkpoint at the current position.
[checkpoints](#checkpoints) | Print out info for existing checkpoints.
[clear](#clear) | Deletes breakpoint.
Expand Down Expand Up @@ -68,6 +69,10 @@ Print out info for active breakpoints.

Aliases: bp

## call
Resumes process, injecting a function call (EXPERIMENTAL!!!)


## check
Creates a checkpoint at the current position.

Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Pass flags to the program you are debugging using `--`, for example:
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_attach.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dlv attach pid [executable]
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dlv connect addr
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_core.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dlv core <executable> <core>
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dlv debug [package]
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dlv exec <path/to/binary>
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_replay.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dlv replay [trace directory]
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dlv run
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_test.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dlv test [package]
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_trace.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dlv trace [package] regexp
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
1 change: 1 addition & 0 deletions Documentation/usage/dlv_version.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dlv version
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.
--wd string Working directory for running the program. (default ".")
```
Expand Down
37 changes: 37 additions & 0 deletions _fixtures/fncall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"fmt"
"runtime"
)

func callstacktrace() (stacktrace string) {
for skip := 0; ; skip++ {
pc, file, line, ok := runtime.Caller(skip)
if !ok {
break
}
fn := runtime.FuncForPC(pc)
stacktrace += fmt.Sprintf("in %s at %s:%d\n", fn.Name(), file, line)
}
return stacktrace
}

func call1(a, b int) int {
fmt.Printf("first: %d second: %d\n", a, b)
return a + b
}

func callpanic() {
fmt.Printf("about to panic\n")
panic("callpanic panicked")
}

var zero = 0

func main() {
one, two := 1, 2
runtime.Breakpoint()
call1(one, two)
fmt.Println(one, two, zero, callpanic, callstacktrace)
}
1 change: 1 addition & 0 deletions cmd/dlv/cmds/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func New(docCall bool) *cobra.Command {
lldbout Copy output from debugserver/lldb to standard output
debuglineerr Log recoverable errors reading .debug_line
rpc Log all RPC messages
fncall Log function call protocol
Defaults to "debugger" when logging is enabled with --log.`)
RootCommand.PersistentFlags().BoolVarP(&Headless, "headless", "", false, "Run debug server only, in headless mode.")
RootCommand.PersistentFlags().BoolVarP(&AcceptMulti, "accept-multiclient", "", false, "Allows a headless server to accept multiple client connections. Note that the server API is not reentrant and clients will have to coordinate.")
Expand Down
8 changes: 8 additions & 0 deletions pkg/logflags/logflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var gdbWire = false
var lldbServerOutput = false
var debugLineErrors = false
var rpc = false
var fnCall = false

// GdbWire returns true if the gdbserial package should log all the packets
// exchanged with the stub.
Expand Down Expand Up @@ -41,6 +42,11 @@ func RPC() bool {
return rpc
}

// FnCall returns true if the function call protocol should be logged.
func FnCall() bool {
return fnCall
}

var errLogstrWithoutLog = errors.New("--log-output specified without --log")

// Setup sets debugger flags based on the contents of logstr.
Expand Down Expand Up @@ -69,6 +75,8 @@ func Setup(logFlag bool, logstr string) error {
debugLineErrors = true
case "rpc":
rpc = true
case "fncall":
fnCall = true
}
}
return nil
Expand Down
5 changes: 5 additions & 0 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,11 @@ func (bi *BinaryInfo) Producer() string {
return ""
}

// Type returns the Dwarf type entry at `offset`.
func (bi *BinaryInfo) Type(offset dwarf.Offset) (godwarf.Type, error) {
return godwarf.ReadType(bi.dwarf, offset, bi.typeCache)
}

// ELF ///////////////////////////////////////////////////////////////

func (bi *BinaryInfo) LoadBinaryInfoElf(path string, wg *sync.WaitGroup) error {
Expand Down
19 changes: 3 additions & 16 deletions pkg/proc/breakpoints.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package proc

import (
"debug/dwarf"
"errors"
"fmt"
"go/ast"
Expand Down Expand Up @@ -385,8 +384,6 @@ func (rbpi *returnBreakpointInfo) Collect(thread Thread) []*Variable {
return nil
}

bi := thread.BinInfo()

g, err := GetG(thread)
if err != nil {
return returnInfoError("could not get g", err, thread)
Expand All @@ -407,22 +404,12 @@ func (rbpi *returnBreakpointInfo) Collect(thread Thread) []*Variable {
return nil
}

// Alter the eval scope so that it looks like we are at the entry point of
// the function we just returned from.
// This involves changing the location (PC, function...) as well as
// anything related to the stack pointer (SP, CFA, FrameBase).
scope.PC = rbpi.fn.Entry
scope.Fn = rbpi.fn
scope.File, scope.Line, _ = bi.PCToLine(rbpi.fn.Entry)
scope.Regs.CFA = rbpi.frameOffset + int64(g.stackhi)
scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = uint64(rbpi.spOffset + int64(g.stackhi))

bi.dwarfReader.Seek(rbpi.fn.offset)
e, err := bi.dwarfReader.Next()
oldFrameOffset := rbpi.frameOffset + int64(g.stackhi)
oldSP := uint64(rbpi.spOffset + int64(g.stackhi))
err = fakeFunctionEntryScope(scope, rbpi.fn, oldFrameOffset, oldSP)
if err != nil {
return returnInfoError("could not read function entry", err, thread)
}
scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs)

vars, err := scope.Locals()
if err != nil {
Expand Down
16 changes: 16 additions & 0 deletions pkg/proc/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ func (t *Thread) Registers(floatingPoint bool) (proc.Registers, error) {
return r, nil
}

func (t *Thread) RestoreRegisters(proc.SavedRegisters) error {
return errors.New("not supported")
}

func (t *Thread) Arch() proc.Arch {
return t.p.bi.Arch
}
Expand All @@ -263,6 +267,14 @@ func (t *Thread) Common() *proc.CommonThread {
return &t.common
}

func (t *Thread) SetPC(uint64) error {
return errors.New("not supported")
}

func (t *Thread) SetSP(uint64) error {
return errors.New("not supported")
}

func (p *Process) Breakpoints() *proc.BreakpointMap {
return &p.breakpoints
}
Expand Down Expand Up @@ -409,3 +421,7 @@ func (r *Registers) Slice() []proc.Register {
out = append(out, r.fpregs...)
return out
}

func (r *Registers) Save() proc.SavedRegisters {
return r
}
5 changes: 0 additions & 5 deletions pkg/proc/core/linux_amd64_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"debug/elf"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -237,10 +236,6 @@ func (r *LinuxCoreRegisters) Get(n int) (uint64, error) {
return 0, proc.UnknownRegisterError
}

func (r *LinuxCoreRegisters) SetPC(proc.Thread, uint64) error {
return errors.New("not supported")
}

// readCore reads a core file from corePath corresponding to the executable at
// exePath. For details on the Linux ELF core format, see:
// http://www.gabriel.urdhr.fr/2015/05/29/core-file/,
Expand Down
Loading

0 comments on commit 7ffc215

Please sign in to comment.