delve/_fixtures/fncall.go

259 lines
5.1 KiB
Go
Raw Permalink Normal View History

package main
import (
"fmt"
"os"
"runtime"
"strings"
)
var call = "this is a variable named `call`"
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 call0(a, b int) {
fmt.Printf("call0: first: %d second: %d\n", a, b)
}
func call1(a, b int) int {
fmt.Printf("first: %d second: %d\n", a, b)
return a + b
}
func call2(a, b int) (int, int) {
fmt.Printf("call2: first: %d second: %d\n", a, b)
return a, b
}
func callexit() {
fmt.Printf("about to exit\n")
os.Exit(0)
}
func callpanic() {
fmt.Printf("about to panic\n")
panic("callpanic panicked")
}
func callbreak() {
fmt.Printf("about to break")
runtime.Breakpoint()
}
func stringsJoin(v []string, sep string) string {
// This is needed because strings.Join is in an optimized package and
// because of a bug in the compiler arguments of optimized functions don't
// have a location.
return strings.Join(v, sep)
}
type astruct struct {
X int
}
type a2struct struct {
Y int
}
func (a astruct) VRcvr(x int) string {
return fmt.Sprintf("%d + %d = %d", x, a.X, x+a.X)
}
func (pa *astruct) PRcvr(x int) string {
return fmt.Sprintf("%d - %d = %d", x, pa.X, x-pa.X)
}
type PRcvrable interface {
PRcvr(int) string
}
type VRcvrable interface {
VRcvr(int) string
}
var zero = 0
func makeclos(pa *astruct) func(int) string {
i := 0
return func(x int) string {
i++
return fmt.Sprintf("%d + %d + %d = %d", i, pa.X, x, i+pa.X+x)
}
}
var ga astruct
var globalPA2 *a2struct
func escapeArg(pa2 *a2struct) {
globalPA2 = pa2
}
proc: allow function calls to appear inside an expression (#1503) The initial implementation of the 'call' command required the function call to be the root expression, i.e. something like: double(3) + 1 was not allowed, because the root expression was the binary operator '+', not the function call. With this change expressions like the one above and others are allowed. This is the first step necessary to implement nested function calls (where the result of a function call is used as argument to another function call). This is implemented by replacing proc.CallFunction with proc.EvalExpressionWithCalls. EvalExpressionWithCalls will run proc.(*EvalScope).EvalExpression in a different goroutine. This goroutine, the 'eval' goroutine, will communicate with the main goroutine of the debugger by means of two channels: continueRequest and continueCompleted. The eval goroutine evaluates the expression recursively, when a function call is encountered it takes care of setting up the function call on the target program and writes a request to the continueRequest channel, this causes the 'main' goroutine to restart the target program by calling proc.Continue. Whenever Continue encounters a breakpoint that belongs to the function call injection protocol (runtime.debugCallV1 and associated functions) it writes to continueCompleted which resumes the 'eval' goroutine. The 'eval' goroutine takes care of implementing the function call injection protocol. When the expression is fully evaluated the 'eval' goroutine will write a special message to 'continueRequest' signaling that the expression evaluation is terminated which will cause Continue to return to the user. Updates #119
2019-05-09 15:29:58 +00:00
func square(x int) int {
return x * x
}
func intcallpanic(a int) int {
if a == 0 {
panic("panic requested")
}
return a
}
func onetwothree(n int) []int {
return []int{n + 1, n + 2, n + 3}
}
func curriedAdd(n int) func(int) int {
return func(m int) int {
return n + m
}
}
func getAStruct(n int) astruct {
return astruct{X: n}
}
func getAStructPtr(n int) *astruct {
return &astruct{X: n}
}
func getVRcvrableFromAStruct(n int) VRcvrable {
return astruct{X: n}
}
func getPRcvrableFromAStructPtr(n int) PRcvrable {
return &astruct{X: n}
}
func getVRcvrableFromAStructPtr(n int) VRcvrable {
return &astruct{X: n}
}
func noreturncall(n int) {
return
}
type Base struct {
y int
}
type Derived struct {
x int
Base
}
func (b *Base) Method() int {
return b.y
}
type X int
func (_ X) CallMe() {
println("foo")
}
type X2 int
func (_ X2) CallMe(i int) int {
return i * i
}
Go 1.17 support branch (#2451) * proc: support new Go 1.17 panic/defer mechanism Go 1.17 will create wrappers for deferred calls that take arguments. Change defer reading code so that wrappers are automatically unwrapped. Also the deferred function is called directly by runtime.gopanic, without going through runtime.callN which means that sometimes when a panic happens the stack is either: 0. deferred function call 1. deferred call wrapper 2. runtime.gopanic or: 0. deferred function call 1. runtime.gopanic instead of always being: 0. deferred function call 1. runtime.callN 2. runtime.gopanic the isPanicCall check is changed accordingly. * test: miscellaneous minor test fixes for Go 1.17 * proc: resolve inlined calls when stepping out of runtime.breakpoint Calls to runtime.Breakpoint are inlined in Go 1.17 when inlining is enabled, resolve inlined calls in stepInstructionOut. * proc: add support for debugCallV2 with regabi This change adds support for the new debug call protocol which had to change for the new register ABI introduced in Go 1.17. Summary of changes: - Abstracts over the debug call version depending on the Go version found in the binary. - Uses R12 instead of RAX as the debug protocol register when the binary is from Go 1.17 or later. - Creates a variable directly from the DWARF entry for function arguments to support passing arguments however the ABI expects. - Computes a very conservative stack frame size for the call when injecting a call into a Go process whose version is >=1.17. Co-authored-by: Michael Anthony Knyszek <mknyszek@google.com> Co-authored-by: Alessandro Arzilli <alessandro.arzilli@gmail.com> * TeamCity: enable tests on go-tip * goversion: version compatibility bump * TeamCity: fix go-tip builds on macOS/arm64 Co-authored-by: Michael Anthony Knyszek <mknyszek@google.com>
2021-07-08 15:47:53 +00:00
func regabistacktest(s1, s2, s3, s4, s5 string, n uint8) (string, string, string, string, string, uint8) {
return s1 + s2, s2 + s3, s3 + s4, s4 + s5, s5 + s1, 2 * n
}
func regabistacktest2(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10 int) (int, int, int, int, int, int, int, int, int, int) {
return n1 + n2, n2 + n3, n3 + n4, n4 + n5, n5 + n6, n6 + n7, n7 + n8, n8 + n9, n9 + n10, n10 + n1
}
func regabistacktest3(sargs [10]string, n uint8) (r [10]string, m uint8) {
for i := range sargs {
r[i] = sargs[i] + sargs[(i+1)%len(sargs)]
}
m = n * 3
return
}
func floatsum(a, b float64) float64 {
return a + b
}
type Issue2698 struct {
a uint32
b uint8
c uint8
d uintptr
}
func (i Issue2698) String() string {
return fmt.Sprintf("%d %d %d %d", i.a, i.b, i.c, i.d)
}
type Issue3364 struct {
a int
b uint32
}
func (i Issue3364) String() string {
return fmt.Sprintf("%d %d", i.a, i.b)
}
func main() {
one, two := 1, 2
intslice := []int{1, 2, 3}
stringslice := []string{"one", "two", "three"}
comma := ","
a := astruct{X: 3}
pa := &astruct{X: 6}
a2 := a2struct{Y: 7}
var pa2 *astruct
var str string = "old string value"
dap: use larger string type variable load limits in 'repl', 'variables' context (#2418) * dap: use larger variable load limits in 'repl', 'variables' context When evaluate requests are triggered in the context of 'repl' (DEBUG CONSOLE in VSCode) or 'variables' (copy values from VARIABLES section in VSCode), they are the result of human action and have more rooms to display. So it is not too bad to apply longer limits. Variable auto-loading for strings or arrays is nice but currently it's unclear to me how this should be integrated in the DEBUG CONSOLE or with the Copy Value feature. Until we have better ideas and tools, let's go with these larger limits. Unfortunately, the "Copy Value" from WATCH section triggers evaluate requests with "watch" context and we don't want to load large data automatically for "watch". So, users who want to query a large value should first copy the expression to DEBUG CONSOLE and evaluate it. Not ideal but not the end of the world either. Updates golang/vscode-go#1318 * dap: apply large limit only to the string type result * dap: move string reload logic to convertVariable* where other reload logic is Currently we are thinking string reload for evaluation as a temporary workaround until we figure out an intutitive way to present long strings. So, I hope moving this logic near other reload logic may be better. And, use the address based expression when reloading - when handling the function return values, we may not have an expression to use. * dap: make deep source check happy * dap: move string reevaluation logic back to onEvaluateRequest Reloading string variables is tricky if they are in registers. We don't attempt to reload them but for clarity, move this up to the onEvaluateRequest handler. For function call, use a generous limit for string load since the results are volatile. * dap: check variable isn't affected by evaluate in other context
2021-05-25 17:23:41 +00:00
longstrs := []string{"very long string 0123456789a0123456789b0123456789c0123456789d0123456789e0123456789f0123456789g012345678h90123456789i0123456789j0123456789"}
rast3 := [10]string{"one", "two", "three", "four", "five", "six", "seven", "height", "nine", "ten"}
var vable_a VRcvrable = a
var vable_pa VRcvrable = pa
var pable_pa PRcvrable = pa
var x X = 2
var x2 X2 = 2
issue2698 := Issue2698{
a: 1,
b: 2,
c: 3,
d: 4,
}
issue3364 := Issue3364{
a: 1,
b: 2,
}
fn2clos := makeclos(pa)
fn2glob := call1
fn2valmeth := pa.VRcvr
fn2ptrmeth := pa.PRcvr
var fn2nil func()
d := &Derived{3, Base{4}}
var ref strings.Builder
fmt.Fprintf(&ref, "blah")
runtime.Breakpoint() // breakpoint here
call1(one, two)
fn2clos(2)
strings.LastIndexByte(stringslice[1], 'w')
d.Method()
d.Base.Method()
x.CallMe()
fmt.Println(one, two, zero, call, call0, call2, callexit, callpanic, callbreak, callstacktrace, stringsJoin, intslice, stringslice, comma, a.VRcvr, a.PRcvr, pa, vable_a, vable_pa, pable_pa, fn2clos, fn2glob, fn2valmeth, fn2ptrmeth, fn2nil, ga, escapeArg, a2, square, intcallpanic, onetwothree, curriedAdd, getAStruct, getAStructPtr, getVRcvrableFromAStruct, getPRcvrableFromAStructPtr, getVRcvrableFromAStructPtr, pa2, noreturncall, str, d, x, x2.CallMe(5), longstrs, regabistacktest, regabistacktest2, issue2698.String(), issue3364.String(), regabistacktest3, rast3, floatsum, ref)
}