Skip to content

Commit 52405ba

Browse files
authored
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
1 parent 4a5350f commit 52405ba

File tree

4 files changed

+51
-30
lines changed

4 files changed

+51
-30
lines changed

Documentation/cli/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ Examine memory:
354354
examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address>
355355
examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] -x <expression>
356356

357-
Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal).
357+
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.
358358
Length is the number of bytes (default 1) and must be less than or equal to 1000.
359359
Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'.
360360
Expression can be an integer expression or pointer value of the memory location to examine.

pkg/terminal/command.go

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ Examine memory:
586586
examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address>
587587
examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] -x <expression>
588588
589-
Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal).
589+
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.
590590
Length is the number of bytes (default 1) and must be less than or equal to 1000.
591591
Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'.
592592
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 {
20572057

20582058
// Default value
20592059
priFmt := byte('x')
2060-
count := 1
2061-
size := 1
2060+
count := int64(1)
2061+
size := int64(1)
20622062
isExpr := false
2063+
rawout := false
20632064

20642065
// nextArg returns the next argument that is not an empty string, if any, and
20652066
// advances the args slice to the position after that.
@@ -2085,27 +2086,31 @@ loop:
20852086
if arg == "" {
20862087
return errors.New("expected argument after -fmt")
20872088
}
2088-
fmtMapToPriFmt := map[string]byte{
2089-
"oct": 'o',
2090-
"octal": 'o',
2091-
"hex": 'x',
2092-
"hexadecimal": 'x',
2093-
"dec": 'd',
2094-
"decimal": 'd',
2095-
"bin": 'b',
2096-
"binary": 'b',
2097-
}
2098-
priFmt, ok = fmtMapToPriFmt[arg]
2099-
if !ok {
2100-
return fmt.Errorf("%q is not a valid format", arg)
2089+
if arg == "raw" {
2090+
rawout = true
2091+
} else {
2092+
fmtMapToPriFmt := map[string]byte{
2093+
"oct": 'o',
2094+
"octal": 'o',
2095+
"hex": 'x',
2096+
"hexadecimal": 'x',
2097+
"dec": 'd',
2098+
"decimal": 'd',
2099+
"bin": 'b',
2100+
"binary": 'b',
2101+
}
2102+
priFmt, ok = fmtMapToPriFmt[arg]
2103+
if !ok {
2104+
return fmt.Errorf("%q is not a valid format", arg)
2105+
}
21012106
}
21022107
case "-count", "-len":
21032108
arg := nextArg()
21042109
if arg == "" {
21052110
return errors.New("expected argument after -count/-len")
21062111
}
21072112
var err error
2108-
count, err = strconv.Atoi(arg)
2113+
count, err = strconv.ParseInt(arg, 0, 64)
21092114
if err != nil || count <= 0 {
21102115
return errors.New("count/len must be a positive integer")
21112116
}
@@ -2115,7 +2120,7 @@ loop:
21152120
return errors.New("expected argument after -size")
21162121
}
21172122
var err error
2118-
size, err = strconv.Atoi(arg)
2123+
size, err = strconv.ParseInt(arg, 0, 64)
21192124
if err != nil || size <= 0 || size > 8 {
21202125
return errors.New("size must be a positive integer (<=8)")
21212126
}
@@ -2131,11 +2136,6 @@ loop:
21312136
}
21322137
}
21332138

2134-
// TODO, maybe configured by user.
2135-
if count*size > 1000 {
2136-
return errors.New("read memory range (count*size) must be less than or equal to 1000 bytes")
2137-
}
2138-
21392139
if len(args) == 0 {
21402140
return errors.New("no address specified")
21412141
}
@@ -2169,12 +2169,28 @@ loop:
21692169
}
21702170
}
21712171

2172-
memArea, isLittleEndian, err := t.client.ExamineMemory(address, count*size)
2173-
if err != nil {
2174-
return err
2175-
}
21762172
t.stdout.pw.PageMaybe(nil)
2177-
fmt.Fprint(t.stdout, api.PrettyExamineMemory(uintptr(address), memArea, isLittleEndian, priFmt, size))
2173+
2174+
start := address
2175+
remsz := int(count * size)
2176+
2177+
for remsz > 0 {
2178+
reqsz := rpc2.ExamineMemoryLengthLimit
2179+
if reqsz > remsz {
2180+
reqsz = remsz
2181+
}
2182+
memArea, isLittleEndian, err := t.client.ExamineMemory(start, reqsz)
2183+
if err != nil {
2184+
return err
2185+
}
2186+
if rawout {
2187+
t.stdout.Write(memArea)
2188+
} else {
2189+
fmt.Fprint(t.stdout, api.PrettyExamineMemory(uintptr(start), memArea, isLittleEndian, priFmt, int(size)))
2190+
}
2191+
start += uint64(reqsz)
2192+
remsz -= reqsz
2193+
}
21782194
return nil
21792195
}
21802196

pkg/terminal/starbind/conv.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ func (v sliceAsStarlarkValue) Hash() (uint32, error) {
9797
}
9898

9999
func (v sliceAsStarlarkValue) String() string {
100+
if x, ok := v.v.Interface().([]byte); ok {
101+
return string(x)
102+
}
100103
return fmt.Sprintf("%#v", v.v)
101104
}
102105

service/rpc2/server.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,10 @@ type ExaminedMemoryOut struct {
977977
IsLittleEndian bool
978978
}
979979

980+
const ExamineMemoryLengthLimit = 1 << 16
981+
980982
func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error {
981-
if arg.Length > 1000 {
983+
if arg.Length > ExamineMemoryLengthLimit {
982984
return errors.New("len must be less than or equal to 1000")
983985
}
984986
Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length)

0 commit comments

Comments
 (0)