Skip to content

Commit

Permalink
clang: loader: Allow user to override kernel version (iovisor#1895)
Browse files Browse the repository at this point in the history
BCC currently requires exactly matching headers. Sometimes this is quite
inconvenient especially if the kernel version is only very slightly
different such as updates in a stable kernel. This patch gives the user
the flexibility to override the the LINUX_VERSION_CODE provided in the
linux kernel headers, so that the eBPF program may load. We also print a
message when this is done, so that the user is warned about the override
happening and that results may be unpredictable.

Also updated the docs.

Signed-off-by: Joel Fernandes <[email protected]>
  • Loading branch information
joelagnel authored and yonghong-song committed Jul 24, 2018
1 parent 492a2bf commit bfecc24
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
27 changes: 27 additions & 0 deletions docs/reference_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ This guide is incomplete. If something feels missing, check the bcc and kernel s
- [1. Invalid mem access](#1-invalid-mem-access)
- [2. Cannot call GPL only function from proprietary program](#2-cannot-call-gpl-only-function-from-proprietary-program)

- [Environment Variables](#envvars)
- [1. kernel source directory](#1-kernel-source-directory)
- [2. kernel version overriding](#2-kernel-version-overriding)

# BPF C

This section describes the C part of a bcc program.
Expand Down Expand Up @@ -1558,3 +1562,26 @@ bpf: Failed to load program: Invalid argument
8: (85) call bpf_get_stackid#27
cannot call GPL only function from proprietary program
```

# Environment Variables

## 1. Kernel source directory

eBPF program compilation needs kernel sources or kernel headers with headers
compiled. In case your kernel sources are at a non-standard location where BCC
cannot find then, its possible to provide BCC the absolute path of the location
by setting `BCC_KERNEL_SOURCE` to it.

## 2. Kernel version overriding

By default, BCC stores the `LINUX_VERSION_CODE` in the generated eBPF object
which is then passed along to the kernel when the eBPF program is loaded.
Sometimes this is quite inconvenient especially when the kernel is slightly
updated such as an LTS kernel release. Its extremely unlikely the slight
mismatch would cause any issues with the loaded eBPF program. By setting
`BCC_LINUX_VERSION_CODE` to the version of the kernel that's running, the check
for verifying the kernel version can be bypassed. This is needed for programs
that use kprobes. This needs to be encoded in the format: `(VERSION * 65536) +
(PATCHLEVEL * 256) + SUBLEVEL`. For example, if the running kernel is `4.9.10`,
then can set `export BCC_LINUX_VERSION_CODE=264458` to override the kernel
version check successfully.
4 changes: 4 additions & 0 deletions src/cc/export/helpers.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,11 @@ struct _name##_table_t _name = { .max_entries = (_max_entries) }
#define cursor_advance(_cursor, _len) \
({ void *_tmp = _cursor; _cursor += _len; _tmp; })

#ifdef LINUX_VERSION_CODE_OVERRIDE
unsigned _version SEC("version") = LINUX_VERSION_CODE_OVERRIDE;
#else
unsigned _version SEC("version") = LINUX_VERSION_CODE;
#endif

/* helper functions called from eBPF programs written in C */
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
Expand Down
11 changes: 11 additions & 0 deletions src/cc/frontends/clang/loader.cc
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, TableStorage &ts,
uname(&un);
string kdir, kpath;
const char *kpath_env = ::getenv("BCC_KERNEL_SOURCE");
const char *version_override = ::getenv("BCC_LINUX_VERSION_CODE");
bool has_kpath_source = false;
string vmacro;

if (kpath_env) {
kpath = string(kpath_env);
Expand Down Expand Up @@ -175,6 +177,15 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, TableStorage &ts,
flags_cstr.push_back(it->c_str());

vector<const char *> flags_cstr_rem;

if (version_override) {
vmacro = "-DLINUX_VERSION_CODE_OVERRIDE=" + string(version_override);

std::cout << "WARNING: Linux version for eBPF program is being overridden with: " << version_override << "\n";
std::cout << "WARNING: Due to this, the results of the program may be unpredictable\n";
flags_cstr_rem.push_back(vmacro.c_str());
}

flags_cstr_rem.push_back("-include");
flags_cstr_rem.push_back("/virtual/include/bcc/helpers.h");
flags_cstr_rem.push_back("-isystem");
Expand Down

0 comments on commit bfecc24

Please sign in to comment.