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 }