pkg/proc: fix ebpf probe tracing backen uprobe handling (#3417)
Uprobes get automatically cleaned and removed when the reference to the Link object is lost. Hold a reference to any active Uprobe Link for duration of Delve execution and ensure they are cleaned up at exit. Fixes ebpf probes don't work after time.Sleep() #3227
This commit is contained in:
parent
ccf17a6f42
commit
1d28ceccdc
22
_fixtures/ebpf_trace2.go
Normal file
22
_fixtures/ebpf_trace2.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
i := int64(0)
|
||||
for i = 0; i < 5; i++ {
|
||||
tracedFunction(i)
|
||||
}
|
||||
for i = 5; i < 10; i++ {
|
||||
tracedFunction(i)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func tracedFunction(x int64) {
|
||||
fmt.Println(x)
|
||||
}
|
@ -1157,6 +1157,54 @@ func TestTraceEBPF2(t *testing.T) {
|
||||
cmd.Wait()
|
||||
}
|
||||
|
||||
func TestTraceEBPF3(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)
|
||||
> (1) main.tracedFunction(1)
|
||||
> (1) main.tracedFunction(2)
|
||||
> (1) main.tracedFunction(3)
|
||||
> (1) main.tracedFunction(4)
|
||||
> (1) main.tracedFunction(5)
|
||||
> (1) main.tracedFunction(6)
|
||||
> (1) main.tracedFunction(7)
|
||||
> (1) main.tracedFunction(8)
|
||||
> (1) main.tracedFunction(9)`)
|
||||
|
||||
fixtures := protest.FindFixturesDir()
|
||||
cmd := exec.Command(dlvbin, "trace", "--ebpf", "--output", filepath.Join(t.TempDir(), "__debug"), filepath.Join(fixtures, "ebpf_trace2.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")
|
||||
|
||||
if !bytes.Contains(output, expected) {
|
||||
t.Fatalf("expected:\n%s\ngot:\n%s", string(expected), string(output))
|
||||
}
|
||||
cmd.Wait()
|
||||
}
|
||||
|
||||
func TestDlvTestChdir(t *testing.T) {
|
||||
dlvbin := getDlvBin(t)
|
||||
|
||||
|
@ -61,6 +61,7 @@ type EBPFContext struct {
|
||||
bpfRingBuf *ringbuf.Reader
|
||||
executable *link.Executable
|
||||
bpfArgMap *ebpf.Map
|
||||
links []link.Link
|
||||
|
||||
parsedBpfEvents []RawUProbeParams
|
||||
m sync.Mutex
|
||||
@ -70,13 +71,19 @@ func (ctx *EBPFContext) Close() {
|
||||
if ctx.objs != nil {
|
||||
ctx.objs.Close()
|
||||
}
|
||||
if ctx.links != nil {
|
||||
for _, l := range ctx.links {
|
||||
l.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) AttachUprobe(pid int, name string, offset uint64) error {
|
||||
if ctx.executable == nil {
|
||||
return errors.New("no eBPF program loaded")
|
||||
}
|
||||
_, err := ctx.executable.Uprobe(name, ctx.objs.tracePrograms.UprobeDlvTrace, &link.UprobeOptions{PID: pid, Offset: offset})
|
||||
l, err := ctx.executable.Uprobe(name, ctx.objs.tracePrograms.UprobeDlvTrace, &link.UprobeOptions{PID: pid, Offset: offset})
|
||||
ctx.links = append(ctx.links, l)
|
||||
return err
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user