inspektor-gadget

Форк
0
141 строка · 3.3 Кб
1
// Copyright 2023 The Inspektor Gadget authors
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 btfgen provides a way to load BTF information generated with btfgen. Files to be
16
// incluided into the binary have to be generated with BTFGen (make btfgen on the root) before
17
// compiling the binary.
18
package btfgen
19

20
import (
21
	"bufio"
22
	"bytes"
23
	_ "embed"
24
	"fmt"
25
	"os"
26
	"path/filepath"
27
	"runtime"
28
	"strings"
29
	"sync"
30

31
	"github.com/cilium/ebpf/btf"
32
	"github.com/inspektor-gadget/inspektor-gadget/pkg/utils/host"
33
	log "github.com/sirupsen/logrus"
34
	"golang.org/x/sys/unix"
35
)
36

37
var (
38
	spec *btf.Spec
39
	once sync.Once
40
)
41

42
func initialize() error {
43
	// If the kernel exposes BTF; nothing to do
44
	_, err := btf.LoadKernelSpec()
45
	if err == nil {
46
		return nil
47
	}
48

49
	info, err := getOSInfo()
50
	if err != nil {
51
		return err
52
	}
53

54
	// architecture naming is a mess:
55
	// - Golang uses amd64 and arm64
56
	// - btfhub uses x86_64 and arm64
57
	// - bpf2go uses x86 and arm64
58
	goarch := runtime.GOARCH
59
	if goarch == "amd64" {
60
		goarch = "x86"
61
	}
62

63
	btfFile := fmt.Sprintf("btfs/%s/%s/%s/%s/%s.btf",
64
		goarch, info.ID, info.VersionID, info.Arch, info.Kernel)
65

66
	file, err := btfs.ReadFile(btfFile)
67
	if err != nil {
68
		return fmt.Errorf("reading %s BTF file %w", btfFile, err)
69
	}
70

71
	s, err := btf.LoadSpecFromReader(bytes.NewReader(file))
72
	if err != nil {
73
		return fmt.Errorf("loading BTF spec: %w", err)
74
	}
75

76
	spec = s
77
	return nil
78
}
79

80
// GetBTFSpec returns the BTF spec with kernel information for the current kernel version. If the
81
// kernel exposes BTF information or if the BTF for this kernel is not found, it returns nil.
82
func GetBTFSpec() *btf.Spec {
83
	once.Do(func() {
84
		err := initialize()
85
		if err != nil {
86
			log.Warnf("Failed to initialize BTF: %v", err)
87
		}
88
	})
89
	return spec
90
}
91

92
type osInfo struct {
93
	ID        string
94
	VersionID string
95
	Arch      string
96
	Kernel    string
97
}
98

99
func getOSInfo() (*osInfo, error) {
100
	osInfo := &osInfo{}
101

102
	file, err := os.Open(filepath.Join(host.HostRoot, "/etc/os-release"))
103
	if err != nil {
104
		return nil, fmt.Errorf("opening file: %w", err)
105
	}
106
	defer file.Close()
107

108
	scanner := bufio.NewScanner(file)
109
	for scanner.Scan() {
110
		line := scanner.Text()
111
		parts := strings.SplitN(line, "=", 2)
112
		if len(parts) != 2 {
113
			continue
114
		}
115

116
		switch parts[0] {
117
		case "ID":
118
			osInfo.ID = parts[1]
119
		case "VERSION_ID":
120
			osInfo.VersionID = strings.Trim(parts[1], "\"")
121
		}
122
	}
123

124
	if osInfo.ID == "" || osInfo.VersionID == "" {
125
		return nil, fmt.Errorf("os-release file is incomplete")
126
	}
127

128
	if err := scanner.Err(); err != nil {
129
		return nil, fmt.Errorf("scanning file: %w", err)
130
	}
131

132
	uts := &unix.Utsname{}
133
	if err := unix.Uname(uts); err != nil {
134
		return nil, fmt.Errorf("calling uname: %w", err)
135
	}
136

137
	osInfo.Kernel = unix.ByteSliceToString(uts.Release[:])
138
	osInfo.Arch = unix.ByteSliceToString(uts.Machine[:])
139

140
	return osInfo, nil
141
}
142

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.