mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 18:57:18 +08:00 
			
		
		
		
	terminal,service: add raw examinemem dump (#3721)
Change the examinemem command to have a new format 'raw' that just prints the raw memory bytes. Change the transcript command to add a new flag that disables prompt echo to the output file. Fixes #3706
This commit is contained in:
		 Alessandro Arzilli
					Alessandro Arzilli
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							4a5350fd1f
						
					
				
				
					commit
					52405ba86b
				
			| @ -354,7 +354,7 @@ Examine memory: | |||||||
| 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address> | 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address> | ||||||
| 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] -x <expression> | 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] -x <expression> | ||||||
|  |  | ||||||
| Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal). | Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal) and raw. | ||||||
| Length is the number of bytes (default 1) and must be less than or equal to 1000. | Length is the number of bytes (default 1) and must be less than or equal to 1000. | ||||||
| Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'. | Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'. | ||||||
| Expression can be an integer expression or pointer value of the memory location to examine. | Expression can be an integer expression or pointer value of the memory location to examine. | ||||||
|  | |||||||
| @ -586,7 +586,7 @@ Examine memory: | |||||||
| 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address> | 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address> | ||||||
| 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] -x <expression> | 	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] -x <expression> | ||||||
|  |  | ||||||
| Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal). | Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal) and raw. | ||||||
| Length is the number of bytes (default 1) and must be less than or equal to 1000. | Length is the number of bytes (default 1) and must be less than or equal to 1000. | ||||||
| Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'. | Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'. | ||||||
| Expression can be an integer expression or pointer value of the memory location to examine. | Expression can be an integer expression or pointer value of the memory location to examine. | ||||||
| @ -2057,9 +2057,10 @@ func examineMemoryCmd(t *Term, ctx callContext, argstr string) error { | |||||||
|  |  | ||||||
| 	// Default value | 	// Default value | ||||||
| 	priFmt := byte('x') | 	priFmt := byte('x') | ||||||
| 	count := 1 | 	count := int64(1) | ||||||
| 	size := 1 | 	size := int64(1) | ||||||
| 	isExpr := false | 	isExpr := false | ||||||
|  | 	rawout := false | ||||||
|  |  | ||||||
| 	// nextArg returns the next argument that is not an empty string, if any, and | 	// nextArg returns the next argument that is not an empty string, if any, and | ||||||
| 	// advances the args slice to the position after that. | 	// advances the args slice to the position after that. | ||||||
| @ -2085,19 +2086,23 @@ loop: | |||||||
| 			if arg == "" { | 			if arg == "" { | ||||||
| 				return errors.New("expected argument after -fmt") | 				return errors.New("expected argument after -fmt") | ||||||
| 			} | 			} | ||||||
| 			fmtMapToPriFmt := map[string]byte{ | 			if arg == "raw" { | ||||||
| 				"oct":         'o', | 				rawout = true | ||||||
| 				"octal":       'o', | 			} else { | ||||||
| 				"hex":         'x', | 				fmtMapToPriFmt := map[string]byte{ | ||||||
| 				"hexadecimal": 'x', | 					"oct":         'o', | ||||||
| 				"dec":         'd', | 					"octal":       'o', | ||||||
| 				"decimal":     'd', | 					"hex":         'x', | ||||||
| 				"bin":         'b', | 					"hexadecimal": 'x', | ||||||
| 				"binary":      'b', | 					"dec":         'd', | ||||||
| 			} | 					"decimal":     'd', | ||||||
| 			priFmt, ok = fmtMapToPriFmt[arg] | 					"bin":         'b', | ||||||
| 			if !ok { | 					"binary":      'b', | ||||||
| 				return fmt.Errorf("%q is not a valid format", arg) | 				} | ||||||
|  | 				priFmt, ok = fmtMapToPriFmt[arg] | ||||||
|  | 				if !ok { | ||||||
|  | 					return fmt.Errorf("%q is not a valid format", arg) | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		case "-count", "-len": | 		case "-count", "-len": | ||||||
| 			arg := nextArg() | 			arg := nextArg() | ||||||
| @ -2105,7 +2110,7 @@ loop: | |||||||
| 				return errors.New("expected argument after -count/-len") | 				return errors.New("expected argument after -count/-len") | ||||||
| 			} | 			} | ||||||
| 			var err error | 			var err error | ||||||
| 			count, err = strconv.Atoi(arg) | 			count, err = strconv.ParseInt(arg, 0, 64) | ||||||
| 			if err != nil || count <= 0 { | 			if err != nil || count <= 0 { | ||||||
| 				return errors.New("count/len must be a positive integer") | 				return errors.New("count/len must be a positive integer") | ||||||
| 			} | 			} | ||||||
| @ -2115,7 +2120,7 @@ loop: | |||||||
| 				return errors.New("expected argument after -size") | 				return errors.New("expected argument after -size") | ||||||
| 			} | 			} | ||||||
| 			var err error | 			var err error | ||||||
| 			size, err = strconv.Atoi(arg) | 			size, err = strconv.ParseInt(arg, 0, 64) | ||||||
| 			if err != nil || size <= 0 || size > 8 { | 			if err != nil || size <= 0 || size > 8 { | ||||||
| 				return errors.New("size must be a positive integer (<=8)") | 				return errors.New("size must be a positive integer (<=8)") | ||||||
| 			} | 			} | ||||||
| @ -2131,11 +2136,6 @@ loop: | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// TODO, maybe configured by user. |  | ||||||
| 	if count*size > 1000 { |  | ||||||
| 		return errors.New("read memory range (count*size) must be less than or equal to 1000 bytes") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if len(args) == 0 { | 	if len(args) == 0 { | ||||||
| 		return errors.New("no address specified") | 		return errors.New("no address specified") | ||||||
| 	} | 	} | ||||||
| @ -2169,12 +2169,28 @@ loop: | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	memArea, isLittleEndian, err := t.client.ExamineMemory(address, count*size) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	t.stdout.pw.PageMaybe(nil) | 	t.stdout.pw.PageMaybe(nil) | ||||||
| 	fmt.Fprint(t.stdout, api.PrettyExamineMemory(uintptr(address), memArea, isLittleEndian, priFmt, size)) |  | ||||||
|  | 	start := address | ||||||
|  | 	remsz := int(count * size) | ||||||
|  |  | ||||||
|  | 	for remsz > 0 { | ||||||
|  | 		reqsz := rpc2.ExamineMemoryLengthLimit | ||||||
|  | 		if reqsz > remsz { | ||||||
|  | 			reqsz = remsz | ||||||
|  | 		} | ||||||
|  | 		memArea, isLittleEndian, err := t.client.ExamineMemory(start, reqsz) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		if rawout { | ||||||
|  | 			t.stdout.Write(memArea) | ||||||
|  | 		} else { | ||||||
|  | 			fmt.Fprint(t.stdout, api.PrettyExamineMemory(uintptr(start), memArea, isLittleEndian, priFmt, int(size))) | ||||||
|  | 		} | ||||||
|  | 		start += uint64(reqsz) | ||||||
|  | 		remsz -= reqsz | ||||||
|  | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -97,6 +97,9 @@ func (v sliceAsStarlarkValue) Hash() (uint32, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (v sliceAsStarlarkValue) String() string { | func (v sliceAsStarlarkValue) String() string { | ||||||
|  | 	if x, ok := v.v.Interface().([]byte); ok { | ||||||
|  | 		return string(x) | ||||||
|  | 	} | ||||||
| 	return fmt.Sprintf("%#v", v.v) | 	return fmt.Sprintf("%#v", v.v) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -977,8 +977,10 @@ type ExaminedMemoryOut struct { | |||||||
| 	IsLittleEndian bool | 	IsLittleEndian bool | ||||||
| } | } | ||||||
|  |  | ||||||
|  | const ExamineMemoryLengthLimit = 1 << 16 | ||||||
|  |  | ||||||
| func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error { | func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error { | ||||||
| 	if arg.Length > 1000 { | 	if arg.Length > ExamineMemoryLengthLimit { | ||||||
| 		return errors.New("len must be less than or equal to 1000") | 		return errors.New("len must be less than or equal to 1000") | ||||||
| 	} | 	} | ||||||
| 	Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length) | 	Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user