-
Notifications
You must be signed in to change notification settings - Fork 2
/
program_kprobe.go
153 lines (125 loc) · 3.57 KB
/
program_kprobe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package gobpfld
import (
"fmt"
"github.com/dylandreimerink/gobpfld/bpfsys"
"github.com/dylandreimerink/gobpfld/bpftypes"
"github.com/dylandreimerink/gobpfld/perf"
)
var _ BPFProgram = (*ProgramKProbe)(nil)
type ProgramKProbe struct {
AbstractBPFProgram
DefaultType perf.ProbeType
// DefaultCategory is the kprobe group used if no group is specified during attaching.
// It can be set when loading from ELF file.
DefaultGroup string
// DefaultName is the kprobe event used if no event is specified during attaching.
// It can be set when loading from ELF file.
DefaultEvent string
DefaultModule string
DefaultSymbol string
DefaultPath string
DefaultOffset int
attachedEvent *perf.Event
}
type ProgKPLoadOpts struct {
VerifierLogLevel bpftypes.BPFLogLevel
VerifierLogSize int
}
func (p *ProgramKProbe) Load(opts ProgKPLoadOpts) (log string, err error) {
return p.load(bpfsys.BPFAttrProgramLoad{
LogLevel: opts.VerifierLogLevel,
LogSize: uint32(opts.VerifierLogSize),
})
}
// Unpin captures the file descriptor of the program at the given 'relativePath' from the kernel.
// If 'deletePin' is true the bpf FS pin will be removed after successfully loading the program, thus transferring
// ownership of the program in a scenario where the program is not shared between multiple userspace programs.
// Otherwise the pin will keep existing which will cause the map to not be deleted when this program exits.
func (p *ProgramKProbe) Unpin(relativePath string, deletePin bool) error {
return p.unpin(relativePath, deletePin)
}
type ProgKPAttachOpts struct {
Type perf.ProbeType
// Group name. If omitted, use "kprobes" for it.
Group string
// Event name. If omitted, the event name is generated
// based on SYM+offs or MEMADDR.
Event string
// Module name which has given Symbol.
Module string
// Symbol+Offset where the probe is inserted.
Symbol string
// Path is the path to the executable to be probed.
Path string
// Offset of the address to be be probed.
Offset int
}
func (p *ProgramKProbe) Attach(opts ProgKPAttachOpts) error {
t := p.DefaultType
if opts.Type != perf.TypeUnknown {
t = opts.Type
}
if t == perf.TypeUnknown {
return fmt.Errorf("unknown probe type")
}
switch t {
case perf.TypeKProbe, perf.TypeKRetprobe:
kprobeOpts := perf.KProbeOpts{
Type: t,
Group: p.DefaultGroup,
Event: p.DefaultEvent,
Module: p.DefaultModule,
Symbol: p.DefaultSymbol,
}
if opts.Group != "" {
kprobeOpts.Group = opts.Group
}
if opts.Event != "" {
kprobeOpts.Event = opts.Event
}
if opts.Module != "" {
kprobeOpts.Module = opts.Module
}
if opts.Symbol != "" {
kprobeOpts.Symbol = opts.Symbol
}
var err error
p.attachedEvent, err = perf.OpenKProbeEvent(kprobeOpts)
if err != nil {
return fmt.Errorf("open kprobe: %w", err)
}
case perf.TypeUProbe, perf.TypeURetProbe:
uprobeOpts := perf.UProbeOpts{
Type: t,
Group: p.DefaultGroup,
Event: p.DefaultEvent,
Path: p.DefaultPath,
Offset: p.DefaultOffset,
}
if opts.Group != "" {
uprobeOpts.Group = opts.Group
}
if opts.Event != "" {
uprobeOpts.Event = opts.Event
}
if opts.Path != "" {
uprobeOpts.Path = opts.Path
}
if opts.Offset != 0 {
uprobeOpts.Offset = opts.Offset
}
var err error
p.attachedEvent, err = perf.OpenUProbeEvent(uprobeOpts)
if err != nil {
return fmt.Errorf("open uprobe: %w", err)
}
}
err := p.attachedEvent.AttachBPFProgram(p.fd)
if err != nil {
return fmt.Errorf("attach program: %w", err)
}
return nil
}
func (p *ProgramKProbe) Detach() error {
return p.attachedEvent.DetachBPFProgram()
}