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