提交 c7fe4e3e 编写于 作者: E epipho 提交者: Derek Parker

Added limit to array size (64) and struct member recursion (2) when printing

上级 fe8e85e3
......@@ -13,6 +13,11 @@ type FooBar2 struct {
Baz string
}
type Nest struct {
Level int
Nest *Nest
}
func barfoo() {
a1 := "bur"
fmt.Println(a1)
......@@ -45,10 +50,12 @@ func foobar(baz string, bar FooBar) {
f32 = float32(1.2)
i32 = [2]int32{1, 2}
f = barfoo
ms = Nest{0, &Nest{1, &Nest{2, &Nest{3, &Nest{4, nil}}}}} // Test recursion capping
ba = make([]int, 200, 200) // Test array size capping
)
barfoo()
fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, b1, b2, baz, neg, i8, u8, u16, u32, u64, up, f32, i32, bar, f)
fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, b1, b2, baz, neg, i8, u8, u16, u32, u64, up, f32, i32, bar, f, ms, ba)
}
func main() {
......
......@@ -13,6 +13,11 @@ import (
"github.com/derekparker/delve/dwarf/reader"
)
const (
maxVariableRecurse = 1
maxArrayValues = 64
)
type Variable struct {
Name string
Value string
......@@ -558,6 +563,10 @@ func (thread *ThreadContext) extractVariableDataAddress(entry *dwarf.Entry, read
// We execute the stack program described in the DW_OP_* instruction stream, and
// then grab the value from the other processes memory.
func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ interface{}, printStructName bool) (string, error) {
return thread.extractValueInternal(instructions, addr, typ, printStructName, 0)
}
func (thread *ThreadContext) extractValueInternal(instructions []byte, addr int64, typ interface{}, printStructName bool, recurseLevel int) (string, error) {
var err error
if addr == 0 {
......@@ -590,7 +599,8 @@ func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ i
return fmt.Sprintf("%s nil", t.String()), nil
}
val, err := thread.extractValue(nil, intaddr, t.Type, printStructName)
// Don't increase the recursion level when dereferencing pointers
val, err := thread.extractValueInternal(nil, intaddr, t.Type, printStructName, recurseLevel)
if err != nil {
return "", err
}
......@@ -605,20 +615,26 @@ func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ i
default:
// Recursively call extractValue to grab
// the value of all the members of the struct.
fields := make([]string, 0, len(t.Field))
for _, field := range t.Field {
val, err := thread.extractValue(nil, field.ByteOffset+addr, field.Type, printStructName)
if err != nil {
return "", err
if recurseLevel <= maxVariableRecurse {
fields := make([]string, 0, len(t.Field))
for _, field := range t.Field {
val, err := thread.extractValueInternal(nil, field.ByteOffset+addr, field.Type, printStructName, recurseLevel+1)
if err != nil {
return "", err
}
fields = append(fields, fmt.Sprintf("%s: %s", field.Name, val))
}
fields = append(fields, fmt.Sprintf("%s: %s", field.Name, val))
if printStructName {
return fmt.Sprintf("%s {%s}", t.StructName, strings.Join(fields, ", ")), nil
}
return fmt.Sprintf("{%s}", strings.Join(fields, ", ")), nil
}
// no fields
if printStructName {
return fmt.Sprintf("%s {%s}", t.StructName, strings.Join(fields, ", ")), nil
} else {
return fmt.Sprintf("{%s}", strings.Join(fields, ", ")), nil
return fmt.Sprintf("%s {...}", t.StructName), nil
}
return "{...}", nil
}
case *dwarf.ArrayType:
return thread.readArray(ptraddress, t)
......@@ -736,6 +752,12 @@ func (thread *ThreadContext) readArrayValues(addr uintptr, count int64, stride i
vals := make([]string, 0)
for i := int64(0); i < count; i++ {
// Cap number of elements
if i >= maxArrayValues {
vals = append(vals, fmt.Sprintf("...+%d more", count-maxArrayValues))
break
}
val, err := thread.extractValue(nil, int64(addr+uintptr(i*stride)), t, false)
if err != nil {
return nil, err
......
......@@ -68,11 +68,13 @@ func TestVariableEvaluation(t *testing.T) {
{"u8", "255", "uint8", nil},
{"up", "5", "uintptr", nil},
{"f", "main.barfoo", "func()", nil},
{"ba", "[]int len: 200, cap: 200, [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...+136 more]", "struct []int", nil},
{"ms", "main.Nest {Level: 0, Nest: *main.Nest {Level: 1, Nest: *main.Nest {...}}}", "main.Nest", nil},
{"NonExistent", "", "", errors.New("could not find symbol value for NonExistent")},
}
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
pc, _, _ := p.GoSymTable.LineToPC(fp, 50)
pc, _, _ := p.GoSymTable.LineToPC(fp, 57)
_, err := p.Break(pc)
assertNoError(err, t, "Break() returned an error")
......@@ -103,7 +105,7 @@ func TestVariableFunctionScoping(t *testing.T) {
}
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
pc, _, _ := p.GoSymTable.LineToPC(fp, 50)
pc, _, _ := p.GoSymTable.LineToPC(fp, 57)
_, err := p.Break(pc)
assertNoError(err, t, "Break() returned an error")
......@@ -118,7 +120,7 @@ func TestVariableFunctionScoping(t *testing.T) {
assertNoError(err, t, "Unable to find variable a1")
// Move scopes, a1 exists here by a2 does not
pc, _, _ = p.GoSymTable.LineToPC(fp, 18)
pc, _, _ = p.GoSymTable.LineToPC(fp, 23)
_, err = p.Break(pc)
assertNoError(err, t, "Break() returned an error")
......@@ -182,10 +184,12 @@ func TestLocalVariables(t *testing.T) {
{"a9", "*main.FooBar nil", "*main.FooBar", nil},
{"b1", "true", "bool", nil},
{"b2", "false", "bool", nil},
{"ba", "[]int len: 200, cap: 200, [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...+136 more]", "struct []int", nil},
{"f", "main.barfoo", "func()", nil},
{"f32", "1.2", "float32", nil},
{"i32", "[2]int32 [1,2]", "[2]int32", nil},
{"i8", "1", "int8", nil},
{"ms", "main.Nest {Level: 0, Nest: *main.Nest {Level: 1, Nest: *main.Nest {...}}}", "main.Nest", nil},
{"neg", "-1", "int", nil},
{"u16", "65535", "uint16", nil},
{"u32", "4294967295", "uint32", nil},
......@@ -199,7 +203,7 @@ func TestLocalVariables(t *testing.T) {
}
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
pc, _, _ := p.GoSymTable.LineToPC(fp, 50)
pc, _, _ := p.GoSymTable.LineToPC(fp, 57)
_, err := p.Break(pc)
assertNoError(err, t, "Break() returned an error")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册