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()
|
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) {
|
func TestDlvTestChdir(t *testing.T) {
|
||||||
dlvbin := getDlvBin(t)
|
dlvbin := getDlvBin(t)
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ type EBPFContext struct {
|
|||||||
bpfRingBuf *ringbuf.Reader
|
bpfRingBuf *ringbuf.Reader
|
||||||
executable *link.Executable
|
executable *link.Executable
|
||||||
bpfArgMap *ebpf.Map
|
bpfArgMap *ebpf.Map
|
||||||
|
links []link.Link
|
||||||
|
|
||||||
parsedBpfEvents []RawUProbeParams
|
parsedBpfEvents []RawUProbeParams
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
@ -70,13 +71,19 @@ func (ctx *EBPFContext) Close() {
|
|||||||
if ctx.objs != nil {
|
if ctx.objs != nil {
|
||||||
ctx.objs.Close()
|
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 {
|
func (ctx *EBPFContext) AttachUprobe(pid int, name string, offset uint64) error {
|
||||||
if ctx.executable == nil {
|
if ctx.executable == nil {
|
||||||
return errors.New("no eBPF program loaded")
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user