Skip to content

Commit

Permalink
Unify vmlinux and BTF location list
Browse files Browse the repository at this point in the history
vmlinux is used for both symbol resolution and BTF. Manage the location
list in one place.
  • Loading branch information
mmisono committed Jan 18, 2020
1 parent 76f08de commit d58bf05
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 68 deletions.
66 changes: 33 additions & 33 deletions src/attached_probe.cpp
Expand Up @@ -386,42 +386,39 @@ void AttachedProbe::resolve_offset_uprobe(bool safe_mode)
probe_.path, symbol, sym_offset, func_offset, safe_mode, probe_.type);
}

static std::string find_vmlinux()
// find vmlinux file containing the given symbol information
static std::string find_vmlinux(const struct vmlinux_location *locs,
struct symbol &sym)
{
char *path = std::getenv("BPFTRACE_VMLINUX");
if (path)
return path;

struct bcc_symbol_option option = {};
option.use_debug_file = 0;
option.use_symbol_type = BCC_SYM_ALL_TYPES;
struct utsname buf;
uname(&buf);

// based on btf_location in btf.cpp
const char *vmlinux_locs[] = {
"/boot/vmlinux-%1$s",
"/lib/modules/%1$s/vmlinux-%1$s",
"/lib/modules/%1$s/build/vmlinux",
"/usr/lib/modules/%1$s/kernel/vmlinux",
"/usr/lib/debug/boot/vmlinux-%1$s",
"/usr/lib/debug/boot/vmlinux-%1$s.debug",
"/usr/lib/debug/lib/modules/%1$s/vmlinux",
nullptr,
};
uname(&buf);

for (int i = 0; vmlinux_locs[i]; i++)
for (int i = 0; locs[i].path; i++)
{
if (locs[i].raw)
continue; // This file is for BTF. skip
char path[PATH_MAX + 1];
snprintf(path, PATH_MAX, vmlinux_locs[i], buf.release);
snprintf(path, PATH_MAX, locs[i].path, buf.release);
if (access(path, R_OK))
continue;
return path;
bcc_elf_foreach_sym(path, sym_name_cb, &option, &sym);
if (sym.start)
{
if (bt_verbose)
std::cout << "vmlinux: using " << path << std::endl;
return path;
}
}

return "";
}

void AttachedProbe::resolve_offset_kprobe(bool safe_mode)
{
struct bcc_symbol_option option = {};
struct symbol sym = {};
std::string &symbol = probe_.attach_point;
uint64_t func_offset = probe_.func_offset;
Expand All @@ -435,16 +432,25 @@ void AttachedProbe::resolve_offset_kprobe(bool safe_mode)
return;

sym.name = symbol;
option.use_debug_file = 0;
option.use_symbol_type = BCC_SYM_ALL_TYPES;
const struct vmlinux_location *locs = vmlinux_locs;
struct vmlinux_location locs_env[] = {
{ nullptr, true },
{ nullptr, false },
};
char *env_path = std::getenv("BPFTRACE_VMLINUX");
if (env_path)
{
locs_env[0].path = env_path;
locs = locs_env;
}

std::string path = find_vmlinux();
std::string path = find_vmlinux(locs, sym);
if (path.empty())
{
if (safe_mode)
{
std::stringstream buf;
buf << "Could not find vmlinux to check the offset.";
buf << "Could not resolve symbol " << symbol << ".";
buf << " Use BPFTRACE_VMLINUX env variable to specify vmlinux path.";
#ifdef HAVE_UNSAFE_PROBE
buf << " Use --unsafe to skip the userspace check.";
Expand All @@ -458,17 +464,11 @@ void AttachedProbe::resolve_offset_kprobe(bool safe_mode)
{
// linux kernel checks alignment, but not the function bounds
if (bt_verbose)
std::cout << "No vmlinux found. Skip offset checking." << std::endl;
std::cout << "Could not resolve symbol " << symbol
<< ". Skip offset checking." << std::endl;
return;
}
}
if (bt_verbose)
std::cout << "vmlinux: using " << path << std::endl;
bcc_elf_foreach_sym(path.c_str(), sym_name_cb, &option, &sym);

if (!sym.start)
throw std::runtime_error("Could not resolve symbol: " + path + ":" +
symbol);

if (func_offset >= sym.size)
throw std::runtime_error("Offset outside the function bounds ('" + symbol +
Expand Down
50 changes: 15 additions & 35 deletions src/btf.cpp
@@ -1,15 +1,16 @@
#include "btf.h"
#include "bpftrace.h"
#include "types.h"
#include "utils.h"
#include <fcntl.h>
#include <iostream>
#include <linux/limits.h>
#include <regex>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <string.h>
#include <linux/limits.h>
#include "btf.h"
#include "types.h"
#include "bpftrace.h"
#include <unistd.h>

#ifdef HAVE_LIBBPF_BTF_DUMP
#include <linux/bpf.h>
Expand All @@ -19,11 +20,6 @@

namespace bpftrace {

struct btf_location {
const char *path; // path with possible "%s" format to be replaced current release
bool raw; // file is either as ELF (false) or raw BTF data (true)
};

static unsigned char *get_data(const char *file, ssize_t *sizep)
{
struct stat st;
Expand Down Expand Up @@ -88,7 +84,7 @@ static int libbpf_print(enum libbpf_print_level level, const char *msg, va_list
return vfprintf(stderr, msg, ap);
}

static struct btf *btf_open(struct btf_location *locs)
static struct btf *btf_open(const struct vmlinux_location *locs)
{
struct utsname buf;

Expand Down Expand Up @@ -135,36 +131,20 @@ static struct btf *btf_open(struct btf_location *locs)

BTF::BTF(void) : btf(nullptr), state(NODATA)
{
// 'borrowed' from libbpf's bpf_core_find_kernel_btf
// from Andrii Nakryiko
struct btf_location locs_normal[] =
{
{ "/sys/kernel/btf/vmlinux", true },
{ "/boot/vmlinux-%1$s", false },
{ "/lib/modules/%1$s/vmlinux-%1$s", false },
{ "/lib/modules/%1$s/build/vmlinux", false },
{ "/usr/lib/modules/%1$s/kernel/vmlinux", false },
{ "/usr/lib/debug/boot/vmlinux-%1$s", false },
{ "/usr/lib/debug/boot/vmlinux-%1$s.debug", false },
{ "/usr/lib/debug/lib/modules/%1$s/vmlinux", false },
{ nullptr, false },
};

struct btf_location locs_test[] =
{
{ nullptr, true },
struct vmlinux_location locs_env[] = {
{ nullptr, true },
{ nullptr, false },
};

struct btf_location *locs = locs_normal;
const struct vmlinux_location *locs = vmlinux_locs;

// Try to get BTF file from BPFTRACE_BTF env
char *path = std::getenv("BPFTRACE_BTF");

if (path)
{
locs_test[0].path = path;
locs = locs_test;
locs_env[0].path = path;
locs = locs_env;
}

btf = btf_open(locs);
Expand Down
14 changes: 14 additions & 0 deletions src/utils.cpp
Expand Up @@ -74,6 +74,20 @@ std::vector<std::string> expand_wildcard_paths(const std::vector<std::string>& p

namespace bpftrace {

//'borrowed' from libbpf's bpf_core_find_kernel_btf
// from Andrii Nakryiko
const struct vmlinux_location vmlinux_locs[] = {
{ "/sys/kernel/btf/vmlinux", true },
{ "/boot/vmlinux-%1$s", false },
{ "/lib/modules/%1$s/vmlinux-%1$s", false },
{ "/lib/modules/%1$s/build/vmlinux", false },
{ "/usr/lib/modules/%1$s/kernel/vmlinux", false },
{ "/usr/lib/debug/boot/vmlinux-%1$s", false },
{ "/usr/lib/debug/boot/vmlinux-%1$s.debug", false },
{ "/usr/lib/debug/lib/modules/%1$s/vmlinux", false },
{ nullptr, false },
};

static bool provider_cache_loaded = false;

// Maps all providers of pid to vector of tracepoints on that provider
Expand Down
8 changes: 8 additions & 0 deletions src/utils.h
Expand Up @@ -10,6 +10,14 @@

namespace bpftrace {

struct vmlinux_location
{
const char *path; // path with possible "%s" format to be replaced current
// release
bool raw; // file is either as ELF (false) or raw BTF data (true)
};
extern const struct vmlinux_location vmlinux_locs[];

typedef enum _USDT_TUPLE_ORDER_
{
USDT_PATH_INDEX,
Expand Down

0 comments on commit d58bf05

Please sign in to comment.