mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 02:36:18 +08:00 
			
		
		
		
	Genericized array reading
This commit is contained in:
		| @ -30,6 +30,7 @@ func foobar(baz string, bar FooBar) { | ||||
| 		a8  = FooBar2{Bur: 10, Baz: "feh"} | ||||
| 		a9  = (*FooBar)(nil) | ||||
| 		a10 = a1[2:5] | ||||
| 		a11 = [3]FooBar{{1, "a"}, {2, "b"}, {3, "c"}} | ||||
| 		b1  = true | ||||
| 		b2  = false | ||||
| 		neg = -1 | ||||
| @ -45,7 +46,7 @@ func foobar(baz string, bar FooBar) { | ||||
| 	) | ||||
|  | ||||
| 	barfoo() | ||||
| 	fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 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, b1, b2, baz, neg, i8, u8, u16, u32, u64, up, f32, i32, bar, f) | ||||
| } | ||||
|  | ||||
| func main() { | ||||
|  | ||||
| @ -448,7 +448,7 @@ func (thread *ThreadContext) evaluateStructMember(parentEntry *dwarf.Entry, read | ||||
| 			binary.LittleEndian.PutUint64(baseAddr, uint64(parentAddr)) | ||||
|  | ||||
| 			parentInstructions := append([]byte{op.DW_OP_addr}, baseAddr...) | ||||
| 			val, err := thread.extractValue(append(parentInstructions, memberInstr...), 0, t) | ||||
| 			val, err := thread.extractValue(append(parentInstructions, memberInstr...), 0, t, true) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| @ -490,7 +490,7 @@ func (thread *ThreadContext) extractVariableFromEntry(entry *dwarf.Entry) (*Vari | ||||
| 		return nil, fmt.Errorf("type assertion failed") | ||||
| 	} | ||||
|  | ||||
| 	val, err := thread.extractValue(instructions, 0, t) | ||||
| 	val, err := thread.extractValue(instructions, 0, t, true) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -556,7 +556,7 @@ func (thread *ThreadContext) extractVariableDataAddress(entry *dwarf.Entry, read | ||||
| // Extracts the value from the instructions given in the DW_AT_location entry. | ||||
| // 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{}) (string, error) { | ||||
| func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ interface{}, printStructName bool) (string, error) { | ||||
| 	var err error | ||||
|  | ||||
| 	if addr == 0 { | ||||
| @ -585,7 +585,7 @@ 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) | ||||
| 		val, err := thread.extractValue(nil, intaddr, t.Type, printStructName) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| @ -602,18 +602,21 @@ func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ i | ||||
| 			// 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) | ||||
| 				val, err := thread.extractValue(nil, field.ByteOffset+addr, field.Type, printStructName) | ||||
| 				if err != nil { | ||||
| 					return "", err | ||||
| 				} | ||||
|  | ||||
| 				fields = append(fields, fmt.Sprintf("%s: %s", field.Name, val)) | ||||
| 			} | ||||
| 			retstr := fmt.Sprintf("%s {%s}", t.StructName, strings.Join(fields, ", ")) | ||||
| 			return retstr, nil | ||||
| 			if printStructName { | ||||
| 				return fmt.Sprintf("%s {%s}", t.StructName, strings.Join(fields, ", ")), nil | ||||
| 			} else { | ||||
| 				return fmt.Sprintf("{%s}", strings.Join(fields, ", ")), nil | ||||
| 			} | ||||
| 		} | ||||
| 	case *dwarf.ArrayType: | ||||
| 		return thread.readIntArray(ptraddress, t) | ||||
| 		return thread.readArray(ptraddress, t) | ||||
| 	case *dwarf.IntType: | ||||
| 		return thread.readInt(ptraddress, t.ByteSize) | ||||
| 	case *dwarf.UintType: | ||||
| @ -681,23 +684,19 @@ func (thread *ThreadContext) readIntSlice(addr uintptr, t *dwarf.StructType) (st | ||||
| 	return "", fmt.Errorf("Could not read slice") | ||||
| } | ||||
|  | ||||
| func (thread *ThreadContext) readIntArray(addr uintptr, t *dwarf.ArrayType) (string, error) { | ||||
| 	val, err := thread.readMemory(addr, uintptr(t.ByteSize)) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| func (thread *ThreadContext) readArray(addr uintptr, t *dwarf.ArrayType) (string, error) { | ||||
| 	vals := make([]string, 0) | ||||
|  | ||||
| 	stride := t.ByteSize / t.Count | ||||
| 	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) | ||||
| 	} | ||||
|  | ||||
| 	switch t.Type.Size() { | ||||
| 	case 4: | ||||
| 		members := *(*[]uint32)(unsafe.Pointer(&val)) | ||||
| 		setSliceLength(unsafe.Pointer(&members), int(t.Count)) | ||||
| 		return fmt.Sprintf("%s %d", t, members), nil | ||||
| 	case 8: | ||||
| 		members := *(*[]uint64)(unsafe.Pointer(&val)) | ||||
| 		setSliceLength(unsafe.Pointer(&members), int(t.Count)) | ||||
| 		return fmt.Sprintf("%s %d", t, members), nil | ||||
| 	} | ||||
| 	return "", fmt.Errorf("Could not read array") | ||||
| 	return fmt.Sprintf("%s [%s]", t, strings.Join(vals, ",")), nil | ||||
| } | ||||
|  | ||||
| func (thread *ThreadContext) readInt(addr uintptr, size int64) (string, error) { | ||||
|  | ||||
| @ -39,9 +39,10 @@ func TestVariableEvaluation(t *testing.T) { | ||||
| 	testcases := []varTest{ | ||||
| 		{"a1", "foofoofoofoofoofoo", "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}, | ||||
| 		{"a2", "6", "int", 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}, | ||||
| 		{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar", nil}, | ||||
| 		{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*main.FooBar", nil}, | ||||
| @ -56,7 +57,7 @@ func TestVariableEvaluation(t *testing.T) { | ||||
| 		{"a9.Baz", "nil", "int", errors.New("a9 is nil")}, | ||||
| 		{"a9.NonExistent", "nil", "int", errors.New("a9 has no member NonExistent")}, | ||||
| 		{"a8", "main.FooBar2 {Bur: 10, Baz: feh}", "main.FooBar2", nil}, // reread variable after member | ||||
| 		{"i32", "[2]int32 [1 2]", "[2]int32", nil}, | ||||
| 		{"i32", "[2]int32 [1,2]", "[2]int32", nil}, | ||||
| 		{"b1", "true", "bool", nil}, | ||||
| 		{"b2", "false", "bool", nil}, {"i8", "1", "int8", nil}, | ||||
| 		{"u16", "65535", "uint16", nil}, | ||||
| @ -69,7 +70,7 @@ func TestVariableEvaluation(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	withTestProcess(executablePath, t, func(p *DebuggedProcess) { | ||||
| 		pc, _, _ := p.GoSymTable.LineToPC(fp, 47) | ||||
| 		pc, _, _ := p.GoSymTable.LineToPC(fp, 48) | ||||
|  | ||||
| 		_, err := p.Break(pc) | ||||
| 		assertNoError(err, t, "Break() returned an error") | ||||
| @ -100,7 +101,7 @@ func TestVariableFunctionScoping(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	withTestProcess(executablePath, t, func(p *DebuggedProcess) { | ||||
| 		pc, _, _ := p.GoSymTable.LineToPC(fp, 47) | ||||
| 		pc, _, _ := p.GoSymTable.LineToPC(fp, 48) | ||||
|  | ||||
| 		_, err := p.Break(pc) | ||||
| 		assertNoError(err, t, "Break() returned an error") | ||||
| @ -166,9 +167,10 @@ func TestLocalVariables(t *testing.T) { | ||||
| 			[]varTest{ | ||||
| 				{"a1", "foofoofoofoofoofoo", "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}, | ||||
| 				{"a2", "6", "int", 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}, | ||||
| 				{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar", nil}, | ||||
| 				{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*main.FooBar", nil}, | ||||
| @ -178,7 +180,7 @@ func TestLocalVariables(t *testing.T) { | ||||
| 				{"b2", "false", "bool", nil}, | ||||
| 				{"f", "main.barfoo", "func()", nil}, | ||||
| 				{"f32", "1.2", "float32", nil}, | ||||
| 				{"i32", "[2]int32 [1 2]", "[2]int32", nil}, | ||||
| 				{"i32", "[2]int32 [1,2]", "[2]int32", nil}, | ||||
| 				{"i8", "1", "int8", nil}, | ||||
| 				{"neg", "-1", "int", nil}, | ||||
| 				{"u16", "65535", "uint16", nil}, | ||||
| @ -193,7 +195,7 @@ func TestLocalVariables(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	withTestProcess(executablePath, t, func(p *DebuggedProcess) { | ||||
| 		pc, _, _ := p.GoSymTable.LineToPC(fp, 47) | ||||
| 		pc, _, _ := p.GoSymTable.LineToPC(fp, 48) | ||||
|  | ||||
| 		_, err := p.Break(pc) | ||||
| 		assertNoError(err, t, "Break() returned an error") | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 epipho
					epipho