delve/pkg/proc/core_linux_amd64_test.go
Heschi Kreinick 423bcaa83a pkg/proc: add initial data structures for core support
Core files contain a variety of memory mappings either to files or
anonymous regions stored in the core file. These regions can overlap, so
figuring out what exactly to read can be tricky. This commit contains
a data structure, SplicedMemory, which accumulates mappings and reads
from the correct sources.
2017-04-18 13:25:11 -07:00

152 lines
2.9 KiB
Go

package proc
import (
"bytes"
"io/ioutil"
"os/exec"
"reflect"
"testing"
"fmt"
"path"
"github.com/derekparker/delve/pkg/proc/test"
)
func TestSplicedReader(t *testing.T) {
data := []byte{}
data2 := []byte{}
for i := 0; i < 100; i++ {
data = append(data, byte(i))
data2 = append(data2, byte(i+100))
}
type region struct {
data []byte
off uintptr
length uintptr
}
tests := []struct {
name string
regions []region
readAddr uintptr
readLen int
want []byte
}{
{
"Insert after",
[]region{
{data, 0, 1},
{data2, 1, 1},
},
0,
2,
[]byte{0, 101},
},
{
"Insert before",
[]region{
{data, 1, 1},
{data2, 0, 1},
},
0,
2,
[]byte{100, 1},
},
{
"Completely overwrite",
[]region{
{data, 1, 1},
{data2, 0, 3},
},
0,
3,
[]byte{100, 101, 102},
},
{
"Overwrite end",
[]region{
{data, 0, 2},
{data2, 1, 2},
},
0,
3,
[]byte{0, 101, 102},
},
{
"Overwrite start",
[]region{
{data, 0, 3},
{data2, 0, 2},
},
0,
3,
[]byte{100, 101, 2},
},
{
"Punch hole",
[]region{
{data, 0, 5},
{data2, 1, 3},
},
0,
5,
[]byte{0, 101, 102, 103, 4},
},
{
"Overlap two",
[]region{
{data, 10, 4},
{data, 14, 4},
{data2, 12, 4},
},
10,
8,
[]byte{10, 11, 112, 113, 114, 115, 16, 17},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
mem := &SplicedMemory{}
for _, region := range test.regions {
r := bytes.NewReader(region.data)
mem.Add(&OffsetReaderAt{r, 0}, region.off, region.length)
}
got := make([]byte, test.readLen)
n, err := mem.ReadMemory(got, test.readAddr)
if n != test.readLen || err != nil || !reflect.DeepEqual(got, test.want) {
t.Errorf("ReadAt = %v, %v, %v, want %v, %v, %v", n, err, got, test.readLen, nil, test.want)
}
})
}
}
func TestReadCore(t *testing.T) {
// This is all very fragile and won't work on hosts with non-default core patterns.
// Might be better to check in the core?
tempDir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal(err)
}
fix := test.BuildFixture("panic")
bashCmd := fmt.Sprintf("cd %v && ulimit -c unlimited && GOTRACEBACK=crash %v", tempDir, fix.Path)
exec.Command("bash", "-c", bashCmd).Run()
corePath := path.Join(tempDir, "core")
core, err := readCore(corePath, fix.Path)
if err != nil {
t.Fatal(err)
}
if len(core.Threads) == 0 {
t.Error("expected at least one thread")
}
// Punch through the abstraction to verify that we got some mappings.
spliced := core.MemoryReader.(*SplicedMemory)
// There should be at least an RO section, RW section, RX section, the heap, and a thread stack.
if len(spliced.readers) < 5 {
t.Errorf("expected at least 5 memory regions, got only %v", len(spliced.readers))
}
// Would be good to test more stuff but not sure what without reading debug information, etc.
}