github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/internal/kallsyms/kallsyms.go (about)

     1  package kallsyms
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"io"
     7  	"os"
     8  	"sync"
     9  )
    10  
    11  var kernelModules struct {
    12  	sync.RWMutex
    13  	// function to kernel module mapping
    14  	kmods map[string]string
    15  }
    16  
    17  // KernelModule returns the kernel module, if any, a probe-able function is contained in.
    18  func KernelModule(fn string) (string, error) {
    19  	kernelModules.RLock()
    20  	kmods := kernelModules.kmods
    21  	kernelModules.RUnlock()
    22  
    23  	if kmods == nil {
    24  		kernelModules.Lock()
    25  		defer kernelModules.Unlock()
    26  		kmods = kernelModules.kmods
    27  	}
    28  
    29  	if kmods != nil {
    30  		return kmods[fn], nil
    31  	}
    32  
    33  	f, err := os.Open("/proc/kallsyms")
    34  	if err != nil {
    35  		return "", err
    36  	}
    37  	defer f.Close()
    38  	kmods, err = loadKernelModuleMapping(f)
    39  	if err != nil {
    40  		return "", err
    41  	}
    42  
    43  	kernelModules.kmods = kmods
    44  	return kmods[fn], nil
    45  }
    46  
    47  // FlushKernelModuleCache removes any cached information about function to kernel module mapping.
    48  func FlushKernelModuleCache() {
    49  	kernelModules.Lock()
    50  	defer kernelModules.Unlock()
    51  
    52  	kernelModules.kmods = nil
    53  }
    54  
    55  func loadKernelModuleMapping(f io.Reader) (map[string]string, error) {
    56  	mods := make(map[string]string)
    57  	scanner := bufio.NewScanner(f)
    58  	for scanner.Scan() {
    59  		fields := bytes.Fields(scanner.Bytes())
    60  		if len(fields) < 4 {
    61  			continue
    62  		}
    63  		switch string(fields[1]) {
    64  		case "t", "T":
    65  			mods[string(fields[2])] = string(bytes.Trim(fields[3], "[]"))
    66  		default:
    67  			continue
    68  		}
    69  	}
    70  	if scanner.Err() != nil {
    71  		return nil, scanner.Err()
    72  	}
    73  	return mods, nil
    74  }