github.com/jayanthvn/pure-gobpf@v0.0.0-20230623131354-8d1d959d9e0b/pkg/ebpf_tracepoint/tracepoint.go (about)

     1  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License").
     4  // You may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  //limitations under the License.
    14  
    15  package ebpf_tracepoint
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"strconv"
    21  	"strings"
    22  
    23  	//"syscall"
    24  	"unsafe"
    25  
    26  	"github.com/jayanthvn/pure-gobpf/pkg/logger"
    27  	"golang.org/x/sys/unix"
    28  )
    29  
    30  var log = logger.Get()
    31  
    32  // if event is nil, we pick funcName
    33  func TracepointAttach(progFD int, subSystem, eventName string) error {
    34  
    35  	//var log = logger.Get()
    36  
    37  	if progFD <= 0 {
    38  		log.Infof("Invalid BPF prog FD %d", progFD)
    39  		return fmt.Errorf("Invalid BPF prog FD %d", progFD)
    40  
    41  	}
    42  
    43  	if len(subSystem) == 0 || len(eventName) == 0 {
    44  		log.Infof("Invalid Arg")
    45  		return fmt.Errorf("Invalid Arguement")
    46  	}
    47  
    48  	//Get the TP ID
    49  	tracepointIDpath := fmt.Sprintf("/sys/kernel/debug/tracing/events/%s/%s/id", subSystem, eventName)
    50  	data, err := os.ReadFile(tracepointIDpath)
    51  	if err != nil {
    52  		log.Infof("Unable to read the tracepointID: %v", err)
    53  		return fmt.Errorf("Unable to read the tracepointID: %v", err)
    54  	}
    55  	id := strings.TrimSpace(string(data))
    56  	eventID, err := strconv.Atoi(id)
    57  	if err != nil {
    58  		log.Infof("Invalid ID during parsing: %s - %v", id, err)
    59  		return fmt.Errorf("Invalid ID during parsing: %s - %w", id, err)
    60  	}
    61  
    62  	log.Infof("Got eventID %d", eventID)
    63  
    64  	attr := unix.PerfEventAttr{
    65  		Type:   unix.PERF_TYPE_TRACEPOINT,
    66  		Sample: 1,
    67  		Wakeup: 1,
    68  		Config: uint64(eventID),
    69  	}
    70  	attr.Size = uint32(unsafe.Sizeof(attr))
    71  
    72  	fd, err := unix.PerfEventOpen(&attr, -1, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
    73  	if err != nil {
    74  		log.Infof("Failed to open perf event %v", err)
    75  		return fmt.Errorf("Failed to open perf event %v", err)
    76  	}
    77  	//defer unix.Close(fd)
    78  
    79  	log.Infof("Attach bpf program to perf event Prog FD %d Event FD %d", progFD, fd)
    80  
    81  	if _, _, err := unix.Syscall(unix.SYS_IOCTL, uintptr(int(fd)), uintptr(uint(unix.PERF_EVENT_IOC_SET_BPF)), uintptr(progFD)); err != 0 {
    82  		log.Infof("error attaching bpf program to perf event: %v", err)
    83  		return fmt.Errorf("error attaching bpf program to perf event: %v", err)
    84  	}
    85  
    86  	if _, _, err := unix.Syscall(unix.SYS_IOCTL, uintptr(int(fd)), uintptr(uint(unix.PERF_EVENT_IOC_ENABLE)), 0); err != 0 {
    87  		log.Infof("error enabling perf event: %v", err)
    88  		return fmt.Errorf("error enabling perf event: %v", err)
    89  	}
    90  
    91  	log.Infof("Attach done!!! %d", fd)
    92  	return nil
    93  
    94  }