mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
Merge 03e6a7a940 ("Merge branch 'selftests/bpf: parallel mode improvement'") into android-mainline
Steps on the way to 5.16-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Id75550d93612a6ebffc64c8dfcdfd1d3a6073249
This commit is contained in:
@@ -474,7 +474,7 @@ No additional type data follow ``btf_type``.
|
||||
* ``info.kind_flag``: 0
|
||||
* ``info.kind``: BTF_KIND_DECL_TAG
|
||||
* ``info.vlen``: 0
|
||||
* ``type``: ``struct``, ``union``, ``func`` or ``var``
|
||||
* ``type``: ``struct``, ``union``, ``func``, ``var`` or ``typedef``
|
||||
|
||||
``btf_type`` is followed by ``struct btf_decl_tag``.::
|
||||
|
||||
@@ -483,8 +483,8 @@ No additional type data follow ``btf_type``.
|
||||
};
|
||||
|
||||
The ``name_off`` encodes btf_decl_tag attribute string.
|
||||
The ``type`` should be ``struct``, ``union``, ``func`` or ``var``.
|
||||
For ``var`` type, ``btf_decl_tag.component_idx`` must be ``-1``.
|
||||
The ``type`` should be ``struct``, ``union``, ``func``, ``var`` or ``typedef``.
|
||||
For ``var`` or ``typedef`` type, ``btf_decl_tag.component_idx`` must be ``-1``.
|
||||
For the other three types, if the btf_decl_tag attribute is
|
||||
applied to the ``struct``, ``union`` or ``func`` itself,
|
||||
``btf_decl_tag.component_idx`` must be ``-1``. Otherwise,
|
||||
|
||||
@@ -553,9 +553,9 @@ struct bpf_binary_header {
|
||||
};
|
||||
|
||||
struct bpf_prog_stats {
|
||||
u64 cnt;
|
||||
u64 nsecs;
|
||||
u64 misses;
|
||||
u64_stats_t cnt;
|
||||
u64_stats_t nsecs;
|
||||
u64_stats_t misses;
|
||||
struct u64_stats_sync syncp;
|
||||
} __aligned(2 * sizeof(u64));
|
||||
|
||||
@@ -614,13 +614,14 @@ static __always_inline u32 __bpf_prog_run(const struct bpf_prog *prog,
|
||||
if (static_branch_unlikely(&bpf_stats_enabled_key)) {
|
||||
struct bpf_prog_stats *stats;
|
||||
u64 start = sched_clock();
|
||||
unsigned long flags;
|
||||
|
||||
ret = dfunc(ctx, prog->insnsi, prog->bpf_func);
|
||||
stats = this_cpu_ptr(prog->stats);
|
||||
u64_stats_update_begin(&stats->syncp);
|
||||
stats->cnt++;
|
||||
stats->nsecs += sched_clock() - start;
|
||||
u64_stats_update_end(&stats->syncp);
|
||||
flags = u64_stats_update_begin_irqsave(&stats->syncp);
|
||||
u64_stats_inc(&stats->cnt);
|
||||
u64_stats_add(&stats->nsecs, sched_clock() - start);
|
||||
u64_stats_update_end_irqrestore(&stats->syncp, flags);
|
||||
} else {
|
||||
ret = dfunc(ctx, prog->insnsi, prog->bpf_func);
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ static bool btf_type_is_decl_tag(const struct btf_type *t)
|
||||
static bool btf_type_is_decl_tag_target(const struct btf_type *t)
|
||||
{
|
||||
return btf_type_is_func(t) || btf_type_is_struct(t) ||
|
||||
btf_type_is_var(t);
|
||||
btf_type_is_var(t) || btf_type_is_typedef(t);
|
||||
}
|
||||
|
||||
u32 btf_nr_types(const struct btf *btf)
|
||||
@@ -3885,7 +3885,7 @@ static int btf_decl_tag_resolve(struct btf_verifier_env *env,
|
||||
|
||||
component_idx = btf_type_decl_tag(t)->component_idx;
|
||||
if (component_idx != -1) {
|
||||
if (btf_type_is_var(next_type)) {
|
||||
if (btf_type_is_var(next_type) || btf_type_is_typedef(next_type)) {
|
||||
btf_verifier_log_type(env, v->t, "Invalid component_idx");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1809,8 +1809,14 @@ static int bpf_prog_release(struct inode *inode, struct file *filp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bpf_prog_kstats {
|
||||
u64 nsecs;
|
||||
u64 cnt;
|
||||
u64 misses;
|
||||
};
|
||||
|
||||
static void bpf_prog_get_stats(const struct bpf_prog *prog,
|
||||
struct bpf_prog_stats *stats)
|
||||
struct bpf_prog_kstats *stats)
|
||||
{
|
||||
u64 nsecs = 0, cnt = 0, misses = 0;
|
||||
int cpu;
|
||||
@@ -1823,9 +1829,9 @@ static void bpf_prog_get_stats(const struct bpf_prog *prog,
|
||||
st = per_cpu_ptr(prog->stats, cpu);
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&st->syncp);
|
||||
tnsecs = st->nsecs;
|
||||
tcnt = st->cnt;
|
||||
tmisses = st->misses;
|
||||
tnsecs = u64_stats_read(&st->nsecs);
|
||||
tcnt = u64_stats_read(&st->cnt);
|
||||
tmisses = u64_stats_read(&st->misses);
|
||||
} while (u64_stats_fetch_retry_irq(&st->syncp, start));
|
||||
nsecs += tnsecs;
|
||||
cnt += tcnt;
|
||||
@@ -1841,7 +1847,7 @@ static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
|
||||
{
|
||||
const struct bpf_prog *prog = filp->private_data;
|
||||
char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
|
||||
struct bpf_prog_stats stats;
|
||||
struct bpf_prog_kstats stats;
|
||||
|
||||
bpf_prog_get_stats(prog, &stats);
|
||||
bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
|
||||
@@ -3582,7 +3588,7 @@ static int bpf_prog_get_info_by_fd(struct file *file,
|
||||
struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
|
||||
struct bpf_prog_info info;
|
||||
u32 info_len = attr->info.info_len;
|
||||
struct bpf_prog_stats stats;
|
||||
struct bpf_prog_kstats stats;
|
||||
char __user *uinsns;
|
||||
u32 ulen;
|
||||
int err;
|
||||
|
||||
@@ -545,7 +545,7 @@ static void notrace inc_misses_counter(struct bpf_prog *prog)
|
||||
|
||||
stats = this_cpu_ptr(prog->stats);
|
||||
u64_stats_update_begin(&stats->syncp);
|
||||
stats->misses++;
|
||||
u64_stats_inc(&stats->misses);
|
||||
u64_stats_update_end(&stats->syncp);
|
||||
}
|
||||
|
||||
@@ -586,11 +586,13 @@ static void notrace update_prog_stats(struct bpf_prog *prog,
|
||||
* Hence check that 'start' is valid.
|
||||
*/
|
||||
start > NO_START_TIME) {
|
||||
unsigned long flags;
|
||||
|
||||
stats = this_cpu_ptr(prog->stats);
|
||||
u64_stats_update_begin(&stats->syncp);
|
||||
stats->cnt++;
|
||||
stats->nsecs += sched_clock() - start;
|
||||
u64_stats_update_end(&stats->syncp);
|
||||
flags = u64_stats_update_begin_irqsave(&stats->syncp);
|
||||
u64_stats_inc(&stats->cnt);
|
||||
u64_stats_add(&stats->nsecs, sched_clock() - start);
|
||||
u64_stats_update_end_irqrestore(&stats->syncp, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +62,9 @@ void seccomp_bpf_print(struct sock_filter *filter, size_t count);
|
||||
#define EXPAND(...) __VA_ARGS__
|
||||
|
||||
/* Ensure that we load the logically correct offset. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
|
||||
#else
|
||||
#error "Unknown endianness"
|
||||
@@ -85,10 +85,10 @@ void seccomp_bpf_print(struct sock_filter *filter, size_t count);
|
||||
#elif __BITS_PER_LONG == 64
|
||||
|
||||
/* Ensure that we load the logically correct offset. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define ENDIAN(_lo, _hi) _lo, _hi
|
||||
#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define ENDIAN(_lo, _hi) _hi, _lo
|
||||
#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
|
||||
#endif
|
||||
|
||||
@@ -31,22 +31,22 @@ LIBBPF = $(LIBBPF_OUTPUT)libbpf.a
|
||||
LIBBPF_BOOTSTRAP_OUTPUT = $(BOOTSTRAP_OUTPUT)libbpf/
|
||||
LIBBPF_BOOTSTRAP = $(LIBBPF_BOOTSTRAP_OUTPUT)libbpf.a
|
||||
|
||||
# We need to copy nlattr.h which is not otherwise exported by libbpf, but still
|
||||
# required by bpftool.
|
||||
LIBBPF_INTERNAL_HDRS := $(addprefix $(LIBBPF_HDRS_DIR)/,nlattr.h)
|
||||
# We need to copy hashmap.h and nlattr.h which is not otherwise exported by
|
||||
# libbpf, but still required by bpftool.
|
||||
LIBBPF_INTERNAL_HDRS := $(addprefix $(LIBBPF_HDRS_DIR)/,hashmap.h nlattr.h)
|
||||
|
||||
ifeq ($(BPFTOOL_VERSION),)
|
||||
BPFTOOL_VERSION := $(shell make -rR --no-print-directory -sC ../../.. kernelversion)
|
||||
endif
|
||||
|
||||
$(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBBPF_BOOTSTRAP_OUTPUT):
|
||||
$(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBBPF_BOOTSTRAP_OUTPUT) $(LIBBPF_HDRS_DIR):
|
||||
$(QUIET_MKDIR)mkdir -p $@
|
||||
|
||||
$(LIBBPF): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_OUTPUT)
|
||||
$(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_OUTPUT) \
|
||||
DESTDIR=$(LIBBPF_DESTDIR) prefix= $(LIBBPF) install_headers
|
||||
|
||||
$(LIBBPF_INTERNAL_HDRS): $(LIBBPF_HDRS_DIR)/%.h: $(BPF_DIR)/%.h $(LIBBPF)
|
||||
$(LIBBPF_INTERNAL_HDRS): $(LIBBPF_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_HDRS_DIR)
|
||||
$(call QUIET_INSTALL, $@)
|
||||
$(Q)install -m 644 -t $(LIBBPF_HDRS_DIR) $<
|
||||
|
||||
@@ -209,7 +209,7 @@ $(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP)
|
||||
$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
|
||||
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
$(BOOTSTRAP_OUTPUT)%.o: %.c | $(BOOTSTRAP_OUTPUT)
|
||||
$(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)
|
||||
$(QUIET_CC)$(HOSTCC) $(CFLAGS) -c -MMD -o $@ $<
|
||||
|
||||
$(OUTPUT)%.o: %.c
|
||||
|
||||
@@ -8,14 +8,15 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <linux/btf.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/hashmap.h>
|
||||
#include <bpf/libbpf.h>
|
||||
|
||||
#include "json_writer.h"
|
||||
#include "main.h"
|
||||
|
||||
@@ -40,14 +41,9 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
|
||||
[BTF_KIND_DECL_TAG] = "DECL_TAG",
|
||||
};
|
||||
|
||||
struct btf_attach_table {
|
||||
DECLARE_HASHTABLE(table, 16);
|
||||
};
|
||||
|
||||
struct btf_attach_point {
|
||||
__u32 obj_id;
|
||||
__u32 btf_id;
|
||||
struct hlist_node hash;
|
||||
};
|
||||
|
||||
static const char *btf_int_enc_str(__u8 encoding)
|
||||
@@ -645,21 +641,8 @@ static int btf_parse_fd(int *argc, char ***argv)
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void delete_btf_table(struct btf_attach_table *tab)
|
||||
{
|
||||
struct btf_attach_point *obj;
|
||||
struct hlist_node *tmp;
|
||||
|
||||
unsigned int bkt;
|
||||
|
||||
hash_for_each_safe(tab->table, bkt, tmp, obj, hash) {
|
||||
hash_del(&obj->hash);
|
||||
free(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
build_btf_type_table(struct btf_attach_table *tab, enum bpf_obj_type type,
|
||||
build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
|
||||
void *info, __u32 *len)
|
||||
{
|
||||
static const char * const names[] = {
|
||||
@@ -667,7 +650,6 @@ build_btf_type_table(struct btf_attach_table *tab, enum bpf_obj_type type,
|
||||
[BPF_OBJ_PROG] = "prog",
|
||||
[BPF_OBJ_MAP] = "map",
|
||||
};
|
||||
struct btf_attach_point *obj_node;
|
||||
__u32 btf_id, id = 0;
|
||||
int err;
|
||||
int fd;
|
||||
@@ -741,28 +723,25 @@ build_btf_type_table(struct btf_attach_table *tab, enum bpf_obj_type type,
|
||||
if (!btf_id)
|
||||
continue;
|
||||
|
||||
obj_node = calloc(1, sizeof(*obj_node));
|
||||
if (!obj_node) {
|
||||
p_err("failed to allocate memory: %s", strerror(errno));
|
||||
err = -ENOMEM;
|
||||
err = hashmap__append(tab, u32_as_hash_field(btf_id),
|
||||
u32_as_hash_field(id));
|
||||
if (err) {
|
||||
p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
|
||||
btf_id, id, strerror(errno));
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
obj_node->obj_id = id;
|
||||
obj_node->btf_id = btf_id;
|
||||
hash_add(tab->table, &obj_node->hash, obj_node->btf_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
delete_btf_table(tab);
|
||||
hashmap__free(tab);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
build_btf_tables(struct btf_attach_table *btf_prog_table,
|
||||
struct btf_attach_table *btf_map_table)
|
||||
build_btf_tables(struct hashmap *btf_prog_table,
|
||||
struct hashmap *btf_map_table)
|
||||
{
|
||||
struct bpf_prog_info prog_info;
|
||||
__u32 prog_len = sizeof(prog_info);
|
||||
@@ -778,7 +757,7 @@ build_btf_tables(struct btf_attach_table *btf_prog_table,
|
||||
err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
|
||||
&map_len);
|
||||
if (err) {
|
||||
delete_btf_table(btf_prog_table);
|
||||
hashmap__free(btf_prog_table);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -787,10 +766,10 @@ build_btf_tables(struct btf_attach_table *btf_prog_table,
|
||||
|
||||
static void
|
||||
show_btf_plain(struct bpf_btf_info *info, int fd,
|
||||
struct btf_attach_table *btf_prog_table,
|
||||
struct btf_attach_table *btf_map_table)
|
||||
struct hashmap *btf_prog_table,
|
||||
struct hashmap *btf_map_table)
|
||||
{
|
||||
struct btf_attach_point *obj;
|
||||
struct hashmap_entry *entry;
|
||||
const char *name = u64_to_ptr(info->name);
|
||||
int n;
|
||||
|
||||
@@ -804,29 +783,30 @@ show_btf_plain(struct bpf_btf_info *info, int fd,
|
||||
printf("size %uB", info->btf_size);
|
||||
|
||||
n = 0;
|
||||
hash_for_each_possible(btf_prog_table->table, obj, hash, info->id) {
|
||||
if (obj->btf_id == info->id)
|
||||
printf("%s%u", n++ == 0 ? " prog_ids " : ",",
|
||||
obj->obj_id);
|
||||
hashmap__for_each_key_entry(btf_prog_table, entry,
|
||||
u32_as_hash_field(info->id)) {
|
||||
printf("%s%u", n++ == 0 ? " prog_ids " : ",",
|
||||
hash_field_as_u32(entry->value));
|
||||
}
|
||||
|
||||
n = 0;
|
||||
hash_for_each_possible(btf_map_table->table, obj, hash, info->id) {
|
||||
if (obj->btf_id == info->id)
|
||||
printf("%s%u", n++ == 0 ? " map_ids " : ",",
|
||||
obj->obj_id);
|
||||
hashmap__for_each_key_entry(btf_map_table, entry,
|
||||
u32_as_hash_field(info->id)) {
|
||||
printf("%s%u", n++ == 0 ? " map_ids " : ",",
|
||||
hash_field_as_u32(entry->value));
|
||||
}
|
||||
emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");
|
||||
|
||||
emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
show_btf_json(struct bpf_btf_info *info, int fd,
|
||||
struct btf_attach_table *btf_prog_table,
|
||||
struct btf_attach_table *btf_map_table)
|
||||
struct hashmap *btf_prog_table,
|
||||
struct hashmap *btf_map_table)
|
||||
{
|
||||
struct btf_attach_point *obj;
|
||||
struct hashmap_entry *entry;
|
||||
const char *name = u64_to_ptr(info->name);
|
||||
|
||||
jsonw_start_object(json_wtr); /* btf object */
|
||||
@@ -835,23 +815,21 @@ show_btf_json(struct bpf_btf_info *info, int fd,
|
||||
|
||||
jsonw_name(json_wtr, "prog_ids");
|
||||
jsonw_start_array(json_wtr); /* prog_ids */
|
||||
hash_for_each_possible(btf_prog_table->table, obj, hash,
|
||||
info->id) {
|
||||
if (obj->btf_id == info->id)
|
||||
jsonw_uint(json_wtr, obj->obj_id);
|
||||
hashmap__for_each_key_entry(btf_prog_table, entry,
|
||||
u32_as_hash_field(info->id)) {
|
||||
jsonw_uint(json_wtr, hash_field_as_u32(entry->value));
|
||||
}
|
||||
jsonw_end_array(json_wtr); /* prog_ids */
|
||||
|
||||
jsonw_name(json_wtr, "map_ids");
|
||||
jsonw_start_array(json_wtr); /* map_ids */
|
||||
hash_for_each_possible(btf_map_table->table, obj, hash,
|
||||
info->id) {
|
||||
if (obj->btf_id == info->id)
|
||||
jsonw_uint(json_wtr, obj->obj_id);
|
||||
hashmap__for_each_key_entry(btf_map_table, entry,
|
||||
u32_as_hash_field(info->id)) {
|
||||
jsonw_uint(json_wtr, hash_field_as_u32(entry->value));
|
||||
}
|
||||
jsonw_end_array(json_wtr); /* map_ids */
|
||||
|
||||
emit_obj_refs_json(&refs_table, info->id, json_wtr); /* pids */
|
||||
emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */
|
||||
|
||||
jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
|
||||
|
||||
@@ -862,8 +840,8 @@ show_btf_json(struct bpf_btf_info *info, int fd,
|
||||
}
|
||||
|
||||
static int
|
||||
show_btf(int fd, struct btf_attach_table *btf_prog_table,
|
||||
struct btf_attach_table *btf_map_table)
|
||||
show_btf(int fd, struct hashmap *btf_prog_table,
|
||||
struct hashmap *btf_map_table)
|
||||
{
|
||||
struct bpf_btf_info info;
|
||||
__u32 len = sizeof(info);
|
||||
@@ -900,8 +878,8 @@ show_btf(int fd, struct btf_attach_table *btf_prog_table,
|
||||
|
||||
static int do_show(int argc, char **argv)
|
||||
{
|
||||
struct btf_attach_table btf_prog_table;
|
||||
struct btf_attach_table btf_map_table;
|
||||
struct hashmap *btf_prog_table;
|
||||
struct hashmap *btf_map_table;
|
||||
int err, fd = -1;
|
||||
__u32 id = 0;
|
||||
|
||||
@@ -917,9 +895,19 @@ static int do_show(int argc, char **argv)
|
||||
return BAD_ARG();
|
||||
}
|
||||
|
||||
hash_init(btf_prog_table.table);
|
||||
hash_init(btf_map_table.table);
|
||||
err = build_btf_tables(&btf_prog_table, &btf_map_table);
|
||||
btf_prog_table = hashmap__new(hash_fn_for_key_as_id,
|
||||
equal_fn_for_key_as_id, NULL);
|
||||
btf_map_table = hashmap__new(hash_fn_for_key_as_id,
|
||||
equal_fn_for_key_as_id, NULL);
|
||||
if (!btf_prog_table || !btf_map_table) {
|
||||
hashmap__free(btf_prog_table);
|
||||
hashmap__free(btf_map_table);
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
p_err("failed to create hashmap for object references");
|
||||
return -1;
|
||||
}
|
||||
err = build_btf_tables(btf_prog_table, btf_map_table);
|
||||
if (err) {
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
@@ -928,7 +916,7 @@ static int do_show(int argc, char **argv)
|
||||
build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
|
||||
|
||||
if (fd >= 0) {
|
||||
err = show_btf(fd, &btf_prog_table, &btf_map_table);
|
||||
err = show_btf(fd, btf_prog_table, btf_map_table);
|
||||
close(fd);
|
||||
goto exit_free;
|
||||
}
|
||||
@@ -960,7 +948,7 @@ static int do_show(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
err = show_btf(fd, &btf_prog_table, &btf_map_table);
|
||||
err = show_btf(fd, btf_prog_table, btf_map_table);
|
||||
close(fd);
|
||||
if (err)
|
||||
break;
|
||||
@@ -970,9 +958,9 @@ static int do_show(int argc, char **argv)
|
||||
jsonw_end_array(json_wtr); /* root array */
|
||||
|
||||
exit_free:
|
||||
delete_btf_table(&btf_prog_table);
|
||||
delete_btf_table(&btf_map_table);
|
||||
delete_obj_refs_table(&refs_table);
|
||||
hashmap__free(btf_prog_table);
|
||||
hashmap__free(btf_map_table);
|
||||
delete_obj_refs_table(refs_table);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <sys/vfs.h>
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/hashmap.h>
|
||||
#include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
|
||||
|
||||
#include "main.h"
|
||||
@@ -393,7 +394,7 @@ void print_hex_data_json(uint8_t *data, size_t len)
|
||||
}
|
||||
|
||||
/* extra params for nftw cb */
|
||||
static struct pinned_obj_table *build_fn_table;
|
||||
static struct hashmap *build_fn_table;
|
||||
static enum bpf_obj_type build_fn_type;
|
||||
|
||||
static int do_build_table_cb(const char *fpath, const struct stat *sb,
|
||||
@@ -401,9 +402,9 @@ static int do_build_table_cb(const char *fpath, const struct stat *sb,
|
||||
{
|
||||
struct bpf_prog_info pinned_info;
|
||||
__u32 len = sizeof(pinned_info);
|
||||
struct pinned_obj *obj_node;
|
||||
enum bpf_obj_type objtype;
|
||||
int fd, err = 0;
|
||||
char *path;
|
||||
|
||||
if (typeflag != FTW_F)
|
||||
goto out_ret;
|
||||
@@ -420,28 +421,26 @@ static int do_build_table_cb(const char *fpath, const struct stat *sb,
|
||||
if (bpf_obj_get_info_by_fd(fd, &pinned_info, &len))
|
||||
goto out_close;
|
||||
|
||||
obj_node = calloc(1, sizeof(*obj_node));
|
||||
if (!obj_node) {
|
||||
path = strdup(fpath);
|
||||
if (!path) {
|
||||
err = -1;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
obj_node->id = pinned_info.id;
|
||||
obj_node->path = strdup(fpath);
|
||||
if (!obj_node->path) {
|
||||
err = -1;
|
||||
free(obj_node);
|
||||
err = hashmap__append(build_fn_table, u32_as_hash_field(pinned_info.id), path);
|
||||
if (err) {
|
||||
p_err("failed to append entry to hashmap for ID %u, path '%s': %s",
|
||||
pinned_info.id, path, strerror(errno));
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
hash_add(build_fn_table->table, &obj_node->hash, obj_node->id);
|
||||
out_close:
|
||||
close(fd);
|
||||
out_ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
int build_pinned_obj_table(struct pinned_obj_table *tab,
|
||||
int build_pinned_obj_table(struct hashmap *tab,
|
||||
enum bpf_obj_type type)
|
||||
{
|
||||
struct mntent *mntent = NULL;
|
||||
@@ -470,17 +469,18 @@ int build_pinned_obj_table(struct pinned_obj_table *tab,
|
||||
return err;
|
||||
}
|
||||
|
||||
void delete_pinned_obj_table(struct pinned_obj_table *tab)
|
||||
void delete_pinned_obj_table(struct hashmap *map)
|
||||
{
|
||||
struct pinned_obj *obj;
|
||||
struct hlist_node *tmp;
|
||||
unsigned int bkt;
|
||||
struct hashmap_entry *entry;
|
||||
size_t bkt;
|
||||
|
||||
hash_for_each_safe(tab->table, bkt, tmp, obj, hash) {
|
||||
hash_del(&obj->hash);
|
||||
free(obj->path);
|
||||
free(obj);
|
||||
}
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
hashmap__for_each_entry(map, entry, bkt)
|
||||
free(entry->value);
|
||||
|
||||
hashmap__free(map);
|
||||
}
|
||||
|
||||
unsigned int get_page_size(void)
|
||||
@@ -962,3 +962,13 @@ int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
size_t hash_fn_for_key_as_id(const void *key, void *ctx)
|
||||
{
|
||||
return (size_t)key;
|
||||
}
|
||||
|
||||
bool equal_fn_for_key_as_id(const void *k1, const void *k2, void *ctx)
|
||||
{
|
||||
return k1 == k2;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/hashmap.h>
|
||||
|
||||
#include "json_writer.h"
|
||||
#include "main.h"
|
||||
@@ -20,6 +21,8 @@ static const char * const link_type_name[] = {
|
||||
[BPF_LINK_TYPE_NETNS] = "netns",
|
||||
};
|
||||
|
||||
static struct hashmap *link_table;
|
||||
|
||||
static int link_parse_fd(int *argc, char ***argv)
|
||||
{
|
||||
int fd;
|
||||
@@ -156,19 +159,18 @@ static int show_link_close_json(int fd, struct bpf_link_info *info)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hash_empty(link_table.table)) {
|
||||
struct pinned_obj *obj;
|
||||
if (!hashmap__empty(link_table)) {
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
jsonw_name(json_wtr, "pinned");
|
||||
jsonw_start_array(json_wtr);
|
||||
hash_for_each_possible(link_table.table, obj, hash, info->id) {
|
||||
if (obj->id == info->id)
|
||||
jsonw_string(json_wtr, obj->path);
|
||||
}
|
||||
hashmap__for_each_key_entry(link_table, entry,
|
||||
u32_as_hash_field(info->id))
|
||||
jsonw_string(json_wtr, entry->value);
|
||||
jsonw_end_array(json_wtr);
|
||||
}
|
||||
|
||||
emit_obj_refs_json(&refs_table, info->id, json_wtr);
|
||||
emit_obj_refs_json(refs_table, info->id, json_wtr);
|
||||
|
||||
jsonw_end_object(json_wtr);
|
||||
|
||||
@@ -244,15 +246,14 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hash_empty(link_table.table)) {
|
||||
struct pinned_obj *obj;
|
||||
if (!hashmap__empty(link_table)) {
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
hash_for_each_possible(link_table.table, obj, hash, info->id) {
|
||||
if (obj->id == info->id)
|
||||
printf("\n\tpinned %s", obj->path);
|
||||
}
|
||||
hashmap__for_each_key_entry(link_table, entry,
|
||||
u32_as_hash_field(info->id))
|
||||
printf("\n\tpinned %s", (char *)entry->value);
|
||||
}
|
||||
emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");
|
||||
emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
|
||||
|
||||
printf("\n");
|
||||
|
||||
@@ -302,8 +303,15 @@ static int do_show(int argc, char **argv)
|
||||
__u32 id = 0;
|
||||
int err, fd;
|
||||
|
||||
if (show_pinned)
|
||||
build_pinned_obj_table(&link_table, BPF_OBJ_LINK);
|
||||
if (show_pinned) {
|
||||
link_table = hashmap__new(hash_fn_for_key_as_id,
|
||||
equal_fn_for_key_as_id, NULL);
|
||||
if (!link_table) {
|
||||
p_err("failed to create hashmap for pinned paths");
|
||||
return -1;
|
||||
}
|
||||
build_pinned_obj_table(link_table, BPF_OBJ_LINK);
|
||||
}
|
||||
build_obj_refs_table(&refs_table, BPF_OBJ_LINK);
|
||||
|
||||
if (argc == 2) {
|
||||
@@ -344,7 +352,10 @@ static int do_show(int argc, char **argv)
|
||||
if (json_output)
|
||||
jsonw_end_array(json_wtr);
|
||||
|
||||
delete_obj_refs_table(&refs_table);
|
||||
delete_obj_refs_table(refs_table);
|
||||
|
||||
if (show_pinned)
|
||||
delete_pinned_obj_table(link_table);
|
||||
|
||||
return errno == ENOENT ? 0 : -1;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/hashmap.h>
|
||||
#include <bpf/libbpf.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
@@ -31,10 +32,7 @@ bool verifier_logs;
|
||||
bool relaxed_maps;
|
||||
bool use_loader;
|
||||
struct btf *base_btf;
|
||||
struct pinned_obj_table prog_table;
|
||||
struct pinned_obj_table map_table;
|
||||
struct pinned_obj_table link_table;
|
||||
struct obj_refs_table refs_table;
|
||||
struct hashmap *refs_table;
|
||||
|
||||
static void __noreturn clean_and_exit(int i)
|
||||
{
|
||||
@@ -409,10 +407,6 @@ int main(int argc, char **argv)
|
||||
block_mount = false;
|
||||
bin_name = argv[0];
|
||||
|
||||
hash_init(prog_table.table);
|
||||
hash_init(map_table.table);
|
||||
hash_init(link_table.table);
|
||||
|
||||
opterr = 0;
|
||||
while ((opt = getopt_long(argc, argv, "VhpjfLmndB:",
|
||||
options, NULL)) >= 0) {
|
||||
@@ -479,11 +473,6 @@ int main(int argc, char **argv)
|
||||
if (json_output)
|
||||
jsonw_destroy(&json_wtr);
|
||||
|
||||
if (show_pinned) {
|
||||
delete_pinned_obj_table(&prog_table);
|
||||
delete_pinned_obj_table(&map_table);
|
||||
delete_pinned_obj_table(&link_table);
|
||||
}
|
||||
btf__free(base_btf);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <tools/libc_compat.h>
|
||||
|
||||
#include <bpf/hashmap.h>
|
||||
#include <bpf/libbpf.h>
|
||||
|
||||
#include "json_writer.h"
|
||||
@@ -91,10 +91,7 @@ extern bool verifier_logs;
|
||||
extern bool relaxed_maps;
|
||||
extern bool use_loader;
|
||||
extern struct btf *base_btf;
|
||||
extern struct pinned_obj_table prog_table;
|
||||
extern struct pinned_obj_table map_table;
|
||||
extern struct pinned_obj_table link_table;
|
||||
extern struct obj_refs_table refs_table;
|
||||
extern struct hashmap *refs_table;
|
||||
|
||||
void __printf(1, 2) p_err(const char *fmt, ...);
|
||||
void __printf(1, 2) p_info(const char *fmt, ...);
|
||||
@@ -108,28 +105,12 @@ void set_max_rlimit(void);
|
||||
|
||||
int mount_tracefs(const char *target);
|
||||
|
||||
struct pinned_obj_table {
|
||||
DECLARE_HASHTABLE(table, 16);
|
||||
};
|
||||
|
||||
struct pinned_obj {
|
||||
__u32 id;
|
||||
char *path;
|
||||
struct hlist_node hash;
|
||||
};
|
||||
|
||||
struct obj_refs_table {
|
||||
DECLARE_HASHTABLE(table, 16);
|
||||
};
|
||||
|
||||
struct obj_ref {
|
||||
int pid;
|
||||
char comm[16];
|
||||
};
|
||||
|
||||
struct obj_refs {
|
||||
struct hlist_node node;
|
||||
__u32 id;
|
||||
int ref_cnt;
|
||||
struct obj_ref *refs;
|
||||
};
|
||||
@@ -137,15 +118,15 @@ struct obj_refs {
|
||||
struct btf;
|
||||
struct bpf_line_info;
|
||||
|
||||
int build_pinned_obj_table(struct pinned_obj_table *table,
|
||||
int build_pinned_obj_table(struct hashmap *table,
|
||||
enum bpf_obj_type type);
|
||||
void delete_pinned_obj_table(struct pinned_obj_table *tab);
|
||||
__weak int build_obj_refs_table(struct obj_refs_table *table,
|
||||
void delete_pinned_obj_table(struct hashmap *table);
|
||||
__weak int build_obj_refs_table(struct hashmap **table,
|
||||
enum bpf_obj_type type);
|
||||
__weak void delete_obj_refs_table(struct obj_refs_table *table);
|
||||
__weak void emit_obj_refs_json(struct obj_refs_table *table, __u32 id,
|
||||
__weak void delete_obj_refs_table(struct hashmap *table);
|
||||
__weak void emit_obj_refs_json(struct hashmap *table, __u32 id,
|
||||
json_writer_t *json_wtr);
|
||||
__weak void emit_obj_refs_plain(struct obj_refs_table *table, __u32 id,
|
||||
__weak void emit_obj_refs_plain(struct hashmap *table, __u32 id,
|
||||
const char *prefix);
|
||||
void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);
|
||||
void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);
|
||||
@@ -259,4 +240,23 @@ int do_filter_dump(struct tcmsg *ifinfo, struct nlattr **tb, const char *kind,
|
||||
|
||||
int print_all_levels(__maybe_unused enum libbpf_print_level level,
|
||||
const char *format, va_list args);
|
||||
|
||||
size_t hash_fn_for_key_as_id(const void *key, void *ctx);
|
||||
bool equal_fn_for_key_as_id(const void *k1, const void *k2, void *ctx);
|
||||
|
||||
static inline void *u32_as_hash_field(__u32 x)
|
||||
{
|
||||
return (void *)(uintptr_t)x;
|
||||
}
|
||||
|
||||
static inline __u32 hash_field_as_u32(const void *x)
|
||||
{
|
||||
return (__u32)(uintptr_t)x;
|
||||
}
|
||||
|
||||
static inline bool hashmap__empty(struct hashmap *map)
|
||||
{
|
||||
return map ? hashmap__size(map) == 0 : true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/hashmap.h>
|
||||
|
||||
#include "json_writer.h"
|
||||
#include "main.h"
|
||||
@@ -56,6 +57,8 @@ const char * const map_type_name[] = {
|
||||
|
||||
const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
|
||||
|
||||
static struct hashmap *map_table;
|
||||
|
||||
static bool map_is_per_cpu(__u32 type)
|
||||
{
|
||||
return type == BPF_MAP_TYPE_PERCPU_HASH ||
|
||||
@@ -535,19 +538,18 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
|
||||
if (info->btf_id)
|
||||
jsonw_int_field(json_wtr, "btf_id", info->btf_id);
|
||||
|
||||
if (!hash_empty(map_table.table)) {
|
||||
struct pinned_obj *obj;
|
||||
if (!hashmap__empty(map_table)) {
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
jsonw_name(json_wtr, "pinned");
|
||||
jsonw_start_array(json_wtr);
|
||||
hash_for_each_possible(map_table.table, obj, hash, info->id) {
|
||||
if (obj->id == info->id)
|
||||
jsonw_string(json_wtr, obj->path);
|
||||
}
|
||||
hashmap__for_each_key_entry(map_table, entry,
|
||||
u32_as_hash_field(info->id))
|
||||
jsonw_string(json_wtr, entry->value);
|
||||
jsonw_end_array(json_wtr);
|
||||
}
|
||||
|
||||
emit_obj_refs_json(&refs_table, info->id, json_wtr);
|
||||
emit_obj_refs_json(refs_table, info->id, json_wtr);
|
||||
|
||||
jsonw_end_object(json_wtr);
|
||||
|
||||
@@ -610,13 +612,12 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (!hash_empty(map_table.table)) {
|
||||
struct pinned_obj *obj;
|
||||
if (!hashmap__empty(map_table)) {
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
hash_for_each_possible(map_table.table, obj, hash, info->id) {
|
||||
if (obj->id == info->id)
|
||||
printf("\n\tpinned %s", obj->path);
|
||||
}
|
||||
hashmap__for_each_key_entry(map_table, entry,
|
||||
u32_as_hash_field(info->id))
|
||||
printf("\n\tpinned %s", (char *)entry->value);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@@ -636,7 +637,7 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
|
||||
if (frozen)
|
||||
printf("%sfrozen", info->btf_id ? " " : "");
|
||||
|
||||
emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");
|
||||
emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
|
||||
|
||||
printf("\n");
|
||||
return 0;
|
||||
@@ -694,8 +695,15 @@ static int do_show(int argc, char **argv)
|
||||
int err;
|
||||
int fd;
|
||||
|
||||
if (show_pinned)
|
||||
build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
|
||||
if (show_pinned) {
|
||||
map_table = hashmap__new(hash_fn_for_key_as_id,
|
||||
equal_fn_for_key_as_id, NULL);
|
||||
if (!map_table) {
|
||||
p_err("failed to create hashmap for pinned paths");
|
||||
return -1;
|
||||
}
|
||||
build_pinned_obj_table(map_table, BPF_OBJ_MAP);
|
||||
}
|
||||
build_obj_refs_table(&refs_table, BPF_OBJ_MAP);
|
||||
|
||||
if (argc == 2)
|
||||
@@ -740,7 +748,10 @@ static int do_show(int argc, char **argv)
|
||||
if (json_output)
|
||||
jsonw_end_array(json_wtr);
|
||||
|
||||
delete_obj_refs_table(&refs_table);
|
||||
delete_obj_refs_table(refs_table);
|
||||
|
||||
if (show_pinned)
|
||||
delete_pinned_obj_table(map_table);
|
||||
|
||||
return errno == ENOENT ? 0 : -1;
|
||||
}
|
||||
|
||||
@@ -6,35 +6,37 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/hashmap.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "skeleton/pid_iter.h"
|
||||
|
||||
#ifdef BPFTOOL_WITHOUT_SKELETONS
|
||||
|
||||
int build_obj_refs_table(struct obj_refs_table *table, enum bpf_obj_type type)
|
||||
int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
void delete_obj_refs_table(struct obj_refs_table *table) {}
|
||||
void emit_obj_refs_plain(struct obj_refs_table *table, __u32 id, const char *prefix) {}
|
||||
void emit_obj_refs_json(struct obj_refs_table *table, __u32 id, json_writer_t *json_writer) {}
|
||||
void delete_obj_refs_table(struct hashmap *map) {}
|
||||
void emit_obj_refs_plain(struct hashmap *map, __u32 id, const char *prefix) {}
|
||||
void emit_obj_refs_json(struct hashmap *map, __u32 id, json_writer_t *json_writer) {}
|
||||
|
||||
#else /* BPFTOOL_WITHOUT_SKELETONS */
|
||||
|
||||
#include "pid_iter.skel.h"
|
||||
|
||||
static void add_ref(struct obj_refs_table *table, struct pid_iter_entry *e)
|
||||
static void add_ref(struct hashmap *map, struct pid_iter_entry *e)
|
||||
{
|
||||
struct hashmap_entry *entry;
|
||||
struct obj_refs *refs;
|
||||
struct obj_ref *ref;
|
||||
int err, i;
|
||||
void *tmp;
|
||||
int i;
|
||||
|
||||
hash_for_each_possible(table->table, refs, node, e->id) {
|
||||
if (refs->id != e->id)
|
||||
continue;
|
||||
hashmap__for_each_key_entry(map, entry, u32_as_hash_field(e->id)) {
|
||||
refs = entry->value;
|
||||
|
||||
for (i = 0; i < refs->ref_cnt; i++) {
|
||||
if (refs->refs[i].pid == e->pid)
|
||||
@@ -64,7 +66,6 @@ static void add_ref(struct obj_refs_table *table, struct pid_iter_entry *e)
|
||||
return;
|
||||
}
|
||||
|
||||
refs->id = e->id;
|
||||
refs->refs = malloc(sizeof(*refs->refs));
|
||||
if (!refs->refs) {
|
||||
free(refs);
|
||||
@@ -76,7 +77,11 @@ static void add_ref(struct obj_refs_table *table, struct pid_iter_entry *e)
|
||||
ref->pid = e->pid;
|
||||
memcpy(ref->comm, e->comm, sizeof(ref->comm));
|
||||
refs->ref_cnt = 1;
|
||||
hash_add(table->table, &refs->node, e->id);
|
||||
|
||||
err = hashmap__append(map, u32_as_hash_field(e->id), refs);
|
||||
if (err)
|
||||
p_err("failed to append entry to hashmap for ID %u: %s",
|
||||
e->id, strerror(errno));
|
||||
}
|
||||
|
||||
static int __printf(2, 0)
|
||||
@@ -87,7 +92,7 @@ libbpf_print_none(__maybe_unused enum libbpf_print_level level,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int build_obj_refs_table(struct obj_refs_table *table, enum bpf_obj_type type)
|
||||
int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type)
|
||||
{
|
||||
struct pid_iter_entry *e;
|
||||
char buf[4096 / sizeof(*e) * sizeof(*e)];
|
||||
@@ -95,7 +100,11 @@ int build_obj_refs_table(struct obj_refs_table *table, enum bpf_obj_type type)
|
||||
int err, ret, fd = -1, i;
|
||||
libbpf_print_fn_t default_print;
|
||||
|
||||
hash_init(table->table);
|
||||
*map = hashmap__new(hash_fn_for_key_as_id, equal_fn_for_key_as_id, NULL);
|
||||
if (!*map) {
|
||||
p_err("failed to create hashmap for PID references");
|
||||
return -1;
|
||||
}
|
||||
set_max_rlimit();
|
||||
|
||||
skel = pid_iter_bpf__open();
|
||||
@@ -151,7 +160,7 @@ int build_obj_refs_table(struct obj_refs_table *table, enum bpf_obj_type type)
|
||||
|
||||
e = (void *)buf;
|
||||
for (i = 0; i < ret; i++, e++) {
|
||||
add_ref(table, e);
|
||||
add_ref(*map, e);
|
||||
}
|
||||
}
|
||||
err = 0;
|
||||
@@ -162,39 +171,44 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
void delete_obj_refs_table(struct obj_refs_table *table)
|
||||
void delete_obj_refs_table(struct hashmap *map)
|
||||
{
|
||||
struct obj_refs *refs;
|
||||
struct hlist_node *tmp;
|
||||
unsigned int bkt;
|
||||
struct hashmap_entry *entry;
|
||||
size_t bkt;
|
||||
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
hashmap__for_each_entry(map, entry, bkt) {
|
||||
struct obj_refs *refs = entry->value;
|
||||
|
||||
hash_for_each_safe(table->table, bkt, tmp, refs, node) {
|
||||
hash_del(&refs->node);
|
||||
free(refs->refs);
|
||||
free(refs);
|
||||
}
|
||||
|
||||
hashmap__free(map);
|
||||
}
|
||||
|
||||
void emit_obj_refs_json(struct obj_refs_table *table, __u32 id,
|
||||
void emit_obj_refs_json(struct hashmap *map, __u32 id,
|
||||
json_writer_t *json_writer)
|
||||
{
|
||||
struct obj_refs *refs;
|
||||
struct obj_ref *ref;
|
||||
int i;
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
if (hash_empty(table->table))
|
||||
if (hashmap__empty(map))
|
||||
return;
|
||||
|
||||
hash_for_each_possible(table->table, refs, node, id) {
|
||||
if (refs->id != id)
|
||||
continue;
|
||||
hashmap__for_each_key_entry(map, entry, u32_as_hash_field(id)) {
|
||||
struct obj_refs *refs = entry->value;
|
||||
int i;
|
||||
|
||||
if (refs->ref_cnt == 0)
|
||||
break;
|
||||
|
||||
jsonw_name(json_writer, "pids");
|
||||
jsonw_start_array(json_writer);
|
||||
for (i = 0; i < refs->ref_cnt; i++) {
|
||||
ref = &refs->refs[i];
|
||||
struct obj_ref *ref = &refs->refs[i];
|
||||
|
||||
jsonw_start_object(json_writer);
|
||||
jsonw_int_field(json_writer, "pid", ref->pid);
|
||||
jsonw_string_field(json_writer, "comm", ref->comm);
|
||||
@@ -205,24 +219,24 @@ void emit_obj_refs_json(struct obj_refs_table *table, __u32 id,
|
||||
}
|
||||
}
|
||||
|
||||
void emit_obj_refs_plain(struct obj_refs_table *table, __u32 id, const char *prefix)
|
||||
void emit_obj_refs_plain(struct hashmap *map, __u32 id, const char *prefix)
|
||||
{
|
||||
struct obj_refs *refs;
|
||||
struct obj_ref *ref;
|
||||
int i;
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
if (hash_empty(table->table))
|
||||
if (hashmap__empty(map))
|
||||
return;
|
||||
|
||||
hash_for_each_possible(table->table, refs, node, id) {
|
||||
if (refs->id != id)
|
||||
continue;
|
||||
hashmap__for_each_key_entry(map, entry, u32_as_hash_field(id)) {
|
||||
struct obj_refs *refs = entry->value;
|
||||
int i;
|
||||
|
||||
if (refs->ref_cnt == 0)
|
||||
break;
|
||||
|
||||
printf("%s", prefix);
|
||||
for (i = 0; i < refs->ref_cnt; i++) {
|
||||
ref = &refs->refs[i];
|
||||
struct obj_ref *ref = &refs->refs[i];
|
||||
|
||||
printf("%s%s(%d)", i == 0 ? "" : ", ", ref->comm, ref->pid);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/hashmap.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <bpf/skel_internal.h>
|
||||
|
||||
@@ -84,6 +85,8 @@ static const char * const attach_type_strings[] = {
|
||||
[__MAX_BPF_ATTACH_TYPE] = NULL,
|
||||
};
|
||||
|
||||
static struct hashmap *prog_table;
|
||||
|
||||
static enum bpf_attach_type parse_attach_type(const char *str)
|
||||
{
|
||||
enum bpf_attach_type type;
|
||||
@@ -307,18 +310,12 @@ static void show_prog_metadata(int fd, __u32 num_maps)
|
||||
if (printed_header)
|
||||
jsonw_end_object(json_wtr);
|
||||
} else {
|
||||
json_writer_t *btf_wtr = jsonw_new(stdout);
|
||||
json_writer_t *btf_wtr;
|
||||
struct btf_dumper d = {
|
||||
.btf = btf,
|
||||
.jw = btf_wtr,
|
||||
.is_plain_text = true,
|
||||
};
|
||||
|
||||
if (!btf_wtr) {
|
||||
p_err("jsonw alloc failed");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < vlen; i++, vsi++) {
|
||||
t_var = btf__type_by_id(btf, vsi->type);
|
||||
name = btf__name_by_offset(btf, t_var->name_off);
|
||||
@@ -328,6 +325,14 @@ static void show_prog_metadata(int fd, __u32 num_maps)
|
||||
|
||||
if (!printed_header) {
|
||||
printf("\tmetadata:");
|
||||
|
||||
btf_wtr = jsonw_new(stdout);
|
||||
if (!btf_wtr) {
|
||||
p_err("jsonw alloc failed");
|
||||
goto out_free;
|
||||
}
|
||||
d.jw = btf_wtr,
|
||||
|
||||
printed_header = true;
|
||||
}
|
||||
|
||||
@@ -414,19 +419,18 @@ static void print_prog_json(struct bpf_prog_info *info, int fd)
|
||||
if (info->btf_id)
|
||||
jsonw_int_field(json_wtr, "btf_id", info->btf_id);
|
||||
|
||||
if (!hash_empty(prog_table.table)) {
|
||||
struct pinned_obj *obj;
|
||||
if (!hashmap__empty(prog_table)) {
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
jsonw_name(json_wtr, "pinned");
|
||||
jsonw_start_array(json_wtr);
|
||||
hash_for_each_possible(prog_table.table, obj, hash, info->id) {
|
||||
if (obj->id == info->id)
|
||||
jsonw_string(json_wtr, obj->path);
|
||||
}
|
||||
hashmap__for_each_key_entry(prog_table, entry,
|
||||
u32_as_hash_field(info->id))
|
||||
jsonw_string(json_wtr, entry->value);
|
||||
jsonw_end_array(json_wtr);
|
||||
}
|
||||
|
||||
emit_obj_refs_json(&refs_table, info->id, json_wtr);
|
||||
emit_obj_refs_json(refs_table, info->id, json_wtr);
|
||||
|
||||
show_prog_metadata(fd, info->nr_map_ids);
|
||||
|
||||
@@ -486,19 +490,18 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd)
|
||||
if (info->nr_map_ids)
|
||||
show_prog_maps(fd, info->nr_map_ids);
|
||||
|
||||
if (!hash_empty(prog_table.table)) {
|
||||
struct pinned_obj *obj;
|
||||
if (!hashmap__empty(prog_table)) {
|
||||
struct hashmap_entry *entry;
|
||||
|
||||
hash_for_each_possible(prog_table.table, obj, hash, info->id) {
|
||||
if (obj->id == info->id)
|
||||
printf("\n\tpinned %s", obj->path);
|
||||
}
|
||||
hashmap__for_each_key_entry(prog_table, entry,
|
||||
u32_as_hash_field(info->id))
|
||||
printf("\n\tpinned %s", (char *)entry->value);
|
||||
}
|
||||
|
||||
if (info->btf_id)
|
||||
printf("\n\tbtf_id %d", info->btf_id);
|
||||
|
||||
emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");
|
||||
emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
|
||||
|
||||
printf("\n");
|
||||
|
||||
@@ -565,8 +568,15 @@ static int do_show(int argc, char **argv)
|
||||
int err;
|
||||
int fd;
|
||||
|
||||
if (show_pinned)
|
||||
build_pinned_obj_table(&prog_table, BPF_OBJ_PROG);
|
||||
if (show_pinned) {
|
||||
prog_table = hashmap__new(hash_fn_for_key_as_id,
|
||||
equal_fn_for_key_as_id, NULL);
|
||||
if (!prog_table) {
|
||||
p_err("failed to create hashmap for pinned paths");
|
||||
return -1;
|
||||
}
|
||||
build_pinned_obj_table(prog_table, BPF_OBJ_PROG);
|
||||
}
|
||||
build_obj_refs_table(&refs_table, BPF_OBJ_PROG);
|
||||
|
||||
if (argc == 2)
|
||||
@@ -609,7 +619,10 @@ static int do_show(int argc, char **argv)
|
||||
if (json_output)
|
||||
jsonw_end_array(json_wtr);
|
||||
|
||||
delete_obj_refs_table(&refs_table);
|
||||
delete_obj_refs_table(refs_table);
|
||||
|
||||
if (show_pinned)
|
||||
delete_pinned_obj_table(prog_table);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ enum bpf_enum_value_kind {
|
||||
#define __CORE_RELO(src, field, info) \
|
||||
__builtin_preserve_field_info((src)->field, BPF_FIELD_##info)
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \
|
||||
bpf_probe_read_kernel( \
|
||||
(void *)dst, \
|
||||
|
||||
@@ -236,17 +236,23 @@ static int btf_parse_hdr(struct btf *btf)
|
||||
}
|
||||
btf_bswap_hdr(hdr);
|
||||
} else if (hdr->magic != BTF_MAGIC) {
|
||||
pr_debug("Invalid BTF magic:%x\n", hdr->magic);
|
||||
pr_debug("Invalid BTF magic: %x\n", hdr->magic);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
meta_left = btf->raw_size - sizeof(*hdr);
|
||||
if (meta_left < hdr->str_off + hdr->str_len) {
|
||||
pr_debug("Invalid BTF total size:%u\n", btf->raw_size);
|
||||
if (btf->raw_size < hdr->hdr_len) {
|
||||
pr_debug("BTF header len %u larger than data size %u\n",
|
||||
hdr->hdr_len, btf->raw_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hdr->type_off + hdr->type_len > hdr->str_off) {
|
||||
meta_left = btf->raw_size - hdr->hdr_len;
|
||||
if (meta_left < (long long)hdr->str_off + hdr->str_len) {
|
||||
pr_debug("Invalid BTF total size: %u\n", btf->raw_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((long long)hdr->type_off + hdr->type_len > hdr->str_off) {
|
||||
pr_debug("Invalid BTF data sections layout: type data at %u + %u, strings data at %u + %u\n",
|
||||
hdr->type_off, hdr->type_len, hdr->str_off, hdr->str_len);
|
||||
return -EINVAL;
|
||||
@@ -532,9 +538,9 @@ int btf__set_pointer_size(struct btf *btf, size_t ptr_sz)
|
||||
|
||||
static bool is_host_big_endian(void)
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
return false;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
return true;
|
||||
#else
|
||||
# error "Unrecognized __BYTE_ORDER__"
|
||||
|
||||
@@ -1576,11 +1576,11 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d,
|
||||
/* Bitfield value retrieval is done in two steps; first relevant bytes are
|
||||
* stored in num, then we left/right shift num to eliminate irrelevant bits.
|
||||
*/
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
for (i = t->size - 1; i >= 0; i--)
|
||||
num = num * 256 + bytes[i];
|
||||
nr_copy_bits = bit_sz + bits_offset;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
for (i = 0; i < t->size; i++)
|
||||
num = num * 256 + bytes[i];
|
||||
nr_copy_bits = t->size * 8 - bits_offset;
|
||||
@@ -1700,10 +1700,10 @@ static int btf_dump_int_data(struct btf_dump *d,
|
||||
/* avoid use of __int128 as some 32-bit platforms do not
|
||||
* support it.
|
||||
*/
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
lsi = ints[0];
|
||||
msi = ints[1];
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
lsi = ints[1];
|
||||
msi = ints[0];
|
||||
#else
|
||||
|
||||
@@ -285,7 +285,7 @@ struct bpf_program {
|
||||
size_t sub_insn_off;
|
||||
|
||||
char *name;
|
||||
/* sec_name with / replaced by _; makes recursive pinning
|
||||
/* name with / replaced by _; makes recursive pinning
|
||||
* in bpf_object__pin_programs easier
|
||||
*/
|
||||
char *pin_name;
|
||||
@@ -618,7 +618,16 @@ static char *__bpf_program__pin_name(struct bpf_program *prog)
|
||||
{
|
||||
char *name, *p;
|
||||
|
||||
name = p = strdup(prog->sec_name);
|
||||
if (libbpf_mode & LIBBPF_STRICT_SEC_NAME)
|
||||
name = strdup(prog->name);
|
||||
else
|
||||
name = strdup(prog->sec_name);
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
p = name;
|
||||
|
||||
while ((p = strchr(p, '/')))
|
||||
*p = '_';
|
||||
|
||||
@@ -1139,6 +1148,7 @@ static struct bpf_object *bpf_object__new(const char *path,
|
||||
size_t obj_buf_sz,
|
||||
const char *obj_name)
|
||||
{
|
||||
bool strict = (libbpf_mode & LIBBPF_STRICT_NO_OBJECT_LIST);
|
||||
struct bpf_object *obj;
|
||||
char *end;
|
||||
|
||||
@@ -1179,7 +1189,8 @@ static struct bpf_object *bpf_object__new(const char *path,
|
||||
obj->loaded = false;
|
||||
|
||||
INIT_LIST_HEAD(&obj->list);
|
||||
list_add(&obj->list, &bpf_objects_list);
|
||||
if (!strict)
|
||||
list_add(&obj->list, &bpf_objects_list);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -1290,10 +1301,10 @@ errout:
|
||||
|
||||
static int bpf_object__check_endianness(struct bpf_object *obj)
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
if (obj->efile.ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
return 0;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
if (obj->efile.ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
return 0;
|
||||
#else
|
||||
@@ -5396,7 +5407,7 @@ static int bpf_core_apply_relo(struct bpf_program *prog,
|
||||
* relocated, so it's enough to just subtract in-section offset
|
||||
*/
|
||||
insn_idx = insn_idx - prog->sec_insn_off;
|
||||
if (insn_idx > prog->insns_cnt)
|
||||
if (insn_idx >= prog->insns_cnt)
|
||||
return -EINVAL;
|
||||
insn = &prog->insns[insn_idx];
|
||||
|
||||
@@ -6644,8 +6655,6 @@ int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver)
|
||||
out:
|
||||
if (err)
|
||||
pr_warn("failed to load program '%s'\n", prog->name);
|
||||
zfree(&prog->insns);
|
||||
prog->insns_cnt = 0;
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
@@ -7352,8 +7361,7 @@ static int check_path(const char *path)
|
||||
return err;
|
||||
}
|
||||
|
||||
int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
|
||||
int instance)
|
||||
static int bpf_program_pin_instance(struct bpf_program *prog, const char *path, int instance)
|
||||
{
|
||||
char *cp, errmsg[STRERR_BUFSIZE];
|
||||
int err;
|
||||
@@ -7388,8 +7396,7 @@ int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_program__unpin_instance(struct bpf_program *prog, const char *path,
|
||||
int instance)
|
||||
static int bpf_program_unpin_instance(struct bpf_program *prog, const char *path, int instance)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -7417,6 +7424,12 @@ int bpf_program__unpin_instance(struct bpf_program *prog, const char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((alias("bpf_program_pin_instance")))
|
||||
int bpf_object__pin_instance(struct bpf_program *prog, const char *path, int instance);
|
||||
|
||||
__attribute__((alias("bpf_program_unpin_instance")))
|
||||
int bpf_program__unpin_instance(struct bpf_program *prog, const char *path, int instance);
|
||||
|
||||
int bpf_program__pin(struct bpf_program *prog, const char *path)
|
||||
{
|
||||
int i, err;
|
||||
@@ -7441,7 +7454,7 @@ int bpf_program__pin(struct bpf_program *prog, const char *path)
|
||||
|
||||
if (prog->instances.nr == 1) {
|
||||
/* don't create subdirs when pinning single instance */
|
||||
return bpf_program__pin_instance(prog, path, 0);
|
||||
return bpf_program_pin_instance(prog, path, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < prog->instances.nr; i++) {
|
||||
@@ -7457,7 +7470,7 @@ int bpf_program__pin(struct bpf_program *prog, const char *path)
|
||||
goto err_unpin;
|
||||
}
|
||||
|
||||
err = bpf_program__pin_instance(prog, buf, i);
|
||||
err = bpf_program_pin_instance(prog, buf, i);
|
||||
if (err)
|
||||
goto err_unpin;
|
||||
}
|
||||
@@ -7475,7 +7488,7 @@ err_unpin:
|
||||
else if (len >= PATH_MAX)
|
||||
continue;
|
||||
|
||||
bpf_program__unpin_instance(prog, buf, i);
|
||||
bpf_program_unpin_instance(prog, buf, i);
|
||||
}
|
||||
|
||||
rmdir(path);
|
||||
@@ -7503,7 +7516,7 @@ int bpf_program__unpin(struct bpf_program *prog, const char *path)
|
||||
|
||||
if (prog->instances.nr == 1) {
|
||||
/* don't create subdirs when pinning single instance */
|
||||
return bpf_program__unpin_instance(prog, path, 0);
|
||||
return bpf_program_unpin_instance(prog, path, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < prog->instances.nr; i++) {
|
||||
@@ -7516,7 +7529,7 @@ int bpf_program__unpin(struct bpf_program *prog, const char *path)
|
||||
else if (len >= PATH_MAX)
|
||||
return libbpf_err(-ENAMETOOLONG);
|
||||
|
||||
err = bpf_program__unpin_instance(prog, buf, i);
|
||||
err = bpf_program_unpin_instance(prog, buf, i);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -7925,6 +7938,10 @@ struct bpf_object *
|
||||
bpf_object__next(struct bpf_object *prev)
|
||||
{
|
||||
struct bpf_object *next;
|
||||
bool strict = (libbpf_mode & LIBBPF_STRICT_NO_OBJECT_LIST);
|
||||
|
||||
if (strict)
|
||||
return NULL;
|
||||
|
||||
if (!prev)
|
||||
next = list_first_entry(&bpf_objects_list,
|
||||
@@ -8135,6 +8152,16 @@ size_t bpf_program__size(const struct bpf_program *prog)
|
||||
return prog->insns_cnt * BPF_INSN_SZ;
|
||||
}
|
||||
|
||||
const struct bpf_insn *bpf_program__insns(const struct bpf_program *prog)
|
||||
{
|
||||
return prog->insns;
|
||||
}
|
||||
|
||||
size_t bpf_program__insn_cnt(const struct bpf_program *prog)
|
||||
{
|
||||
return prog->insns_cnt;
|
||||
}
|
||||
|
||||
int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
|
||||
bpf_program_prep_t prep)
|
||||
{
|
||||
|
||||
@@ -168,7 +168,8 @@ LIBBPF_API struct bpf_program *
|
||||
bpf_object__find_program_by_name(const struct bpf_object *obj,
|
||||
const char *name);
|
||||
|
||||
LIBBPF_API struct bpf_object *bpf_object__next(struct bpf_object *prev);
|
||||
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "track bpf_objects in application code instead")
|
||||
struct bpf_object *bpf_object__next(struct bpf_object *prev);
|
||||
#define bpf_object__for_each_safe(pos, tmp) \
|
||||
for ((pos) = bpf_object__next(NULL), \
|
||||
(tmp) = bpf_object__next(pos); \
|
||||
@@ -224,14 +225,51 @@ LIBBPF_API bool bpf_program__autoload(const struct bpf_program *prog);
|
||||
LIBBPF_API int bpf_program__set_autoload(struct bpf_program *prog, bool autoload);
|
||||
|
||||
/* returns program size in bytes */
|
||||
LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_program__insn_cnt() instead")
|
||||
LIBBPF_API size_t bpf_program__size(const struct bpf_program *prog);
|
||||
|
||||
struct bpf_insn;
|
||||
|
||||
/**
|
||||
* @brief **bpf_program__insns()** gives read-only access to BPF program's
|
||||
* underlying BPF instructions.
|
||||
* @param prog BPF program for which to return instructions
|
||||
* @return a pointer to an array of BPF instructions that belong to the
|
||||
* specified BPF program
|
||||
*
|
||||
* Returned pointer is always valid and not NULL. Number of `struct bpf_insn`
|
||||
* pointed to can be fetched using **bpf_program__insn_cnt()** API.
|
||||
*
|
||||
* Keep in mind, libbpf can modify and append/delete BPF program's
|
||||
* instructions as it processes BPF object file and prepares everything for
|
||||
* uploading into the kernel. So depending on the point in BPF object
|
||||
* lifetime, **bpf_program__insns()** can return different sets of
|
||||
* instructions. As an example, during BPF object load phase BPF program
|
||||
* instructions will be CO-RE-relocated, BPF subprograms instructions will be
|
||||
* appended, ldimm64 instructions will have FDs embedded, etc. So instructions
|
||||
* returned before **bpf_object__load()** and after it might be quite
|
||||
* different.
|
||||
*/
|
||||
LIBBPF_API const struct bpf_insn *bpf_program__insns(const struct bpf_program *prog);
|
||||
/**
|
||||
* @brief **bpf_program__insn_cnt()** returns number of `struct bpf_insn`'s
|
||||
* that form specified BPF program.
|
||||
* @param prog BPF program for which to return number of BPF instructions
|
||||
*
|
||||
* See **bpf_program__insns()** documentation for notes on how libbpf can
|
||||
* change instructions and their count during different phases of
|
||||
* **bpf_object** lifetime.
|
||||
*/
|
||||
LIBBPF_API size_t bpf_program__insn_cnt(const struct bpf_program *prog);
|
||||
|
||||
LIBBPF_API int bpf_program__load(struct bpf_program *prog, char *license,
|
||||
__u32 kern_version);
|
||||
LIBBPF_API int bpf_program__fd(const struct bpf_program *prog);
|
||||
LIBBPF_DEPRECATED_SINCE(0, 7, "multi-instance bpf_program support is deprecated")
|
||||
LIBBPF_API int bpf_program__pin_instance(struct bpf_program *prog,
|
||||
const char *path,
|
||||
int instance);
|
||||
LIBBPF_DEPRECATED_SINCE(0, 7, "multi-instance bpf_program support is deprecated")
|
||||
LIBBPF_API int bpf_program__unpin_instance(struct bpf_program *prog,
|
||||
const char *path,
|
||||
int instance);
|
||||
@@ -365,8 +403,6 @@ LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_iter(const struct bpf_program *prog,
|
||||
const struct bpf_iter_attach_opts *opts);
|
||||
|
||||
struct bpf_insn;
|
||||
|
||||
/*
|
||||
* Libbpf allows callers to adjust BPF programs before being loaded
|
||||
* into kernel. One program in an object file can be transformed into
|
||||
@@ -395,7 +431,7 @@ struct bpf_insn;
|
||||
* one instance. In this case bpf_program__fd(prog) is equal to
|
||||
* bpf_program__nth_fd(prog, 0).
|
||||
*/
|
||||
|
||||
LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_program__insns() for getting bpf_program instructions")
|
||||
struct bpf_prog_prep_result {
|
||||
/*
|
||||
* If not NULL, load new instruction array.
|
||||
@@ -424,9 +460,11 @@ typedef int (*bpf_program_prep_t)(struct bpf_program *prog, int n,
|
||||
struct bpf_insn *insns, int insns_cnt,
|
||||
struct bpf_prog_prep_result *res);
|
||||
|
||||
LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_program__insns() for getting bpf_program instructions")
|
||||
LIBBPF_API int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,
|
||||
bpf_program_prep_t prep);
|
||||
|
||||
LIBBPF_DEPRECATED_SINCE(0, 7, "multi-instance bpf_program support is deprecated")
|
||||
LIBBPF_API int bpf_program__nth_fd(const struct bpf_program *prog, int n);
|
||||
|
||||
/*
|
||||
|
||||
@@ -393,6 +393,8 @@ LIBBPF_0.6.0 {
|
||||
bpf_object__next_program;
|
||||
bpf_object__prev_map;
|
||||
bpf_object__prev_program;
|
||||
bpf_program__insn_cnt;
|
||||
bpf_program__insns;
|
||||
btf__add_btf;
|
||||
btf__add_decl_tag;
|
||||
btf__raw_data;
|
||||
|
||||
@@ -52,8 +52,17 @@ enum libbpf_strict_mode {
|
||||
* allowed, with LIBBPF_STRICT_SEC_PREFIX this will become
|
||||
* unrecognized by libbpf and would have to be just SEC("xdp") and
|
||||
* SEC("xdp") and SEC("perf_event").
|
||||
*
|
||||
* Note, in this mode the program pin path will be based on the
|
||||
* function name instead of section name.
|
||||
*/
|
||||
LIBBPF_STRICT_SEC_NAME = 0x04,
|
||||
/*
|
||||
* Disable the global 'bpf_objects_list'. Maintaining this list adds
|
||||
* a race condition to bpf_object__open() and bpf_object__close().
|
||||
* Clients can maintain it on their own if it is valuable for them.
|
||||
*/
|
||||
LIBBPF_STRICT_NO_OBJECT_LIST = 0x08,
|
||||
|
||||
__LIBBPF_STRICT_LAST,
|
||||
};
|
||||
|
||||
@@ -323,12 +323,12 @@ static int init_output_elf(struct bpf_linker *linker, const char *file)
|
||||
|
||||
linker->elf_hdr->e_machine = EM_BPF;
|
||||
linker->elf_hdr->e_type = ET_REL;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
linker->elf_hdr->e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
linker->elf_hdr->e_ident[EI_DATA] = ELFDATA2MSB;
|
||||
#else
|
||||
#error "Unknown __BYTE_ORDER"
|
||||
#error "Unknown __BYTE_ORDER__"
|
||||
#endif
|
||||
|
||||
/* STRTAB */
|
||||
@@ -538,12 +538,12 @@ static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
|
||||
const struct bpf_linker_file_opts *opts,
|
||||
struct src_obj *obj)
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
const int host_endianness = ELFDATA2LSB;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
const int host_endianness = ELFDATA2MSB;
|
||||
#else
|
||||
#error "Unknown __BYTE_ORDER"
|
||||
#error "Unknown __BYTE_ORDER__"
|
||||
#endif
|
||||
int err = 0;
|
||||
Elf_Scn *scn;
|
||||
|
||||
@@ -662,7 +662,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,
|
||||
*validate = true; /* signedness is never ambiguous */
|
||||
break;
|
||||
case BPF_FIELD_LSHIFT_U64:
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
*val = 64 - (bit_off + bit_sz - byte_off * 8);
|
||||
#else
|
||||
*val = (8 - byte_sz) * 8 + (bit_off - byte_off * 8);
|
||||
|
||||
@@ -421,10 +421,9 @@ ifeq ($($(TRUNNER_TESTS_DIR)-tests-hdr),)
|
||||
$(TRUNNER_TESTS_DIR)-tests-hdr := y
|
||||
$(TRUNNER_TESTS_HDR): $(TRUNNER_TESTS_DIR)/*.c
|
||||
$$(call msg,TEST-HDR,$(TRUNNER_BINARY),$$@)
|
||||
$$(shell ( cd $(TRUNNER_TESTS_DIR); \
|
||||
echo '/* Generated header, do not edit */'; \
|
||||
ls *.c 2> /dev/null | \
|
||||
sed -e 's@\([^\.]*\)\.c@DEFINE_TEST(\1)@'; \
|
||||
$$(shell (echo '/* Generated header, do not edit */'; \
|
||||
sed -n -E 's/^void (serial_)?test_([a-zA-Z0-9_]+)\((void)?\).*/DEFINE_TEST(\2)/p' \
|
||||
$(TRUNNER_TESTS_DIR)/*.c | sort ; \
|
||||
) > $$@)
|
||||
endif
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
|
||||
const char *cfg_map_name = "jmp_table";
|
||||
bool cfg_attach = true;
|
||||
char *cfg_section_name;
|
||||
char *cfg_prog_name;
|
||||
char *cfg_path_name;
|
||||
|
||||
static void load_and_attach_program(void)
|
||||
@@ -25,7 +25,11 @@ static void load_and_attach_program(void)
|
||||
int prog_fd, ret;
|
||||
struct bpf_object *obj;
|
||||
|
||||
ret = bpf_flow_load(&obj, cfg_path_name, cfg_section_name,
|
||||
ret = libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
|
||||
if (ret)
|
||||
error(1, 0, "failed to enable libbpf strict mode: %d", ret);
|
||||
|
||||
ret = bpf_flow_load(&obj, cfg_path_name, cfg_prog_name,
|
||||
cfg_map_name, NULL, &prog_fd, NULL);
|
||||
if (ret)
|
||||
error(1, 0, "bpf_flow_load %s", cfg_path_name);
|
||||
@@ -75,15 +79,15 @@ static void parse_opts(int argc, char **argv)
|
||||
break;
|
||||
case 'p':
|
||||
if (cfg_path_name)
|
||||
error(1, 0, "only one prog name can be given");
|
||||
error(1, 0, "only one path can be given");
|
||||
|
||||
cfg_path_name = optarg;
|
||||
break;
|
||||
case 's':
|
||||
if (cfg_section_name)
|
||||
error(1, 0, "only one section can be given");
|
||||
if (cfg_prog_name)
|
||||
error(1, 0, "only one prog can be given");
|
||||
|
||||
cfg_section_name = optarg;
|
||||
cfg_prog_name = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -94,7 +98,7 @@ static void parse_opts(int argc, char **argv)
|
||||
if (cfg_attach && !cfg_path_name)
|
||||
error(1, 0, "must provide a path to the BPF program");
|
||||
|
||||
if (cfg_attach && !cfg_section_name)
|
||||
if (cfg_attach && !cfg_prog_name)
|
||||
error(1, 0, "must provide a section name");
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
static inline int bpf_flow_load(struct bpf_object **obj,
|
||||
const char *path,
|
||||
const char *section_name,
|
||||
const char *prog_name,
|
||||
const char *map_name,
|
||||
const char *keys_map_name,
|
||||
int *prog_fd,
|
||||
@@ -23,13 +23,7 @@ static inline int bpf_flow_load(struct bpf_object **obj,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
main_prog = NULL;
|
||||
bpf_object__for_each_program(prog, *obj) {
|
||||
if (strcmp(section_name, bpf_program__section_name(prog)) == 0) {
|
||||
main_prog = prog;
|
||||
break;
|
||||
}
|
||||
}
|
||||
main_prog = bpf_object__find_program_by_name(*obj, prog_name);
|
||||
if (!main_prog)
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
/* this is how USDT semaphore is actually defined, except volatile modifier */
|
||||
volatile unsigned short uprobe_ref_ctr __attribute__((unused)) __attribute((section(".probes")));
|
||||
|
||||
/* attach point */
|
||||
static void method(void) {
|
||||
return ;
|
||||
}
|
||||
|
||||
void test_attach_probe(void)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
|
||||
@@ -33,7 +38,7 @@ void test_attach_probe(void)
|
||||
if (CHECK(base_addr < 0, "get_base_addr",
|
||||
"failed to find base addr: %zd", base_addr))
|
||||
return;
|
||||
uprobe_offset = get_uprobe_offset(&get_base_addr, base_addr);
|
||||
uprobe_offset = get_uprobe_offset(&method, base_addr);
|
||||
|
||||
ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
|
||||
if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
|
||||
@@ -98,7 +103,7 @@ void test_attach_probe(void)
|
||||
goto cleanup;
|
||||
|
||||
/* trigger & validate uprobe & uretprobe */
|
||||
get_base_addr();
|
||||
method();
|
||||
|
||||
if (CHECK(skel->bss->uprobe_res != 3, "check_uprobe_res",
|
||||
"wrong uprobe res: %d\n", skel->bss->uprobe_res))
|
||||
|
||||
@@ -39,82 +39,166 @@ struct scale_test_def {
|
||||
bool fails;
|
||||
};
|
||||
|
||||
void test_bpf_verif_scale(void)
|
||||
static void scale_test(const char *file,
|
||||
enum bpf_prog_type attach_type,
|
||||
bool should_fail)
|
||||
{
|
||||
struct scale_test_def tests[] = {
|
||||
{ "loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT, true /* fails */ },
|
||||
|
||||
{ "test_verif_scale1.o", BPF_PROG_TYPE_SCHED_CLS },
|
||||
{ "test_verif_scale2.o", BPF_PROG_TYPE_SCHED_CLS },
|
||||
{ "test_verif_scale3.o", BPF_PROG_TYPE_SCHED_CLS },
|
||||
|
||||
{ "pyperf_global.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
{ "pyperf_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
|
||||
/* full unroll by llvm */
|
||||
{ "pyperf50.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
{ "pyperf100.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
{ "pyperf180.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
|
||||
/* partial unroll. llvm will unroll loop ~150 times.
|
||||
* C loop count -> 600.
|
||||
* Asm loop count -> 4.
|
||||
* 16k insns in loop body.
|
||||
* Total of 5 such loops. Total program size ~82k insns.
|
||||
*/
|
||||
{ "pyperf600.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
|
||||
/* no unroll at all.
|
||||
* C loop count -> 600.
|
||||
* ASM loop count -> 600.
|
||||
* ~110 insns in loop body.
|
||||
* Total of 5 such loops. Total program size ~1500 insns.
|
||||
*/
|
||||
{ "pyperf600_nounroll.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
|
||||
{ "loop1.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
{ "loop2.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
{ "loop4.o", BPF_PROG_TYPE_SCHED_CLS },
|
||||
{ "loop5.o", BPF_PROG_TYPE_SCHED_CLS },
|
||||
{ "loop6.o", BPF_PROG_TYPE_KPROBE },
|
||||
|
||||
/* partial unroll. 19k insn in a loop.
|
||||
* Total program size 20.8k insn.
|
||||
* ~350k processed_insns
|
||||
*/
|
||||
{ "strobemeta.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
|
||||
/* no unroll, tiny loops */
|
||||
{ "strobemeta_nounroll1.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
{ "strobemeta_nounroll2.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
|
||||
/* non-inlined subprogs */
|
||||
{ "strobemeta_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
|
||||
|
||||
{ "test_sysctl_loop1.o", BPF_PROG_TYPE_CGROUP_SYSCTL },
|
||||
{ "test_sysctl_loop2.o", BPF_PROG_TYPE_CGROUP_SYSCTL },
|
||||
|
||||
{ "test_xdp_loop.o", BPF_PROG_TYPE_XDP },
|
||||
{ "test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL },
|
||||
};
|
||||
libbpf_print_fn_t old_print_fn = NULL;
|
||||
int err, i;
|
||||
int err;
|
||||
|
||||
if (env.verifier_stats) {
|
||||
test__force_log();
|
||||
old_print_fn = libbpf_set_print(libbpf_debug_print);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
const struct scale_test_def *test = &tests[i];
|
||||
|
||||
if (!test__start_subtest(test->file))
|
||||
continue;
|
||||
|
||||
err = check_load(test->file, test->attach_type);
|
||||
CHECK_FAIL(err && !test->fails);
|
||||
}
|
||||
err = check_load(file, attach_type);
|
||||
if (should_fail)
|
||||
ASSERT_ERR(err, "expect_error");
|
||||
else
|
||||
ASSERT_OK(err, "expect_success");
|
||||
|
||||
if (env.verifier_stats)
|
||||
libbpf_set_print(old_print_fn);
|
||||
}
|
||||
|
||||
void test_verif_scale1()
|
||||
{
|
||||
scale_test("test_verif_scale1.o", BPF_PROG_TYPE_SCHED_CLS, false);
|
||||
}
|
||||
|
||||
void test_verif_scale2()
|
||||
{
|
||||
scale_test("test_verif_scale2.o", BPF_PROG_TYPE_SCHED_CLS, false);
|
||||
}
|
||||
|
||||
void test_verif_scale3()
|
||||
{
|
||||
scale_test("test_verif_scale3.o", BPF_PROG_TYPE_SCHED_CLS, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_pyperf_global()
|
||||
{
|
||||
scale_test("pyperf_global.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_pyperf_subprogs()
|
||||
{
|
||||
scale_test("pyperf_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_pyperf50()
|
||||
{
|
||||
/* full unroll by llvm */
|
||||
scale_test("pyperf50.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_pyperf100()
|
||||
{
|
||||
/* full unroll by llvm */
|
||||
scale_test("pyperf100.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_pyperf180()
|
||||
{
|
||||
/* full unroll by llvm */
|
||||
scale_test("pyperf180.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_pyperf600()
|
||||
{
|
||||
/* partial unroll. llvm will unroll loop ~150 times.
|
||||
* C loop count -> 600.
|
||||
* Asm loop count -> 4.
|
||||
* 16k insns in loop body.
|
||||
* Total of 5 such loops. Total program size ~82k insns.
|
||||
*/
|
||||
scale_test("pyperf600.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_pyperf600_nounroll()
|
||||
{
|
||||
/* no unroll at all.
|
||||
* C loop count -> 600.
|
||||
* ASM loop count -> 600.
|
||||
* ~110 insns in loop body.
|
||||
* Total of 5 such loops. Total program size ~1500 insns.
|
||||
*/
|
||||
scale_test("pyperf600_nounroll.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_loop1()
|
||||
{
|
||||
scale_test("loop1.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_loop2()
|
||||
{
|
||||
scale_test("loop2.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_loop3_fail()
|
||||
{
|
||||
scale_test("loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT, true /* fails */);
|
||||
}
|
||||
|
||||
void test_verif_scale_loop4()
|
||||
{
|
||||
scale_test("loop4.o", BPF_PROG_TYPE_SCHED_CLS, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_loop5()
|
||||
{
|
||||
scale_test("loop5.o", BPF_PROG_TYPE_SCHED_CLS, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_loop6()
|
||||
{
|
||||
scale_test("loop6.o", BPF_PROG_TYPE_KPROBE, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_strobemeta()
|
||||
{
|
||||
/* partial unroll. 19k insn in a loop.
|
||||
* Total program size 20.8k insn.
|
||||
* ~350k processed_insns
|
||||
*/
|
||||
scale_test("strobemeta.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_strobemeta_nounroll1()
|
||||
{
|
||||
/* no unroll, tiny loops */
|
||||
scale_test("strobemeta_nounroll1.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_strobemeta_nounroll2()
|
||||
{
|
||||
/* no unroll, tiny loops */
|
||||
scale_test("strobemeta_nounroll2.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_strobemeta_subprogs()
|
||||
{
|
||||
/* non-inlined subprogs */
|
||||
scale_test("strobemeta_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_sysctl_loop1()
|
||||
{
|
||||
scale_test("test_sysctl_loop1.o", BPF_PROG_TYPE_CGROUP_SYSCTL, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_sysctl_loop2()
|
||||
{
|
||||
scale_test("test_sysctl_loop2.o", BPF_PROG_TYPE_CGROUP_SYSCTL, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_xdp_loop()
|
||||
{
|
||||
scale_test("test_xdp_loop.o", BPF_PROG_TYPE_XDP, false);
|
||||
}
|
||||
|
||||
void test_verif_scale_seg6_loop()
|
||||
{
|
||||
scale_test("test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL, false);
|
||||
}
|
||||
|
||||
@@ -3903,6 +3903,42 @@ static struct btf_raw_test raw_tests[] = {
|
||||
.btf_load_err = true,
|
||||
.err_str = "Invalid component_idx",
|
||||
},
|
||||
{
|
||||
.descr = "decl_tag test #13, typedef, well-formed",
|
||||
.raw_types = {
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||
BTF_TYPEDEF_ENC(NAME_TBD, 1), /* [2] */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 2, -1),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0t\0tag"),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "tag_type_check_btf",
|
||||
.key_size = sizeof(int),
|
||||
.value_size = 4,
|
||||
.key_type_id = 1,
|
||||
.value_type_id = 1,
|
||||
.max_entries = 1,
|
||||
},
|
||||
{
|
||||
.descr = "decl_tag test #14, typedef, invalid component_idx",
|
||||
.raw_types = {
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||
BTF_TYPEDEF_ENC(NAME_TBD, 1), /* [2] */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 2, 0),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0local\0tag"),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "tag_type_check_btf",
|
||||
.key_size = sizeof(int),
|
||||
.value_size = 4,
|
||||
.key_type_id = 1,
|
||||
.value_type_id = 1,
|
||||
.max_entries = 1,
|
||||
.btf_load_err = true,
|
||||
.err_str = "Invalid component_idx",
|
||||
},
|
||||
|
||||
}; /* struct btf_raw_test raw_tests[] */
|
||||
|
||||
@@ -6841,11 +6877,12 @@ const struct btf_dedup_test dedup_tests[] = {
|
||||
BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 8),
|
||||
BTF_FUNC_ENC(NAME_TBD, 12), /* [13] func */
|
||||
BTF_TYPE_FLOAT_ENC(NAME_TBD, 2), /* [14] float */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, -1), /* [15] tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, 1), /* [16] tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, -1), /* [15] decl_tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, 1), /* [16] decl_tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 7, -1), /* [17] decl_tag */
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"),
|
||||
BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P\0Q"),
|
||||
},
|
||||
.expect = {
|
||||
.raw_types = {
|
||||
@@ -6869,11 +6906,12 @@ const struct btf_dedup_test dedup_tests[] = {
|
||||
BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 8),
|
||||
BTF_FUNC_ENC(NAME_TBD, 12), /* [13] func */
|
||||
BTF_TYPE_FLOAT_ENC(NAME_TBD, 2), /* [14] float */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, -1), /* [15] tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, 1), /* [16] tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, -1), /* [15] decl_tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 13, 1), /* [16] decl_tag */
|
||||
BTF_DECL_TAG_ENC(NAME_TBD, 7, -1), /* [17] decl_tag */
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"),
|
||||
BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P\0Q"),
|
||||
},
|
||||
.opts = {
|
||||
.dont_resolve_fwds = false,
|
||||
@@ -7168,6 +7206,39 @@ const struct btf_dedup_test dedup_tests[] = {
|
||||
.dont_resolve_fwds = false,
|
||||
},
|
||||
},
|
||||
{
|
||||
.descr = "dedup: typedef tags",
|
||||
.input = {
|
||||
.raw_types = {
|
||||
/* int */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||
BTF_TYPEDEF_ENC(NAME_NTH(1), 1), /* [2] */
|
||||
BTF_TYPEDEF_ENC(NAME_NTH(1), 1), /* [3] */
|
||||
/* tag -> t: tag1, tag2 */
|
||||
BTF_DECL_TAG_ENC(NAME_NTH(2), 2, -1), /* [4] */
|
||||
BTF_DECL_TAG_ENC(NAME_NTH(3), 2, -1), /* [5] */
|
||||
/* tag -> t: tag1, tag3 */
|
||||
BTF_DECL_TAG_ENC(NAME_NTH(2), 3, -1), /* [6] */
|
||||
BTF_DECL_TAG_ENC(NAME_NTH(4), 3, -1), /* [7] */
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0t\0tag1\0tag2\0tag3"),
|
||||
},
|
||||
.expect = {
|
||||
.raw_types = {
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||
BTF_TYPEDEF_ENC(NAME_NTH(1), 1), /* [2] */
|
||||
BTF_DECL_TAG_ENC(NAME_NTH(2), 2, -1), /* [3] */
|
||||
BTF_DECL_TAG_ENC(NAME_NTH(3), 2, -1), /* [4] */
|
||||
BTF_DECL_TAG_ENC(NAME_NTH(4), 2, -1), /* [5] */
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0t\0tag1\0tag2\0tag3"),
|
||||
},
|
||||
.opts = {
|
||||
.dont_resolve_fwds = false,
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ static char *dump_buf;
|
||||
static size_t dump_buf_sz;
|
||||
static FILE *dump_buf_file;
|
||||
|
||||
void test_btf_dump_incremental(void)
|
||||
static void test_btf_dump_incremental(void)
|
||||
{
|
||||
struct btf *btf = NULL;
|
||||
struct btf_dump *d = NULL;
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
#include <bpf/btf.h>
|
||||
|
||||
void test_btf_endian() {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
enum btf_endianness endian = BTF_LITTLE_ENDIAN;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
enum btf_endianness endian = BTF_BIG_ENDIAN;
|
||||
#else
|
||||
#error "Unrecognized __BYTE_ORDER"
|
||||
#error "Unrecognized __BYTE_ORDER__"
|
||||
#endif
|
||||
enum btf_endianness swap_endian = 1 - endian;
|
||||
struct btf *btf = NULL, *swap_btf = NULL;
|
||||
|
||||
@@ -78,6 +78,12 @@ void serial_test_get_branch_snapshot(void)
|
||||
struct get_branch_snapshot *skel = NULL;
|
||||
int err;
|
||||
|
||||
/* Skip the test before we fix LBR snapshot for hypervisor. */
|
||||
if (is_hypervisor()) {
|
||||
test__skip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (create_perf_events()) {
|
||||
test__skip(); /* system doesn't support LBR */
|
||||
goto cleanup;
|
||||
@@ -91,9 +97,10 @@ void serial_test_get_branch_snapshot(void)
|
||||
if (!ASSERT_OK(err, "kallsyms_find"))
|
||||
goto cleanup;
|
||||
|
||||
err = kallsyms_find_next("bpf_testmod_loop_test", &skel->bss->address_high);
|
||||
if (!ASSERT_OK(err, "kallsyms_find_next"))
|
||||
goto cleanup;
|
||||
/* Just a guess for the end of this function, as module functions
|
||||
* in /proc/kallsyms could come in any order.
|
||||
*/
|
||||
skel->bss->address_high = skel->bss->address_low + 128;
|
||||
|
||||
err = get_branch_snapshot__attach(skel);
|
||||
if (!ASSERT_OK(err, "get_branch_snapshot__attach"))
|
||||
@@ -107,16 +114,6 @@ void serial_test_get_branch_snapshot(void)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (is_hypervisor()) {
|
||||
/* As of today, LBR in hypervisor cannot be stopped before
|
||||
* too many entries are flushed. Skip the hit/waste test
|
||||
* for now in hypervisor until we optimize the LBR in
|
||||
* hypervisor.
|
||||
*/
|
||||
test__skip();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ASSERT_GT(skel->bss->test1_hits, 6, "find_looptest_in_lbr");
|
||||
|
||||
/* Given we stop LBR in software, we will waste a few entries.
|
||||
|
||||
@@ -117,14 +117,14 @@ static int resolve_symbols(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_resolve_btfids(void)
|
||||
void test_resolve_btfids(void)
|
||||
{
|
||||
__u32 *test_list, *test_lists[] = { test_list_local, test_list_global };
|
||||
unsigned int i, j;
|
||||
int ret = 0;
|
||||
|
||||
if (resolve_symbols())
|
||||
return -1;
|
||||
return;
|
||||
|
||||
/* Check BTF_ID_LIST(test_list_local) and
|
||||
* BTF_ID_LIST_GLOBAL(test_list_global) IDs
|
||||
@@ -138,7 +138,7 @@ int test_resolve_btfids(void)
|
||||
test_symbols[i].name,
|
||||
test_list[i], test_symbols[i].id);
|
||||
if (ret)
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,9 +161,7 @@ int test_resolve_btfids(void)
|
||||
|
||||
if (i > 0) {
|
||||
if (!ASSERT_LE(test_set.ids[i - 1], test_set.ids[i], "sort_check"))
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ static void test_signal_pending_by_type(enum bpf_prog_type prog_type)
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
}
|
||||
|
||||
void test_signal_pending(enum bpf_prog_type prog_type)
|
||||
void test_signal_pending(void)
|
||||
{
|
||||
test_signal_pending_by_type(BPF_PROG_TYPE_SOCKET_FILTER);
|
||||
test_signal_pending_by_type(BPF_PROG_TYPE_FLOW_DISSECTOR);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#define EXP_NO_BUF_RET 29
|
||||
|
||||
void test_snprintf_positive(void)
|
||||
static void test_snprintf_positive(void)
|
||||
{
|
||||
char exp_addr_out[] = EXP_ADDR_OUT;
|
||||
char exp_sym_out[] = EXP_SYM_OUT;
|
||||
@@ -103,7 +103,7 @@ static int load_single_snprintf(char *fmt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void test_snprintf_negative(void)
|
||||
static void test_snprintf_negative(void)
|
||||
{
|
||||
ASSERT_OK(load_single_snprintf("valid %d"), "valid usage");
|
||||
|
||||
|
||||
@@ -176,6 +176,18 @@ static int netns_setup_namespaces(const char *verb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void netns_setup_namespaces_nofail(const char *verb)
|
||||
{
|
||||
const char * const *ns = namespaces;
|
||||
char cmd[128];
|
||||
|
||||
while (*ns) {
|
||||
snprintf(cmd, sizeof(cmd), "ip netns %s %s > /dev/null 2>&1", verb, *ns);
|
||||
system(cmd);
|
||||
ns++;
|
||||
}
|
||||
}
|
||||
|
||||
struct netns_setup_result {
|
||||
int ifindex_veth_src_fwd;
|
||||
int ifindex_veth_dst_fwd;
|
||||
@@ -762,6 +774,8 @@ fail:
|
||||
|
||||
static void *test_tc_redirect_run_tests(void *arg)
|
||||
{
|
||||
netns_setup_namespaces_nofail("delete");
|
||||
|
||||
RUN_TEST(tc_redirect_peer);
|
||||
RUN_TEST(tc_redirect_peer_l3);
|
||||
RUN_TEST(tc_redirect_neigh);
|
||||
@@ -769,7 +783,7 @@ static void *test_tc_redirect_run_tests(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void test_tc_redirect(void)
|
||||
void serial_test_tc_redirect(void)
|
||||
{
|
||||
pthread_t test_thread;
|
||||
int err;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <test_progs.h>
|
||||
#include <network_helpers.h>
|
||||
|
||||
void test_xdp_adjust_tail_shrink(void)
|
||||
static void test_xdp_adjust_tail_shrink(void)
|
||||
{
|
||||
const char *file = "./test_xdp_adjust_tail_shrink.o";
|
||||
__u32 duration, retval, size, expect_sz;
|
||||
@@ -30,7 +30,7 @@ void test_xdp_adjust_tail_shrink(void)
|
||||
bpf_object__close(obj);
|
||||
}
|
||||
|
||||
void test_xdp_adjust_tail_grow(void)
|
||||
static void test_xdp_adjust_tail_grow(void)
|
||||
{
|
||||
const char *file = "./test_xdp_adjust_tail_grow.o";
|
||||
struct bpf_object *obj;
|
||||
@@ -58,7 +58,7 @@ void test_xdp_adjust_tail_grow(void)
|
||||
bpf_object__close(obj);
|
||||
}
|
||||
|
||||
void test_xdp_adjust_tail_grow2(void)
|
||||
static void test_xdp_adjust_tail_grow2(void)
|
||||
{
|
||||
const char *file = "./test_xdp_adjust_tail_grow.o";
|
||||
char buf[4096]; /* avoid segfault: large buf to hold grow results */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define IFINDEX_LO 1
|
||||
|
||||
void test_xdp_with_devmap_helpers(void)
|
||||
static void test_xdp_with_devmap_helpers(void)
|
||||
{
|
||||
struct test_xdp_with_devmap_helpers *skel;
|
||||
struct bpf_prog_info info = {};
|
||||
@@ -60,7 +60,7 @@ out_close:
|
||||
test_xdp_with_devmap_helpers__destroy(skel);
|
||||
}
|
||||
|
||||
void test_neg_xdp_devmap_helpers(void)
|
||||
static void test_neg_xdp_devmap_helpers(void)
|
||||
{
|
||||
struct test_xdp_devmap_helpers *skel;
|
||||
|
||||
|
||||
@@ -24,18 +24,23 @@ struct key_t {
|
||||
int c;
|
||||
} __tag1 __tag2;
|
||||
|
||||
typedef struct {
|
||||
int a;
|
||||
int b;
|
||||
} value_t __tag1 __tag2;
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 3);
|
||||
__type(key, struct key_t);
|
||||
__type(value, __u64);
|
||||
__type(value, value_t);
|
||||
} hashmap1 SEC(".maps");
|
||||
|
||||
|
||||
static __noinline int foo(int x __tag1 __tag2) __tag1 __tag2
|
||||
{
|
||||
struct key_t key;
|
||||
__u64 val = 1;
|
||||
value_t val = {};
|
||||
|
||||
key.a = key.b = key.c = x;
|
||||
bpf_map_update_elem(&hashmap1, &key, &val, 0);
|
||||
|
||||
@@ -42,7 +42,16 @@ struct core_reloc_mods {
|
||||
core_reloc_mods_substruct_t h;
|
||||
};
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*(dst)), src)
|
||||
#else
|
||||
#define CORE_READ(dst, src) ({ \
|
||||
int __sz = sizeof(*(dst)) < sizeof(*(src)) ? sizeof(*(dst)) : \
|
||||
sizeof(*(src)); \
|
||||
bpf_core_read((char *)(dst) + sizeof(*(dst)) - __sz, __sz, \
|
||||
(const char *)(src) + sizeof(*(src)) - __sz); \
|
||||
})
|
||||
#endif
|
||||
|
||||
SEC("raw_tracepoint/sys_enter")
|
||||
int test_core_mods(void *ctx)
|
||||
|
||||
@@ -26,22 +26,22 @@ if [[ -z $(ip netns identify $$) ]]; then
|
||||
type flow_dissector
|
||||
|
||||
if ! unshare --net $bpftool prog attach pinned \
|
||||
/sys/fs/bpf/flow/flow_dissector flow_dissector; then
|
||||
/sys/fs/bpf/flow/_dissect flow_dissector; then
|
||||
echo "Unexpected unsuccessful attach in namespace" >&2
|
||||
err=1
|
||||
fi
|
||||
|
||||
$bpftool prog attach pinned /sys/fs/bpf/flow/flow_dissector \
|
||||
$bpftool prog attach pinned /sys/fs/bpf/flow/_dissect \
|
||||
flow_dissector
|
||||
|
||||
if unshare --net $bpftool prog attach pinned \
|
||||
/sys/fs/bpf/flow/flow_dissector flow_dissector; then
|
||||
/sys/fs/bpf/flow/_dissect flow_dissector; then
|
||||
echo "Unexpected successful attach in namespace" >&2
|
||||
err=1
|
||||
fi
|
||||
|
||||
if ! $bpftool prog detach pinned \
|
||||
/sys/fs/bpf/flow/flow_dissector flow_dissector; then
|
||||
/sys/fs/bpf/flow/_dissect flow_dissector; then
|
||||
echo "Failed to detach flow dissector" >&2
|
||||
err=1
|
||||
fi
|
||||
@@ -95,7 +95,7 @@ else
|
||||
fi
|
||||
|
||||
# Attach BPF program
|
||||
./flow_dissector_load -p bpf_flow.o -s flow_dissector
|
||||
./flow_dissector_load -p bpf_flow.o -s _dissect
|
||||
|
||||
# Setup
|
||||
tc qdisc add dev lo ingress
|
||||
|
||||
@@ -124,7 +124,7 @@ static struct sysctl_test tests[] = {
|
||||
.descr = "ctx:write sysctl:write read ok narrow",
|
||||
.insns = {
|
||||
/* u64 w = (u16)write & 1; */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1,
|
||||
offsetof(struct bpf_sysctl, write)),
|
||||
#else
|
||||
@@ -184,7 +184,7 @@ static struct sysctl_test tests[] = {
|
||||
.descr = "ctx:file_pos sysctl:read read ok narrow",
|
||||
.insns = {
|
||||
/* If (file_pos == X) */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
|
||||
offsetof(struct bpf_sysctl, file_pos)),
|
||||
#else
|
||||
|
||||
@@ -118,42 +118,6 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* find the address of the next symbol of the same type, this can be used
|
||||
* to determine the end of a function.
|
||||
*/
|
||||
int kallsyms_find_next(const char *sym, unsigned long long *addr)
|
||||
{
|
||||
char type, found_type, name[500];
|
||||
unsigned long long value;
|
||||
bool found = false;
|
||||
int err = 0;
|
||||
FILE *f;
|
||||
|
||||
f = fopen("/proc/kallsyms", "r");
|
||||
if (!f)
|
||||
return -EINVAL;
|
||||
|
||||
while (fscanf(f, "%llx %c %499s%*[^\n]\n", &value, &type, name) > 0) {
|
||||
/* Different types of symbols in kernel modules are mixed
|
||||
* in /proc/kallsyms. Only return the next matching type.
|
||||
* Use tolower() for type so that 'T' matches 't'.
|
||||
*/
|
||||
if (found && found_type == tolower(type)) {
|
||||
*addr = value;
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(name, sym) == 0) {
|
||||
found = true;
|
||||
found_type = tolower(type);
|
||||
}
|
||||
}
|
||||
err = -ENOENT;
|
||||
|
||||
out:
|
||||
fclose(f);
|
||||
return err;
|
||||
}
|
||||
|
||||
void read_trace_pipe(void)
|
||||
{
|
||||
int trace_fd;
|
||||
|
||||
@@ -16,11 +16,6 @@ long ksym_get_addr(const char *name);
|
||||
/* open kallsyms and find addresses on the fly, faster than load + search. */
|
||||
int kallsyms_find(const char *sym, unsigned long long *addr);
|
||||
|
||||
/* find the address of the next symbol, this can be used to determine the
|
||||
* end of a function
|
||||
*/
|
||||
int kallsyms_find_next(const char *sym, unsigned long long *addr);
|
||||
|
||||
void read_trace_pipe(void);
|
||||
|
||||
ssize_t get_uprobe_offset(const void *addr, ssize_t base);
|
||||
|
||||
@@ -502,7 +502,7 @@
|
||||
"check skb->hash byte load permitted",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, hash)),
|
||||
#else
|
||||
@@ -537,7 +537,7 @@
|
||||
"check skb->hash byte load permitted 3",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, hash) + 3),
|
||||
#else
|
||||
@@ -646,7 +646,7 @@
|
||||
"check skb->hash half load permitted",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, hash)),
|
||||
#else
|
||||
@@ -661,7 +661,7 @@
|
||||
"check skb->hash half load permitted 2",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, hash) + 2),
|
||||
#else
|
||||
@@ -676,7 +676,7 @@
|
||||
"check skb->hash half load not permitted, unaligned 1",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, hash) + 1),
|
||||
#else
|
||||
@@ -693,7 +693,7 @@
|
||||
"check skb->hash half load not permitted, unaligned 3",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, hash) + 3),
|
||||
#else
|
||||
@@ -951,7 +951,7 @@
|
||||
"check skb->data half load not permitted",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, data)),
|
||||
#else
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
"check skb->tc_classid half load not permitted for lwt prog",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, tc_classid)),
|
||||
#else
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"check bpf_perf_event_data->sample_period byte load permitted",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct bpf_perf_event_data, sample_period)),
|
||||
#else
|
||||
@@ -18,7 +18,7 @@
|
||||
"check bpf_perf_event_data->sample_period half load permitted",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct bpf_perf_event_data, sample_period)),
|
||||
#else
|
||||
@@ -34,7 +34,7 @@
|
||||
"check bpf_perf_event_data->sample_period word load permitted",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct bpf_perf_event_data, sample_period)),
|
||||
#else
|
||||
|
||||
@@ -224,10 +224,10 @@ EOF
|
||||
-nodefaults \
|
||||
-display none \
|
||||
-serial mon:stdio \
|
||||
-cpu kvm64 \
|
||||
-cpu host \
|
||||
-enable-kvm \
|
||||
-smp 4 \
|
||||
-m 2G \
|
||||
-smp 8 \
|
||||
-m 4G \
|
||||
-drive file="${rootfs_img}",format=raw,index=1,media=disk,if=virtio,cache=none \
|
||||
-kernel "${kernel_bzimage}" \
|
||||
-append "root=/dev/vda rw console=ttyS0,115200"
|
||||
|
||||
@@ -276,12 +276,12 @@ int seccomp(unsigned int op, unsigned int flags, void *args)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]) + sizeof(__u32))
|
||||
#else
|
||||
#error "wut? Unknown __BYTE_ORDER?!"
|
||||
#error "wut? Unknown __BYTE_ORDER__?!"
|
||||
#endif
|
||||
|
||||
#define SIBLING_EXIT_UNKILLED 0xbadbeef
|
||||
|
||||
Reference in New Issue
Block a user