forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libbpf-tools: Add experimental integration with BTFGen
This commit adds an experimental BTFGen[0] integration to allow some of the libbpf-tools to run in systems that don't provide BTF information. The whole process consist of two parts: (1) generating and embedding the BTF file within the tools binary and (2) using those when the tool is run. The first part is done by using the Makefile, it generates the reduced BTF files for the different eBPF objects of the tools, those files are then compressed and a C header file with its content is created. The second part is handled by a new C file that provides the logic to uncompress and save the BTF file according to the Linux distribution and kernel version where the tools is being run. [0] https://lore.kernel.org/bpf/[email protected]/ Signed-off-by: Mauricio Vásquez <[email protected]>
- Loading branch information
1 parent
6230695
commit 37d703d
Showing
5 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
/.output | ||
/btfhub-archive | ||
/bashreadline | ||
/bindsnoop | ||
/biolatency | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
SOURCE_BTF_FILES = $(shell find $(BTFHUB_ARCHIVE)/ -iregex ".*$(subst x86,x86_64,$(ARCH)).*" -type f -name '*.btf.tar.xz') | ||
MIN_CORE_BTF_FILES = $(patsubst $(BTFHUB_ARCHIVE)/%.btf.tar.xz, $(OUTPUT)/min_core_btfs/%.btf, $(SOURCE_BTF_FILES)) | ||
BPF_O_FILES = $(patsubst %,$(OUTPUT)/%.bpf.o,$(APPS)) | ||
|
||
.PHONY: all | ||
all: $(OUTPUT)/min_core_btf_tar.o | ||
|
||
ifeq ($(V),1) | ||
Q = | ||
msg = | ||
else | ||
Q = @ | ||
msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; | ||
MAKEFLAGS += --no-print-directory | ||
endif | ||
|
||
$(BTFHUB_ARCHIVE)/%.btf: $(BTFHUB_ARCHIVE)/%.btf.tar.xz | ||
$(call msg,UNTAR,$@) | ||
$(Q)tar xvfJ $< -C "$(@D)" > /dev/null | ||
$(Q)touch $@ | ||
|
||
$(MIN_CORE_BTF_FILES): $(BPF_O_FILES) | ||
|
||
# Create reduced version of BTF files to be embedded within the tools executables | ||
$(OUTPUT)/min_core_btfs/%.btf: $(BTFHUB_ARCHIVE)/%.btf | ||
$(call msg,BTFGEN,$@) | ||
$(Q)mkdir -p "$(@D)" | ||
$(Q)$(BPFTOOL) gen min_core_btf $< $@ $(OUTPUT)/*.bpf.o | ||
|
||
# Compress reduced BTF files and create an object file with its content | ||
$(OUTPUT)/min_core_btf_tar.o: $(MIN_CORE_BTF_FILES) | ||
$(call msg,TAR,$@) | ||
$(Q)tar c --gz -f $(OUTPUT)/min_core_btfs.tar.gz -C $(OUTPUT)/min_core_btfs/ . | ||
$(Q)cd $(OUTPUT) && ld -r -b binary min_core_btfs.tar.gz -o $@ | ||
|
||
# delete failed targets | ||
.DELETE_ON_ERROR: | ||
# keep intermediate (.skel.h, .bpf.o, etc) targets | ||
.SECONDARY: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ | ||
|
||
#include <errno.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/utsname.h> | ||
#include <zlib.h> | ||
|
||
#include "trace_helpers.h" | ||
#include "btf_helpers.h" | ||
|
||
extern unsigned char _binary_min_core_btfs_tar_gz_start[] __attribute__((weak)); | ||
extern unsigned char _binary_min_core_btfs_tar_gz_end[] __attribute__((weak)); | ||
|
||
#define FIELD_LEN 65 | ||
#define ID_FMT "ID=%64s" | ||
#define VERSION_FMT "VERSION_ID=\"%64s" | ||
|
||
struct os_info { | ||
char id[FIELD_LEN]; | ||
char version[FIELD_LEN]; | ||
char arch[FIELD_LEN]; | ||
char kernel_release[FIELD_LEN]; | ||
}; | ||
|
||
static struct os_info * get_os_info() | ||
{ | ||
struct os_info *info = NULL; | ||
struct utsname u; | ||
size_t len = 0; | ||
ssize_t read; | ||
char *line = NULL; | ||
FILE *f; | ||
|
||
if (uname(&u) == -1) | ||
return NULL; | ||
|
||
f = fopen("/etc/os-release", "r"); | ||
if (!f) | ||
return NULL; | ||
|
||
info = calloc(1, sizeof(*info)); | ||
if (!info) | ||
goto out; | ||
|
||
strncpy(info->kernel_release, u.release, FIELD_LEN); | ||
strncpy(info->arch, u.machine, FIELD_LEN); | ||
|
||
while ((read = getline(&line, &len, f)) != -1) { | ||
if (sscanf(line, ID_FMT, info->id) == 1) | ||
continue; | ||
|
||
if (sscanf(line, VERSION_FMT, info->version) == 1) { | ||
/* remove '"' suffix */ | ||
info->version[strlen(info->version) - 1] = 0; | ||
continue; | ||
} | ||
} | ||
|
||
out: | ||
free(line); | ||
fclose(f); | ||
|
||
return info; | ||
} | ||
|
||
#define INITIAL_BUF_SIZE (1024 * 1024 * 4) /* 4MB */ | ||
|
||
/* adapted from https://zlib.net/zlib_how.html */ | ||
static int | ||
inflate_gz(unsigned char *src, int src_size, unsigned char **dst, int *dst_size) | ||
{ | ||
size_t size = INITIAL_BUF_SIZE; | ||
size_t next_size = size; | ||
z_stream strm; | ||
void *tmp; | ||
int ret; | ||
|
||
strm.zalloc = Z_NULL; | ||
strm.zfree = Z_NULL; | ||
strm.opaque = Z_NULL; | ||
strm.avail_in = 0; | ||
strm.next_in = Z_NULL; | ||
|
||
ret = inflateInit2(&strm, 16 + MAX_WBITS); | ||
if (ret != Z_OK) | ||
return -EINVAL; | ||
|
||
*dst = malloc(size); | ||
if (!*dst) | ||
return -ENOMEM; | ||
|
||
strm.next_in = src; | ||
strm.avail_in = src_size; | ||
|
||
/* run inflate() on input until it returns Z_STREAM_END */ | ||
do { | ||
strm.next_out = *dst + strm.total_out; | ||
strm.avail_out = next_size; | ||
ret = inflate(&strm, Z_NO_FLUSH); | ||
if (ret != Z_OK && ret != Z_STREAM_END) | ||
goto out_err; | ||
/* we need more space */ | ||
if (strm.avail_out == 0) { | ||
next_size = size; | ||
size *= 2; | ||
tmp = realloc(*dst, size); | ||
if (!tmp) { | ||
ret = -ENOMEM; | ||
goto out_err; | ||
} | ||
*dst = tmp; | ||
} | ||
} while (ret != Z_STREAM_END); | ||
|
||
*dst_size = strm.total_out; | ||
|
||
/* clean up and return */ | ||
ret = inflateEnd(&strm); | ||
if (ret != Z_OK) { | ||
ret = -EINVAL; | ||
goto out_err; | ||
} | ||
return 0; | ||
|
||
out_err: | ||
free(*dst); | ||
*dst = NULL; | ||
return ret; | ||
} | ||
|
||
/* tar header from https://github.com/tklauser/libtar/blob/v1.2.20/lib/libtar.h#L39-L60 */ | ||
struct tar_header { | ||
char name[100]; | ||
char mode[8]; | ||
char uid[8]; | ||
char gid[8]; | ||
char size[12]; | ||
char mtime[12]; | ||
char chksum[8]; | ||
char typeflag; | ||
char linkname[100]; | ||
char magic[6]; | ||
char version[2]; | ||
char uname[32]; | ||
char gname[32]; | ||
char devmajor[8]; | ||
char devminor[8]; | ||
char prefix[155]; | ||
char padding[12]; | ||
}; | ||
|
||
static char *tar_file_start(struct tar_header *tar, const char *name, int *length) | ||
{ | ||
while (tar->name[0]) { | ||
sscanf(tar->size, "%o", length); | ||
if (!strcmp(tar->name, name)) | ||
return (char *)(tar + 1); | ||
tar += 1 + (*length + 511)/512; | ||
} | ||
return NULL; | ||
} | ||
|
||
int ensure_core_btf(struct bpf_object_open_opts *opts) | ||
{ | ||
char name_fmt[] = "./%s/%s/%s/%s.btf"; | ||
char btf_path[] = "/tmp/bcc-libbpf-tools.btf.XXXXXX"; | ||
struct os_info *info = NULL; | ||
unsigned char *dst_buf = NULL; | ||
char *file_start; | ||
int dst_size = 0; | ||
char name[100]; | ||
FILE *dst = NULL; | ||
int ret; | ||
|
||
/* do nothing if the system provides BTF */ | ||
if (vmlinux_btf_exists()) | ||
return 0; | ||
|
||
/* compiled without min core btfs */ | ||
if (!_binary_min_core_btfs_tar_gz_start) | ||
return -EOPNOTSUPP; | ||
|
||
info = get_os_info(); | ||
if (!info) | ||
return -errno; | ||
|
||
ret = mkstemp(btf_path); | ||
if (ret < 0) { | ||
ret = -errno; | ||
goto out; | ||
} | ||
|
||
dst = fdopen(ret, "wb"); | ||
if (!dst) { | ||
ret = -errno; | ||
goto out; | ||
} | ||
|
||
ret = snprintf(name, sizeof(name), name_fmt, info->id, info->version, | ||
info->arch, info->kernel_release); | ||
if (ret < 0 || ret == sizeof(name)) { | ||
ret = -EINVAL; | ||
goto out; | ||
} | ||
|
||
ret = inflate_gz(_binary_min_core_btfs_tar_gz_start, | ||
_binary_min_core_btfs_tar_gz_end - _binary_min_core_btfs_tar_gz_start, | ||
&dst_buf, &dst_size); | ||
if (ret < 0) | ||
goto out; | ||
|
||
ret = 0; | ||
file_start = tar_file_start((struct tar_header *)dst_buf, name, &dst_size); | ||
if (!file_start) { | ||
ret = -EINVAL; | ||
goto out; | ||
} | ||
|
||
if (fwrite(file_start, 1, dst_size, dst) != dst_size) { | ||
ret = -ferror(dst); | ||
goto out; | ||
} | ||
|
||
opts->btf_custom_path = strdup(btf_path); | ||
if (!opts->btf_custom_path) | ||
ret = -ENOMEM; | ||
|
||
out: | ||
free(info); | ||
fclose(dst); | ||
free(dst_buf); | ||
|
||
return ret; | ||
} | ||
|
||
void cleanup_core_btf(struct bpf_object_open_opts *opts) { | ||
if (!opts) | ||
return; | ||
|
||
if (!opts->btf_custom_path) | ||
return; | ||
|
||
unlink(opts->btf_custom_path); | ||
free((void *)opts->btf_custom_path); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ | ||
|
||
#ifndef __BTF_HELPERS_H | ||
#define __BTF_HELPERS_H | ||
|
||
#include <bpf/libbpf.h> | ||
|
||
int ensure_core_btf(struct bpf_object_open_opts *opts); | ||
void cleanup_core_btf(struct bpf_object_open_opts *opts); | ||
|
||
#endif /* __BTF_HELPERS_H */ |