github.com/undoio/delve@v1.9.0/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 "github.com/undoio/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{uint64(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 assertNoError(bi.LoadBinaryInfo(fixture.Path, 0, nil), t, "LoadBinaryInfo") 116 for _, cu := range bi.Images[0].compileUnits { 117 if cu.Version != 4 { 118 t.Errorf("compile unit %q at %#x has bad version %d", cu.name, cu.entry.Offset, cu.Version) 119 } 120 } 121 } 122 123 func TestRegabiFlagSentinel(t *testing.T) { 124 // Detect if the regabi flag in the producer string gets removed 125 if !protest.RegabiSupported() { 126 t.Skip("irrelevant before Go 1.17 or on non-amd64 architectures") 127 } 128 fixture := protest.BuildFixture("math", 0) 129 bi := NewBinaryInfo(runtime.GOOS, runtime.GOARCH) 130 assertNoError(bi.LoadBinaryInfo(fixture.Path, 0, nil), t, "LoadBinaryInfo") 131 if !bi.regabi { 132 t.Errorf("regabi flag not set %s GOEXPERIMENT=%s", runtime.Version(), os.Getenv("GOEXPERIMENT")) 133 } 134 } 135 136 func TestGenericFunctionParser(t *testing.T) { 137 // Normal parsing 138 139 var testCases = []struct{ name, pkg, rcv, base string }{ 140 {"github.com/undoio/delve.afunc", "github.com/undoio/delve", "", "afunc"}, 141 {"github.com/undoio/delve..afunc", "github.com/undoio/delve", "", "afunc"}, // malformed 142 {"github.com/undoio/delve.afunc[some/[thing].el se]", "github.com/undoio/delve", "", "afunc[some/[thing].el se]"}, 143 {"github.com/undoio/delve.Receiver.afunc", "github.com/undoio/delve", "Receiver", "afunc"}, 144 {"github.com/undoio/delve.(*Receiver).afunc", "github.com/undoio/delve", "(*Receiver)", "afunc"}, 145 {"github.com/undoio/delve.Receiver.afunc[some/[thing].el se]", "github.com/undoio/delve", "Receiver", "afunc[some/[thing].el se]"}, // malformed 146 {"github.com/undoio/delve.(*Receiver).afunc[some/[thing].el se]", "github.com/undoio/delve", "(*Receiver)", "afunc[some/[thing].el se]"}, // malformed 147 {"github.com/undoio/delve.Receiver[some/[thing].el se].afunc", "github.com/undoio/delve", "Receiver[some/[thing].el se]", "afunc"}, 148 {"github.com/undoio/delve.(*Receiver[some/[thing].el se]).afunc", "github.com/undoio/delve", "(*Receiver[some/[thing].el se])", "afunc"}, 149 150 {"github.com/undoio/delve.afunc[.some/[thing].el se]", "github.com/undoio/delve", "", "afunc[.some/[thing].el se]"}, 151 {"github.com/undoio/delve.Receiver.afunc[.some/[thing].el se]", "github.com/undoio/delve", "Receiver", "afunc[.some/[thing].el se]"}, // malformed 152 {"github.com/undoio/delve.Receiver[.some/[thing].el se].afunc", "github.com/undoio/delve", "Receiver[.some/[thing].el se]", "afunc"}, 153 {"github.com/undoio/delve.(*Receiver[.some/[thing].el se]).afunc", "github.com/undoio/delve", "(*Receiver[.some/[thing].el se])", "afunc"}, 154 } 155 156 for _, tc := range testCases { 157 fn := &Function{Name: tc.name} 158 if fn.PackageName() != tc.pkg { 159 t.Errorf("Package name mismatch: %q %q", tc.pkg, fn.PackageName()) 160 } 161 if fn.ReceiverName() != tc.rcv { 162 t.Errorf("Receiver name mismatch: %q %q", tc.rcv, fn.ReceiverName()) 163 } 164 if fn.BaseName() != tc.base { 165 t.Errorf("Base name mismatch: %q %q", tc.base, fn.BaseName()) 166 } 167 } 168 }