mirror of
https://github.com/go-delve/delve.git
synced 2025-10-30 10:17:03 +08:00
Genericized slice reading
This commit is contained in:
@ -31,6 +31,8 @@ func foobar(baz string, bar FooBar) {
|
|||||||
a9 = (*FooBar)(nil)
|
a9 = (*FooBar)(nil)
|
||||||
a10 = a1[2:5]
|
a10 = a1[2:5]
|
||||||
a11 = [3]FooBar{{1, "a"}, {2, "b"}, {3, "c"}}
|
a11 = [3]FooBar{{1, "a"}, {2, "b"}, {3, "c"}}
|
||||||
|
a12 = []FooBar{{4, "d"}, {5, "e"}}
|
||||||
|
a13 = []*FooBar{{6, "f"}, {7, "g"}, {8, "h"}}
|
||||||
b1 = true
|
b1 = true
|
||||||
b2 = false
|
b2 = false
|
||||||
neg = -1
|
neg = -1
|
||||||
@ -46,7 +48,7 @@ func foobar(baz string, bar FooBar) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
barfoo()
|
barfoo()
|
||||||
fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@ -592,11 +592,11 @@ func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ i
|
|||||||
|
|
||||||
return fmt.Sprintf("*%s", val), nil
|
return fmt.Sprintf("*%s", val), nil
|
||||||
case *dwarf.StructType:
|
case *dwarf.StructType:
|
||||||
switch t.StructName {
|
switch {
|
||||||
case "string":
|
case t.StructName == "string":
|
||||||
return thread.readString(ptraddress)
|
return thread.readString(ptraddress)
|
||||||
case "[]int":
|
case strings.HasPrefix(t.StructName, "[]"):
|
||||||
return thread.readIntSlice(ptraddress, t)
|
return thread.readSlice(ptraddress, t)
|
||||||
default:
|
default:
|
||||||
// Recursively call extractValue to grab
|
// Recursively call extractValue to grab
|
||||||
// the value of all the members of the struct.
|
// the value of all the members of the struct.
|
||||||
@ -660,45 +660,79 @@ func (thread *ThreadContext) readString(addr uintptr) (string, error) {
|
|||||||
return *(*string)(unsafe.Pointer(&val)), nil
|
return *(*string)(unsafe.Pointer(&val)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (thread *ThreadContext) readIntSlice(addr uintptr, t *dwarf.StructType) (string, error) {
|
func (thread *ThreadContext) readSlice(addr uintptr, t *dwarf.StructType) (string, error) {
|
||||||
val, err := thread.readMemory(addr, uintptr(24))
|
var sliceLen, sliceCap int64
|
||||||
|
var arrayAddr uintptr
|
||||||
|
var arrayType dwarf.Type
|
||||||
|
for _, f := range t.Field {
|
||||||
|
switch f.Name {
|
||||||
|
case "array":
|
||||||
|
val, err := thread.readMemory(addr+uintptr(f.ByteOffset), ptrsize)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
arrayAddr = uintptr(binary.LittleEndian.Uint64(val))
|
||||||
|
// Dereference array type to get value type
|
||||||
|
ptrType, ok := f.Type.(*dwarf.PtrType)
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("Invalid type %s in slice array", f.Type)
|
||||||
|
}
|
||||||
|
arrayType = ptrType.Type
|
||||||
|
case "len":
|
||||||
|
lstr, err := thread.extractValue(nil, int64(addr+uintptr(f.ByteOffset)), f.Type, true)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
sliceLen, err = strconv.ParseInt(lstr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
case "cap":
|
||||||
|
cstr, err := thread.extractValue(nil, int64(addr+uintptr(f.ByteOffset)), f.Type, true)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
sliceCap, err = strconv.ParseInt(cstr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stride := arrayType.Size()
|
||||||
|
if _, ok := arrayType.(*dwarf.PtrType); ok {
|
||||||
|
stride = int64(ptrsize)
|
||||||
|
}
|
||||||
|
vals, err := thread.readArrayValues(arrayAddr, sliceLen, stride, arrayType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
a := binary.LittleEndian.Uint64(val[:8])
|
return fmt.Sprintf("[]%s len: %d, cap: %d, [%s]", arrayType, sliceLen, sliceCap, strings.Join(vals, ",")), nil
|
||||||
l := binary.LittleEndian.Uint64(val[8:16])
|
|
||||||
c := binary.LittleEndian.Uint64(val[16:24])
|
|
||||||
|
|
||||||
val, err = thread.readMemory(uintptr(a), uintptr(uint64(ptrsize)*l))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t.StructName {
|
|
||||||
case "[]int":
|
|
||||||
members := *(*[]int)(unsafe.Pointer(&val))
|
|
||||||
setSliceLength(unsafe.Pointer(&members), int(l))
|
|
||||||
return fmt.Sprintf("len: %d cap: %d %d", l, c, members), nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("Could not read slice")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (thread *ThreadContext) readArray(addr uintptr, t *dwarf.ArrayType) (string, error) {
|
func (thread *ThreadContext) readArray(addr uintptr, t *dwarf.ArrayType) (string, error) {
|
||||||
vals := make([]string, 0)
|
vals, err := thread.readArrayValues(addr, t.Count, t.ByteSize/t.Count, t.Type)
|
||||||
|
if err != nil {
|
||||||
stride := t.ByteSize / t.Count
|
return "", err
|
||||||
for i := int64(0); i < t.Count; i++ {
|
|
||||||
val, err := thread.extractValue(nil, int64(addr+uintptr(i*stride)), t.Type, false)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
vals = append(vals, val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s [%s]", t, strings.Join(vals, ",")), nil
|
return fmt.Sprintf("%s [%s]", t, strings.Join(vals, ",")), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (thread *ThreadContext) readArrayValues(addr uintptr, count int64, stride int64, t dwarf.Type) ([]string, error) {
|
||||||
|
vals := make([]string, 0)
|
||||||
|
|
||||||
|
for i := int64(0); i < count; i++ {
|
||||||
|
val, err := thread.extractValue(nil, int64(addr+uintptr(i*stride)), t, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (thread *ThreadContext) readInt(addr uintptr, size int64) (string, error) {
|
func (thread *ThreadContext) readInt(addr uintptr, size int64) (string, error) {
|
||||||
var n int64
|
var n int64
|
||||||
|
|
||||||
|
|||||||
@ -40,10 +40,12 @@ func TestVariableEvaluation(t *testing.T) {
|
|||||||
{"a1", "foofoofoofoofoofoo", "struct string", nil},
|
{"a1", "foofoofoofoofoofoo", "struct string", nil},
|
||||||
{"a10", "ofo", "struct string", nil},
|
{"a10", "ofo", "struct string", nil},
|
||||||
{"a11", "[3]main.FooBar [{Baz: 1, Bur: a},{Baz: 2, Bur: b},{Baz: 3, Bur: c}]", "[3]main.FooBar", nil},
|
{"a11", "[3]main.FooBar [{Baz: 1, Bur: a},{Baz: 2, Bur: b},{Baz: 3, Bur: c}]", "[3]main.FooBar", nil},
|
||||||
|
{"a12", "[]main.FooBar len: 2, cap: 2, [{Baz: 4, Bur: d},{Baz: 5, Bur: e}]", "struct []main.FooBar", nil},
|
||||||
|
{"a13", "[]*main.FooBar len: 3, cap: 3, [*{Baz: 6, Bur: f},*{Baz: 7, Bur: g},*{Baz: 8, Bur: h}]", "struct []*main.FooBar", nil},
|
||||||
{"a2", "6", "int", nil},
|
{"a2", "6", "int", nil},
|
||||||
{"a3", "7.23", "float64", nil},
|
{"a3", "7.23", "float64", nil},
|
||||||
{"a4", "[2]int [1,2]", "[2]int", nil},
|
{"a4", "[2]int [1,2]", "[2]int", nil},
|
||||||
{"a5", "len: 5 cap: 5 [1 2 3 4 5]", "struct []int", nil},
|
{"a5", "[]int len: 5, cap: 5, [1,2,3,4,5]", "struct []int", nil},
|
||||||
{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar", nil},
|
{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar", nil},
|
||||||
{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*main.FooBar", nil},
|
{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*main.FooBar", nil},
|
||||||
{"a8", "main.FooBar2 {Bur: 10, Baz: feh}", "main.FooBar2", nil},
|
{"a8", "main.FooBar2 {Bur: 10, Baz: feh}", "main.FooBar2", nil},
|
||||||
@ -70,7 +72,7 @@ func TestVariableEvaluation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
|
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
|
||||||
pc, _, _ := p.GoSymTable.LineToPC(fp, 48)
|
pc, _, _ := p.GoSymTable.LineToPC(fp, 50)
|
||||||
|
|
||||||
_, err := p.Break(pc)
|
_, err := p.Break(pc)
|
||||||
assertNoError(err, t, "Break() returned an error")
|
assertNoError(err, t, "Break() returned an error")
|
||||||
@ -101,7 +103,7 @@ func TestVariableFunctionScoping(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
|
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
|
||||||
pc, _, _ := p.GoSymTable.LineToPC(fp, 48)
|
pc, _, _ := p.GoSymTable.LineToPC(fp, 50)
|
||||||
|
|
||||||
_, err := p.Break(pc)
|
_, err := p.Break(pc)
|
||||||
assertNoError(err, t, "Break() returned an error")
|
assertNoError(err, t, "Break() returned an error")
|
||||||
@ -168,10 +170,12 @@ func TestLocalVariables(t *testing.T) {
|
|||||||
{"a1", "foofoofoofoofoofoo", "struct string", nil},
|
{"a1", "foofoofoofoofoofoo", "struct string", nil},
|
||||||
{"a10", "ofo", "struct string", nil},
|
{"a10", "ofo", "struct string", nil},
|
||||||
{"a11", "[3]main.FooBar [{Baz: 1, Bur: a},{Baz: 2, Bur: b},{Baz: 3, Bur: c}]", "[3]main.FooBar", nil},
|
{"a11", "[3]main.FooBar [{Baz: 1, Bur: a},{Baz: 2, Bur: b},{Baz: 3, Bur: c}]", "[3]main.FooBar", nil},
|
||||||
|
{"a12", "[]main.FooBar len: 2, cap: 2, [{Baz: 4, Bur: d},{Baz: 5, Bur: e}]", "struct []main.FooBar", nil},
|
||||||
|
{"a13", "[]*main.FooBar len: 3, cap: 3, [*{Baz: 6, Bur: f},*{Baz: 7, Bur: g},*{Baz: 8, Bur: h}]", "struct []*main.FooBar", nil},
|
||||||
{"a2", "6", "int", nil},
|
{"a2", "6", "int", nil},
|
||||||
{"a3", "7.23", "float64", nil},
|
{"a3", "7.23", "float64", nil},
|
||||||
{"a4", "[2]int [1,2]", "[2]int", nil},
|
{"a4", "[2]int [1,2]", "[2]int", nil},
|
||||||
{"a5", "len: 5 cap: 5 [1 2 3 4 5]", "struct []int", nil},
|
{"a5", "[]int len: 5, cap: 5, [1,2,3,4,5]", "struct []int", nil},
|
||||||
{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar", nil},
|
{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar", nil},
|
||||||
{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*main.FooBar", nil},
|
{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*main.FooBar", nil},
|
||||||
{"a8", "main.FooBar2 {Bur: 10, Baz: feh}", "main.FooBar2", nil},
|
{"a8", "main.FooBar2 {Bur: 10, Baz: feh}", "main.FooBar2", nil},
|
||||||
@ -195,7 +199,7 @@ func TestLocalVariables(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
|
withTestProcess(executablePath, t, func(p *DebuggedProcess) {
|
||||||
pc, _, _ := p.GoSymTable.LineToPC(fp, 48)
|
pc, _, _ := p.GoSymTable.LineToPC(fp, 50)
|
||||||
|
|
||||||
_, err := p.Break(pc)
|
_, err := p.Break(pc)
|
||||||
assertNoError(err, t, "Break() returned an error")
|
assertNoError(err, t, "Break() returned an error")
|
||||||
|
|||||||
Reference in New Issue
Block a user