From f0b534ddcc8c2004ce292e0b9e76a4987fe3e13d Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Fri, 18 Aug 2023 10:56:44 -0700 Subject: [PATCH] pkg/proc: add support for more types in ebpf tracing backend (#3474) --- _fixtures/ebpf_trace3.go | 23 ++++++++++++++ cmd/dlv/dlv_test.go | 52 +++++++++++++++++++++++++++++-- pkg/proc/internal/ebpf/helpers.go | 4 ++- 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 _fixtures/ebpf_trace3.go diff --git a/_fixtures/ebpf_trace3.go b/_fixtures/ebpf_trace3.go new file mode 100644 index 00000000..3ef67377 --- /dev/null +++ b/_fixtures/ebpf_trace3.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + str := "abcdefghijklmnopqrstuvqxyz" + i := int64(0) + for i = 0; i < 5; i++ { + tracedFunction(i, i%5 == 0, str[i]) + } + for i = 5; i < 10; i++ { + tracedFunction(i, i%5 == 0, str[i]) + time.Sleep(time.Millisecond) + } +} + +//go:noinline +func tracedFunction(x int64, b bool, r byte) { + fmt.Println(x, b, r) +} diff --git a/cmd/dlv/dlv_test.go b/cmd/dlv/dlv_test.go index 1dc474a3..4ac90563 100644 --- a/cmd/dlv/dlv_test.go +++ b/cmd/dlv/dlv_test.go @@ -1098,10 +1098,10 @@ func TestTraceEBPF(t *testing.T) { output, err := ioutil.ReadAll(rdr) assertNoError(err, t, "ReadAll") + cmd.Wait() if !bytes.Contains(output, expected) { t.Fatalf("expected:\n%s\ngot:\n%s", string(expected), string(output)) } - cmd.Wait() } func TestTraceEBPF2(t *testing.T) { @@ -1158,10 +1158,10 @@ func TestTraceEBPF2(t *testing.T) { output, err := ioutil.ReadAll(rdr) assertNoError(err, t, "ReadAll") + cmd.Wait() if !bytes.Contains(output, expected) { t.Fatalf("expected:\n%s\ngot:\n%s", string(expected), string(output)) } - cmd.Wait() } func TestTraceEBPF3(t *testing.T) { @@ -1206,10 +1206,58 @@ func TestTraceEBPF3(t *testing.T) { output, err := ioutil.ReadAll(rdr) assertNoError(err, t, "ReadAll") + cmd.Wait() if !bytes.Contains(output, expected) { t.Fatalf("expected:\n%s\ngot:\n%s", string(expected), string(output)) } +} + +func TestTraceEBPF4(t *testing.T) { + if os.Getenv("CI") == "true" { + t.Skip("cannot run test in CI, requires kernel compiled with btf support") + } + if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { + t.Skip("not implemented on non linux/amd64 systems") + } + if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 16) { + t.Skip("requires at least Go 1.16 to run test") + } + usr, err := user.Current() + if err != nil { + t.Fatal(err) + } + if usr.Uid != "0" { + t.Skip("test must be run as root") + } + + dlvbin := getDlvBinEBPF(t) + + expected := []byte(`> (1) main.tracedFunction(0, true, 97) +> (1) main.tracedFunction(1, false, 98) +> (1) main.tracedFunction(2, false, 99) +> (1) main.tracedFunction(3, false, 100) +> (1) main.tracedFunction(4, false, 101) +> (1) main.tracedFunction(5, true, 102) +> (1) main.tracedFunction(6, false, 103) +> (1) main.tracedFunction(7, false, 104) +> (1) main.tracedFunction(8, false, 105) +> (1) main.tracedFunction(9, false, 106)`) + + fixtures := protest.FindFixturesDir() + cmd := exec.Command(dlvbin, "trace", "--ebpf", "--output", filepath.Join(t.TempDir(), "__debug"), filepath.Join(fixtures, "ebpf_trace3.go"), "main.traced") + rdr, err := cmd.StderrPipe() + assertNoError(err, t, "stderr pipe") + defer rdr.Close() + + assertNoError(cmd.Start(), t, "running trace") + + output, err := ioutil.ReadAll(rdr) + assertNoError(err, t, "ReadAll") + cmd.Wait() + if !bytes.Contains(output, expected) { + t.Fatalf("expected:\n%s\ngot:\n%s", string(expected), string(output)) + } } func TestDlvTestChdir(t *testing.T) { diff --git a/pkg/proc/internal/ebpf/helpers.go b/pkg/proc/internal/ebpf/helpers.go index fbef79e9..cddb4af7 100644 --- a/pkg/proc/internal/ebpf/helpers.go +++ b/pkg/proc/internal/ebpf/helpers.go @@ -186,7 +186,9 @@ func parseFunctionParameterList(rawParamBytes []byte) RawUProbeParams { iparam.Addr = FakeAddressBase switch iparam.Kind { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + iparam.RealType = &godwarf.UintType{BasicType: godwarf.BasicType{CommonType: godwarf.CommonType{ByteSize: 8}}} + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Bool: iparam.RealType = &godwarf.IntType{BasicType: godwarf.BasicType{CommonType: godwarf.CommonType{ByteSize: 8}}} case reflect.String: strLen := binary.LittleEndian.Uint64(val[8:])