gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/proc_general_test.go (about)

     1  package proc
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"runtime"
     7  	"testing"
     8  	"unsafe"
     9  
    10  	protest "gitlab.com/Raven-IO/raven-delve/pkg/proc/test"
    11  )
    12  
    13  func ptrSizeByRuntimeArch() int {
    14  	return int(unsafe.Sizeof(uintptr(0)))
    15  }
    16  
    17  func TestIssue554(t *testing.T) {
    18  	// unsigned integer overflow in proc.(*memCache).contains was
    19  	// causing it to always return true for address 0xffffffffffffffff
    20  	mem := memCache{true, 0x20, make([]byte, 100), nil}
    21  	var addr uint64
    22  	switch ptrSizeByRuntimeArch() {
    23  	case 4:
    24  		addr = 0xffffffff
    25  	case 8:
    26  		addr = 0xffffffffffffffff
    27  	}
    28  	if mem.contains(addr, 40) {
    29  		t.Fatalf("should be false")
    30  	}
    31  }
    32  
    33  type dummyMem struct {
    34  	t     *testing.T
    35  	mem   []byte
    36  	base  uint64
    37  	reads []memRead
    38  }
    39  
    40  type memRead struct {
    41  	addr uint64
    42  	size int
    43  }
    44  
    45  func (dm *dummyMem) ReadMemory(buf []byte, addr uint64) (int, error) {
    46  	dm.t.Logf("read addr=%#x size=%#x\n", addr, len(buf))
    47  	dm.reads = append(dm.reads, memRead{addr, len(buf)})
    48  	a := int64(addr) - int64(dm.base)
    49  	if a < 0 {
    50  		panic("reading below base")
    51  	}
    52  	if int(a)+len(buf) > len(dm.mem) {
    53  		panic("reading beyond end of mem")
    54  	}
    55  	copy(buf, dm.mem[a:])
    56  	return len(buf), nil
    57  }
    58  
    59  func (dm *dummyMem) WriteMemory(uint64, []byte) (int, error) {
    60  	panic("not supported")
    61  }
    62  
    63  func TestReadCStringValue(t *testing.T) {
    64  	const tgt = "a test string"
    65  	const maxstrlen = 64
    66  
    67  	dm := &dummyMem{t: t}
    68  	dm.mem = make([]byte, maxstrlen)
    69  	copy(dm.mem, tgt)
    70  
    71  	for _, tc := range []struct {
    72  		base     uint64
    73  		numreads int
    74  	}{
    75  		{0x5000, 1},
    76  		{0x5001, 1},
    77  		{0x4fff, 2},
    78  		{uint64(0x5000 - len(tgt) - 1), 1},
    79  		{uint64(0x5000-len(tgt)-1) + 1, 2},
    80  	} {
    81  		t.Logf("base is %#x\n", tc.base)
    82  		dm.base = tc.base
    83  		dm.reads = dm.reads[:0]
    84  		out, done, err := readCStringValue(dm, tc.base, LoadConfig{MaxStringLen: maxstrlen})
    85  		if err != nil {
    86  			t.Errorf("base=%#x readCStringValue: %v", tc.base, err)
    87  		}
    88  		if !done {
    89  			t.Errorf("base=%#x expected done but wasn't", tc.base)
    90  		}
    91  		if out != tgt {
    92  			t.Errorf("base=%#x got %q expected %q", tc.base, out, tgt)
    93  		}
    94  		if len(dm.reads) != tc.numreads {
    95  			t.Errorf("base=%#x wrong number of reads %d (expected %d)", tc.base, len(dm.reads), tc.numreads)
    96  		}
    97  		if tc.base == 0x4fff && dm.reads[0].size != 1 {
    98  			t.Errorf("base=%#x first read in not of one byte", tc.base)
    99  		}
   100  	}
   101  }
   102  
   103  func assertNoError(err error, t testing.TB, s string) {
   104  	if err != nil {
   105  		_, file, line, _ := runtime.Caller(1)
   106  		fname := filepath.Base(file)
   107  		t.Fatalf("failed assertion at %s:%d: %s - %s\n", fname, line, s, err)
   108  	}
   109  }
   110  
   111  func TestDwarfVersion(t *testing.T) {
   112  	// Tests that we correctly read the version of compilation units
   113  	fixture := protest.BuildFixture("math", 0)
   114  	bi := NewBinaryInfo(runtime.GOOS, runtime.GOARCH)
   115  	// Use a fake entry point so LoadBinaryInfo does not error in case the binary is PIE.
   116  	const fakeEntryPoint = 1
   117  	assertNoError(bi.LoadBinaryInfo(fixture.Path, fakeEntryPoint, nil), t, "LoadBinaryInfo")
   118  	for _, cu := range bi.Images[0].compileUnits {
   119  		if cu.Version != 4 {
   120  			t.Errorf("compile unit %q at %#x has bad version %d", cu.name, cu.entry.Offset, cu.Version)
   121  		}
   122  	}
   123  }
   124  
   125  func TestRegabiFlagSentinel(t *testing.T) {
   126  	// Detect if the regabi flag in the producer string gets removed
   127  	if !protest.RegabiSupported() {
   128  		t.Skip("irrelevant before Go 1.17 or on non-amd64 architectures")
   129  	}
   130  	fixture := protest.BuildFixture("math", 0)
   131  	bi := NewBinaryInfo(runtime.GOOS, runtime.GOARCH)
   132  	// Use a fake entry point so LoadBinaryInfo does not error in case the binary is PIE.
   133  	const fakeEntryPoint = 1
   134  	assertNoError(bi.LoadBinaryInfo(fixture.Path, fakeEntryPoint, nil), t, "LoadBinaryInfo")
   135  	if !bi.regabi {
   136  		t.Errorf("regabi flag not set %s GOEXPERIMENT=%s", runtime.Version(), os.Getenv("GOEXPERIMENT"))
   137  	}
   138  }
   139  
   140  func TestGenericFunctionParser(t *testing.T) {
   141  	// Normal parsing
   142  
   143  	var testCases = []struct{ name, pkg, rcv, base string }{
   144  		{"gitlab.com/Raven-IO/raven-delve.afunc", "gitlab.com/Raven-IO/raven-delve", "", "afunc"},
   145  		{"gitlab.com/Raven-IO/raven-delve..afunc", "gitlab.com/Raven-IO/raven-delve", "", "afunc"}, // malformed
   146  		{"gitlab.com/Raven-IO/raven-delve.afunc[some/[thing].el se]", "gitlab.com/Raven-IO/raven-delve", "", "afunc[some/[thing].el se]"},
   147  		{"gitlab.com/Raven-IO/raven-delve.Receiver.afunc", "gitlab.com/Raven-IO/raven-delve", "Receiver", "afunc"},
   148  		{"gitlab.com/Raven-IO/raven-delve.(*Receiver).afunc", "gitlab.com/Raven-IO/raven-delve", "(*Receiver)", "afunc"},
   149  		{"gitlab.com/Raven-IO/raven-delve.Receiver.afunc[some/[thing].el se]", "gitlab.com/Raven-IO/raven-delve", "Receiver", "afunc[some/[thing].el se]"},       // malformed
   150  		{"gitlab.com/Raven-IO/raven-delve.(*Receiver).afunc[some/[thing].el se]", "gitlab.com/Raven-IO/raven-delve", "(*Receiver)", "afunc[some/[thing].el se]"}, // malformed
   151  		{"gitlab.com/Raven-IO/raven-delve.Receiver[some/[thing].el se].afunc", "gitlab.com/Raven-IO/raven-delve", "Receiver[some/[thing].el se]", "afunc"},
   152  		{"gitlab.com/Raven-IO/raven-delve.(*Receiver[some/[thing].el se]).afunc", "gitlab.com/Raven-IO/raven-delve", "(*Receiver[some/[thing].el se])", "afunc"},
   153  
   154  		{"gitlab.com/Raven-IO/raven-delve.afunc[.some/[thing].el se]", "gitlab.com/Raven-IO/raven-delve", "", "afunc[.some/[thing].el se]"},
   155  		{"gitlab.com/Raven-IO/raven-delve.Receiver.afunc[.some/[thing].el se]", "gitlab.com/Raven-IO/raven-delve", "Receiver", "afunc[.some/[thing].el se]"}, // malformed
   156  		{"gitlab.com/Raven-IO/raven-delve.Receiver[.some/[thing].el se].afunc", "gitlab.com/Raven-IO/raven-delve", "Receiver[.some/[thing].el se]", "afunc"},
   157  		{"gitlab.com/Raven-IO/raven-delve.(*Receiver[.some/[thing].el se]).afunc", "gitlab.com/Raven-IO/raven-delve", "(*Receiver[.some/[thing].el se])", "afunc"},
   158  	}
   159  
   160  	for _, tc := range testCases {
   161  		fn := &Function{Name: tc.name}
   162  		if fn.PackageName() != tc.pkg {
   163  			t.Errorf("Package name mismatch: %q %q", tc.pkg, fn.PackageName())
   164  		}
   165  		if fn.ReceiverName() != tc.rcv {
   166  			t.Errorf("Receiver name mismatch: %q %q", tc.rcv, fn.ReceiverName())
   167  		}
   168  		if fn.BaseName() != tc.base {
   169  			t.Errorf("Base name mismatch: %q %q", tc.base, fn.BaseName())
   170  		}
   171  	}
   172  }