Skip to content

Commit

Permalink
terminal,service: add raw examinemem dump
Browse files Browse the repository at this point in the history
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
  • Loading branch information
aarzilli committed May 14, 2024
1 parent b4fc206 commit 1ab504a
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 38 deletions.
6 changes: 3 additions & 3 deletions Documentation/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ Examine memory:
examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address>
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.
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.
Expand Down Expand Up @@ -741,10 +741,10 @@ Aliases: t
## transcript
Appends command output to a file.

transcript [-t] [-x] <output file>
transcript [-t] [-x] [-n] <output file>
transcript -off

Output of Delve's command is appended to the specified output file. If '-t' is specified and the output file exists it is truncated. If '-x' is specified output to stdout is suppressed instead.
Output of Delve's command is appended to the specified output file. If '-t' is specified and the output file exists it is truncated. If '-x' is specified output to stdout is suppressed. If [-n] input echo to the transcript file is disabled.

Using the -off option disables the transcript.

Expand Down
81 changes: 50 additions & 31 deletions pkg/terminal/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ Examine memory:
examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address>
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.
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.
Expand Down Expand Up @@ -615,10 +615,10 @@ The core dump is always written in ELF, even on systems (windows, macOS) where t

{aliases: []string{"transcript"}, cmdFn: transcript, helpMsg: `Appends command output to a file.
transcript [-t] [-x] <output file>
transcript [-t] [-x] [-n] <output file>
transcript -off
Output of Delve's command is appended to the specified output file. If '-t' is specified and the output file exists it is truncated. If '-x' is specified output to stdout is suppressed instead.
Output of Delve's command is appended to the specified output file. If '-t' is specified and the output file exists it is truncated. If '-x' is specified output to stdout is suppressed. If [-n] input echo to the transcript file is disabled.
Using the -off option disables the transcript.`},

Expand Down Expand Up @@ -2057,9 +2057,10 @@ func examineMemoryCmd(t *Term, ctx callContext, argstr string) error {

// Default value
priFmt := byte('x')
count := 1
size := 1
count := int64(1)
size := int64(1)
isExpr := false
rawout := false

// nextArg returns the next argument that is not an empty string, if any, and
// advances the args slice to the position after that.
Expand All @@ -2085,27 +2086,31 @@ loop:
if arg == "" {
return fmt.Errorf("expected argument after -fmt")
}
fmtMapToPriFmt := map[string]byte{
"oct": 'o',
"octal": 'o',
"hex": 'x',
"hexadecimal": 'x',
"dec": 'd',
"decimal": 'd',
"bin": 'b',
"binary": 'b',
}
priFmt, ok = fmtMapToPriFmt[arg]
if !ok {
return fmt.Errorf("%q is not a valid format", arg)
if arg == "raw" {
rawout = true
} else {
fmtMapToPriFmt := map[string]byte{
"oct": 'o',
"octal": 'o',
"hex": 'x',
"hexadecimal": 'x',
"dec": 'd',
"decimal": 'd',
"bin": 'b',
"binary": 'b',
}
priFmt, ok = fmtMapToPriFmt[arg]
if !ok {
return fmt.Errorf("%q is not a valid format", arg)
}
}
case "-count", "-len":
arg := nextArg()
if arg == "" {
return fmt.Errorf("expected argument after -count/-len")
}
var err error
count, err = strconv.Atoi(arg)
count, err = strconv.ParseInt(arg, 0, 64)
if err != nil || count <= 0 {
return fmt.Errorf("count/len must be a positive integer")
}
Expand All @@ -2115,7 +2120,7 @@ loop:
return fmt.Errorf("expected argument after -size")
}
var err error
size, err = strconv.Atoi(arg)
size, err = strconv.ParseInt(arg, 0, 64)
if err != nil || size <= 0 || size > 8 {
return fmt.Errorf("size must be a positive integer (<=8)")
}
Expand All @@ -2131,11 +2136,6 @@ loop:
}
}

// TODO, maybe configured by user.
if count*size > 1000 {
return fmt.Errorf("read memory range (count*size) must be less than or equal to 1000 bytes")
}

if len(args) == 0 {
return fmt.Errorf("no address specified")
}
Expand Down Expand Up @@ -2169,12 +2169,28 @@ loop:
}
}

memArea, isLittleEndian, err := t.client.ExamineMemory(address, count*size)
if err != nil {
return err
}
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
}

Expand Down Expand Up @@ -3355,9 +3371,12 @@ func transcript(t *Term, ctx callContext, args string) error {
truncate := false
fileOnly := false
disable := false
echo := true
path := ""
for _, arg := range argv {
switch arg {
case "-n":
echo = false
case "-x":
fileOnly = true
case "-t":
Expand Down Expand Up @@ -3397,7 +3416,7 @@ func transcript(t *Term, ctx callContext, args string) error {
return err
}

t.stdout.TranscribeTo(fh, fileOnly)
t.stdout.TranscribeTo(fh, fileOnly, echo)
return nil
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/terminal/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import (
// transcriptWriter writes to a pagingWriter and also, optionally, to a
// buffered file.
type transcriptWriter struct {
fileOnly bool
fileOnly, echo bool

pw *pagingWriter
file *bufio.Writer
fh io.Closer
Expand Down Expand Up @@ -52,7 +53,7 @@ func (w *transcriptWriter) ColorizePrint(path string, reader io.ReadSeeker, star

// Echo outputs str only to the optional transcript file.
func (w *transcriptWriter) Echo(str string) {
if w.file != nil {
if w.echo && w.file != nil {
w.file.WriteString(str)
}
}
Expand Down Expand Up @@ -80,13 +81,14 @@ func (w *transcriptWriter) CloseTranscript() error {
// TranscribeTo starts transcribing the output to the specified file. If
// fileOnly is true the output will only go to the file, output to the
// io.Writer will be suppressed.
func (w *transcriptWriter) TranscribeTo(fh io.WriteCloser, fileOnly bool) {
func (w *transcriptWriter) TranscribeTo(fh io.WriteCloser, fileOnly, echo bool) {
if w.file == nil {
w.CloseTranscript()
}
w.fh = fh
w.file = bufio.NewWriter(fh)
w.fileOnly = fileOnly
w.echo = echo
}

// pagingWriter writes to w. If PageMaybe is called, after a large amount of
Expand Down
4 changes: 3 additions & 1 deletion service/rpc2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -976,8 +976,10 @@ type ExaminedMemoryOut struct {
IsLittleEndian bool
}

const ExamineMemoryLengthLimit = 1 << 16

func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error {
if arg.Length > 1000 {
if arg.Length > ExamineMemoryLengthLimit {
return fmt.Errorf("len must be less than or equal to 1000")
}
Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length)
Expand Down

0 comments on commit 1ab504a

Please sign in to comment.