Skip to content

Commit

Permalink
link: Add Info interface support for perf event kprobe link
Browse files Browse the repository at this point in the history
Implementing Info function (Link interface) for perf event
kprobe link, it's now possibe to retrieve link's data with:

  pevent := info.PerfEvent()
  switch pevent.Type {
  case unix.BPF_PERF_EVENT_KPROBE, unix.BPF_PERF_EVENT_KRETPROBE:
          kp := pevent.Kprobe()
          addr, ok := kp.Address()
          addr, ok := kp.Flags()
          missed, ok := kp.Missed()
  }

At the moment we support/return only Addr/Flags/Missed data
returned by Address/Flags/Missed KprobeMultiInfo methods
respectively.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
  • Loading branch information
olsajiri authored and lmb committed Apr 9, 2024
1 parent eae9447 commit e678d6e
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
4 changes: 4 additions & 0 deletions internal/sys/syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func (i *KprobeMultiLinkInfo) info() (unsafe.Pointer, uint32) {
return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
}

func (i *KprobeLinkInfo) info() (unsafe.Pointer, uint32) {
return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
}

var _ Info = (*BtfInfo)(nil)

func (i *BtfInfo) info() (unsafe.Pointer, uint32) {
Expand Down
57 changes: 55 additions & 2 deletions link/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,29 @@ func (kpm *KprobeMultiInfo) Missed() (uint64, bool) {
return kpm.missed, kpm.count > 0
}

type PerfEventInfo struct {
Type sys.PerfEventType
extra interface{}
}

func (r *PerfEventInfo) Kprobe() *KprobeInfo {
e, _ := r.extra.(*KprobeInfo)
return e
}

type KprobeInfo struct {
address uint64
missed uint64
}

func (kp *KprobeInfo) Address() (uint64, bool) {
return kp.address, kp.address > 0
}

func (kp *KprobeInfo) Missed() (uint64, bool) {
return kp.missed, kp.address > 0
}

// Tracing returns tracing type-specific link info.
//
// Returns nil if the type-specific link info isn't available.
Expand Down Expand Up @@ -277,6 +300,14 @@ func (r Info) KprobeMulti() *KprobeMultiInfo {
return e
}

// PerfEvent returns perf-event type-specific link info.
//
// Returns nil if the type-specific link info isn't available.
func (r Info) PerfEvent() *PerfEventInfo {
e, _ := r.extra.(*PerfEventInfo)
return e
}

// RawLink is the low-level API to bpf_link.
//
// You should consider using the higher level interfaces in this
Expand Down Expand Up @@ -452,8 +483,7 @@ func (l *RawLink) Info() (*Info, error) {
extra = &XDPInfo{
Ifindex: xdpInfo.Ifindex,
}
case RawTracepointType, IterType,
PerfEventType, UprobeMultiType:
case RawTracepointType, IterType, UprobeMultiType:
// Extra metadata not supported.
case TCXType:
var tcxInfo sys.TcxLinkInfo
Expand Down Expand Up @@ -494,6 +524,29 @@ func (l *RawLink) Info() (*Info, error) {
flags: kprobeMultiInfo.Flags,
missed: kprobeMultiInfo.Missed,
}
case PerfEventType:
var perfEventInfo sys.PerfEventLinkInfo
if err := sys.ObjInfo(l.fd, &perfEventInfo); err != nil {
return nil, fmt.Errorf("perf event link info: %s", err)
}

var extra2 interface{}
switch perfEventInfo.PerfEventType {
case sys.BPF_PERF_EVENT_KPROBE, sys.BPF_PERF_EVENT_KRETPROBE:
var kprobeInfo sys.KprobeLinkInfo
if err := sys.ObjInfo(l.fd, &kprobeInfo); err != nil {
return nil, fmt.Errorf("kprobe multi link info: %s", err)
}
extra2 = &KprobeInfo{
address: kprobeInfo.Addr,
missed: kprobeInfo.Missed,
}
}

extra = &PerfEventInfo{
Type: perfEventInfo.PerfEventType,
extra: extra2,
}
default:
return nil, fmt.Errorf("unknown link info type: %d", info.Type)
}
Expand Down
15 changes: 15 additions & 0 deletions link/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,21 @@ func testLink(t *testing.T, link Link, prog *ebpf.Program) {
// NB: We don't check that missed is actually correct
// since it's not easy to trigger from tests.
}
case sys.BPF_LINK_TYPE_PERF_EVENT:
// test default Info data
pevent := info.PerfEvent()
switch pevent.Type {
case sys.BPF_PERF_EVENT_KPROBE, sys.BPF_PERF_EVENT_KRETPROBE:
kp := pevent.Kprobe()
if addr, ok := kp.Address(); ok {
qt.Assert(t, qt.Not(qt.Equals(addr, 0)))

_, ok := kp.Missed()
qt.Assert(t, qt.IsTrue(ok))
// NB: We don't check that missed is actually correct
// since it's not easy to trigger from tests.
}
}
}
})

Expand Down

0 comments on commit e678d6e

Please sign in to comment.