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  }