Recently, I had to debug a number of failing Go batch pipelines. Because of how these pipelines are structured, it is prohibitively complicated to run them locally, so all I had was a core dump.
With a running program, I would expect call os.WriteFile("/tmp/b.bin", b, 0600) to write the contents of the byte slice b to /tmp/b.bin. Unfortunately this didn’t actually work in my test, but that’s probably worth a separate issue:
(dlv) call os.WriteFile("/tmp/b.bin", b, 0644)
> [runtime-fatal-throw] runtime.fatalsignal() third_party/go/gc/src/runtime/signal_unix.go:795 (hits goroutine(1):1 total:1) (PC: 0x558a764f39ae)
Warning: debugging optimized function
Command failed: could not find symbol value for os
Anyway, because I only have a core dump, I needed to find another way to dump the contents.
With the memory address and element count, we can try to display the slice contents:
(dlv) x -size 1 -count 0x1d6c 0x000000c005c80000
Command failed: count/len must be a positive integer
(dlv) x -size 1 -count 7532 0x000000c005c80000
Command failed: read memory range (count*size) must be less than or equal to 1000 bytes
I removed the 1000 bytes check from the code:
diff --git i/pkg/terminal/command.go w/pkg/terminal/command.go
index dc629437..4c0c19d6 100644
--- i/pkg/terminal/command.go
+++ w/pkg/terminal/command.go
@@ -2131,9 +2131,9 @@ 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 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")
diff --git i/service/rpc2/server.go w/service/rpc2/server.go
index f806873b..cbcd4d18 100644
--- i/service/rpc2/server.go
+++ w/service/rpc2/server.go
@@ -977,9 +977,9 @@ type ExaminedMemoryOut struct {
}
func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error {
- if arg.Length > 1000 {
- return fmt.Errorf("len must be less than or equal to 1000")
- }
+ // if arg.Length > 1000 {
+ // return fmt.Errorf("len must be less than or equal to 1000")
+ // }
Mem, err := s.debugger.ExamineMemory(arg.Address, arg.Length)
if err != nil {
return err
Now, dlv lets me print the memory contents, which I can redirect into a file using the transcript command:
…and then I can use xxd -r /tmp/b.hex > /tmp/b.bin (after deleting the command itself from /tmp/b.hex).
My feature request is for a command built into delve which can dump memory into a file. It would be tremendously useful and is rather hard to accomplish today (see above).
[Using dlv 1.22.1]
Recently, I had to debug a number of failing Go batch pipelines. Because of how these pipelines are structured, it is prohibitively complicated to run them locally, so all I had was a core dump.
With a running program, I would expect
call os.WriteFile("/tmp/b.bin", b, 0600)
to write the contents of the byte sliceb
to/tmp/b.bin
. Unfortunately this didn’t actually work in my test, but that’s probably worth a separate issue:Anyway, because I only have a core dump, I needed to find another way to dump the contents.
Luckily, I found https://www.youtube.com/watch?v=sV5f1dF8ZU0, which explains how to display the Go slice header:
With the memory address and element count, we can try to display the slice contents:
I removed the 1000 bytes check from the code:
Now, dlv lets me print the memory contents, which I can redirect into a file using the
transcript
command:However, dlv’s current format is not compatible with
xxd -r
, so would require further work to turn from hex back to binary.I found it easier to modify dlv’s printing:
With this modification, dlv will print like so:
…and then I can use
xxd -r /tmp/b.hex > /tmp/b.bin
(after deleting the command itself from /tmp/b.hex).My feature request is for a command built into delve which can dump memory into a file. It would be tremendously useful and is rather hard to accomplish today (see above).
Thanks