1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
From 5208c6275e65d94d0ed169ca2b253602c78c15a8 Mon Sep 17 00:00:00 2001
From: Dominique Martinet <asmadeus@codewreck.org>
Date: Fri, 14 Jun 2024 22:32:43 +0900
Subject: [PATCH] kernel headers: only print kheaders not found warning if
parsing failed
Current code would print kheaders not found as soon as the code has any
include, even if the include worked.
This delays printing the warning until we know if parsing succeeded or
not, and only prints it if parsing failed.
Also update the message to give clearer extraction instructions
---
CHANGELOG.md | 2 ++
src/CMakeLists.txt | 3 ++-
src/main.cpp | 40 ++++++++++++++++++++++++----------------
src/utils.cpp | 45 +++++++++++++++++++++------------------------
src/utils.h | 5 +++--
5 files changed, 52 insertions(+), 43 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4aca8b6c85d..181c1bffc9f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@ ## Unreleased
#### Added
#### Changed
+- Only print kernel headers not found message if parsing fails
+ - [#3265](https://github.com/bpftrace/bpftrace/pull/3265)
#### Deprecated
#### Removed
#### Fixed
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index eadb11207052..7b637835afd9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -90,11 +90,12 @@ endif()
if (KERNEL_HEADERS_DIR)
MESSAGE(STATUS "Using KERNEL_HEADERS_DIR=${KERNEL_HEADERS_DIR}")
- target_compile_definitions(runtime PUBLIC KERNEL_HEADERS_DIR="${KERNEL_HEADERS_DIR}")
endif()
+target_compile_definitions(runtime PUBLIC KERNEL_HEADERS_DIR="${KERNEL_HEADERS_DIR}")
if (NOT SYSTEM_INCLUDE_PATHS EQUAL "auto")
MESSAGE(STATUS "Using SYSTEM_INCLUDE_PATHS=${SYSTEM_INCLUDE_PATHS}")
endif()
+target_compile_definitions(runtime PUBLIC SYSTEM_INCLUDE_PATHS="${SYSTEM_INCLUDE_PATHS}")
execute_process(
COMMAND git describe --abbrev=4 --dirty --tags
diff --git a/src/main.cpp b/src/main.cpp
index 3c532b3aa767..7918f90b90ab 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -420,24 +420,20 @@ static std::optional<struct timespec> get_delta_taitime()
bool should_clang_parse = !(driver.root.get()->c_definitions.empty() &&
bpftrace.btf_set_.empty());
-
- if (should_clang_parse)
- {
+ if (should_clang_parse) {
ClangParser clang;
+ bool found_kernel_headers;
+ std::string ksrc, kobj;
+ struct utsname utsname;
std::vector<std::string> extra_flags;
- {
- struct utsname utsname;
- uname(&utsname);
- std::string ksrc, kobj;
- auto kdirs = get_kernel_dirs(utsname);
- ksrc = std::get<0>(kdirs);
- kobj = std::get<1>(kdirs);
+ uname(&utsname);
+ found_kernel_headers = get_kernel_dirs(utsname, ksrc, kobj);
- if (ksrc != "")
- {
- extra_flags = get_kernel_cflags(
- utsname.machine, ksrc, kobj, bpftrace.kconfig);
- }
+ if (found_kernel_headers)
+ {
+ extra_flags = get_kernel_cflags(
+ utsname.machine, ksrc, kobj, bpftrace.kconfig);
+ found_kernel_headers = true;
}
extra_flags.push_back("-include");
extra_flags.push_back(CLANG_WORKAROUNDS_H);
@@ -453,8 +449,20 @@ static std::optional<struct timespec> get_delta_taitime()
extra_flags.push_back(file);
}
- if (!clang.parse(driver.root.get(), bpftrace, extra_flags))
+ if (!clang.parse(driver.root.get(), bpftrace, extra_flags)) {
+ if (!found_kernel_headers) {
+ LOG(WARNING)
+ << "Could not find kernel headers in " << ksrc << " / " << kobj
+ << ". To specify a particular path to kernel headers, set the env "
+ << "variables BPFTRACE_KERNEL_SOURCE and, optionally, "
+ << "BPFTRACE_KERNEL_BUILD if the kernel was built in a different "
+ << "directory than its source. You can also point the variable to "
+ << "a directory with built-in headers extracted from the following "
+ << "snippet:\nmodprobe kheaders && tar -C <directory> -xf "
+ << "/sys/kernel/kheaders.tar.xz";
+ }
return nullptr;
+ }
}
err = driver.parse();
diff --git a/src/utils.cpp b/src/utils.cpp
index c358a401fc83..06d7fa95ff6e 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -700,8 +700,8 @@ bool is_dir(const std::string& path)
return std_filesystem::is_directory(buf, ec);
}
-// get_kernel_dirs returns {ksrc, kobj} - directories for pristine and
-// generated kernel sources.
+// get_kernel_dirs fills {ksrc, kobj} - directories for pristine and
+// generated kernel sources - and returns if they were found.
//
// When the kernel was built in its source tree ksrc == kobj, however when
// the kernel was build in a different directory than its source, ksrc != kobj.
@@ -714,44 +714,41 @@ bool is_dir(const std::string& path)
//
// /lib/modules/`uname -r`/build/
//
-// {"", ""} is returned if no trace of kernel headers was found at all.
-// Both ksrc and kobj are guaranteed to be != "", if at least some trace of kernel sources was found.
-std::tuple<std::string, std::string> get_kernel_dirs(
- const struct utsname &utsname)
+// false is returned if no trace of kernel headers was found at all, with the guessed
+// location set anyway for later warning.
+// Both ksrc and kobj are guaranteed to be != ""
+bool get_kernel_dirs(const struct utsname &utsname,
+ std::string &ksrc,
+ std::string &kobj)
{
-#ifdef KERNEL_HEADERS_DIR
- return {KERNEL_HEADERS_DIR, KERNEL_HEADERS_DIR};
-#endif
+ ksrc = kobj = std::string(KERNEL_HEADERS_DIR);
+ if (!ksrc.empty())
+ return true;
const char *kpath_env = ::getenv("BPFTRACE_KERNEL_SOURCE");
if (kpath_env)
{
+ ksrc = std::string(kpath_env);
const char *kpath_build_env = ::getenv("BPFTRACE_KERNEL_BUILD");
- if (!kpath_build_env)
+ if (kpath_build_env)
{
- kpath_build_env = kpath_env;
+ kobj = std::string(kpath_build_env);
+ } else {
+ kobj = ksrc;
}
- return std::make_tuple(kpath_env, kpath_build_env);
+ return true;
}
std::string kdir = std::string("/lib/modules/") + utsname.release;
- auto ksrc = kdir + "/source";
- auto kobj = kdir + "/build";
+ ksrc = kdir + "/source";
+ kobj = kdir + "/build";
// if one of source/ or build/ is not present - try to use the other one for
// both.
auto has_ksrc = is_dir(ksrc);
auto has_kobj = is_dir(kobj);
if (!has_ksrc && !has_kobj) {
- LOG(WARNING) << "Could not find kernel headers in " << ksrc << " or "
- << kobj
- << ". To specify a particular path to kernel headers, set the "
- "env variables BPFTRACE_KERNEL_SOURCE and, optionally, "
- "BPFTRACE_KERNEL_BUILD if the kernel was built in a "
- "different directory than its source. To create kernel "
- "headers run 'modprobe kheaders', which will create a tar "
- "file at /sys/kernel/kheaders.tar.xz";
- return std::make_tuple("", "");
+ return false;
}
if (!has_ksrc) {
ksrc = kobj;
@@ -759,7 +756,7 @@ std::tuple<std::string, std::string> get_kernel_dirs(
kobj = ksrc;
}
- return std::make_tuple(ksrc, kobj);
+ return true;
}
const std::string &is_deprecated(const std::string &str)
diff --git a/src/utils.h b/src/utils.h
index bc78bd2176b5..9bd5395eab22 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -186,8 +186,9 @@ std::vector<int> get_online_cpus();
std::vector<int> get_possible_cpus();
bool is_dir(const std::string &path);
bool file_exists_and_ownedby_root(const char *f);
-std::tuple<std::string, std::string> get_kernel_dirs(
- const struct utsname &utsname);
+bool get_kernel_dirs(const struct utsname &utsname,
+ std::string &ksrc,
+ std::string &kobj);
std::vector<std::string> get_kernel_cflags(const char *uname_machine,
const std::string &ksrc,
const std::string &kobj,
--
2.45.2
|