mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 14:43:58 +08:00
selftests/bpf: Add field existence CO-RE relocs tests
Add a bunch of tests validating CO-RE is handling field existence relocation. Relaxed CO-RE relocation mode is activated for these new tests to prevent libbpf from rejecting BPF object for no-match relocation, even though test BPF program is not going to use that relocation, if field is missing. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20191015182849.3922287-6-andriin@fb.com
This commit is contained in:
parent
01340e3191
commit
c7566a6969
@ -174,6 +174,21 @@
|
||||
.fails = true, \
|
||||
}
|
||||
|
||||
#define EXISTENCE_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
|
||||
.a = 42, \
|
||||
}
|
||||
|
||||
#define EXISTENCE_CASE_COMMON(name) \
|
||||
.case_name = #name, \
|
||||
.bpf_obj_file = "test_core_reloc_existence.o", \
|
||||
.btf_src_file = "btf__core_reloc_" #name ".o", \
|
||||
.relaxed_core_relocs = true \
|
||||
|
||||
#define EXISTENCE_ERR_CASE(name) { \
|
||||
EXISTENCE_CASE_COMMON(name), \
|
||||
.fails = true, \
|
||||
}
|
||||
|
||||
struct core_reloc_test_case {
|
||||
const char *case_name;
|
||||
const char *bpf_obj_file;
|
||||
@ -183,6 +198,7 @@ struct core_reloc_test_case {
|
||||
const char *output;
|
||||
int output_len;
|
||||
bool fails;
|
||||
bool relaxed_core_relocs;
|
||||
};
|
||||
|
||||
static struct core_reloc_test_case test_cases[] = {
|
||||
@ -283,6 +299,59 @@ static struct core_reloc_test_case test_cases[] = {
|
||||
},
|
||||
.output_len = sizeof(struct core_reloc_misc_output),
|
||||
},
|
||||
|
||||
/* validate field existence checks */
|
||||
{
|
||||
EXISTENCE_CASE_COMMON(existence),
|
||||
.input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
|
||||
.a = 1,
|
||||
.b = 2,
|
||||
.c = 3,
|
||||
.arr = { 4 },
|
||||
.s = { .x = 5 },
|
||||
},
|
||||
.input_len = sizeof(struct core_reloc_existence),
|
||||
.output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
|
||||
.a_exists = 1,
|
||||
.b_exists = 1,
|
||||
.c_exists = 1,
|
||||
.arr_exists = 1,
|
||||
.s_exists = 1,
|
||||
.a_value = 1,
|
||||
.b_value = 2,
|
||||
.c_value = 3,
|
||||
.arr_value = 4,
|
||||
.s_value = 5,
|
||||
},
|
||||
.output_len = sizeof(struct core_reloc_existence_output),
|
||||
},
|
||||
{
|
||||
EXISTENCE_CASE_COMMON(existence___minimal),
|
||||
.input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
|
||||
.a = 42,
|
||||
},
|
||||
.input_len = sizeof(struct core_reloc_existence),
|
||||
.output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
|
||||
.a_exists = 1,
|
||||
.b_exists = 0,
|
||||
.c_exists = 0,
|
||||
.arr_exists = 0,
|
||||
.s_exists = 0,
|
||||
.a_value = 42,
|
||||
.b_value = 0xff000002u,
|
||||
.c_value = 0xff000003u,
|
||||
.arr_value = 0xff000004u,
|
||||
.s_value = 0xff000005u,
|
||||
},
|
||||
.output_len = sizeof(struct core_reloc_existence_output),
|
||||
},
|
||||
|
||||
EXISTENCE_ERR_CASE(existence__err_int_sz),
|
||||
EXISTENCE_ERR_CASE(existence__err_int_type),
|
||||
EXISTENCE_ERR_CASE(existence__err_int_kind),
|
||||
EXISTENCE_ERR_CASE(existence__err_arr_kind),
|
||||
EXISTENCE_ERR_CASE(existence__err_arr_value_type),
|
||||
EXISTENCE_ERR_CASE(existence__err_struct_type),
|
||||
};
|
||||
|
||||
struct data {
|
||||
@ -305,11 +374,14 @@ void test_core_reloc(void)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
|
||||
test_case = &test_cases[i];
|
||||
|
||||
if (!test__start_subtest(test_case->case_name))
|
||||
continue;
|
||||
|
||||
obj = bpf_object__open(test_case->bpf_obj_file);
|
||||
LIBBPF_OPTS(bpf_object_open_opts, opts,
|
||||
.relaxed_core_relocs = test_case->relaxed_core_relocs,
|
||||
);
|
||||
|
||||
obj = bpf_object__open_file(test_case->bpf_obj_file, &opts);
|
||||
if (CHECK(IS_ERR_OR_NULL(obj), "obj_open",
|
||||
"failed to open '%s': %ld\n",
|
||||
test_case->bpf_obj_file, PTR_ERR(obj)))
|
||||
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence x) {}
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence___err_wrong_arr_kind x) {}
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence___err_wrong_arr_value_type x) {}
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence___err_wrong_int_kind x) {}
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence___err_wrong_int_sz x) {}
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence___err_wrong_int_type x) {}
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence___err_wrong_struct_type x) {}
|
@ -0,0 +1,3 @@
|
||||
#include "core_reloc_types.h"
|
||||
|
||||
void f(struct core_reloc_existence___minimal x) {}
|
@ -674,3 +674,59 @@ struct core_reloc_misc_extensible {
|
||||
int c;
|
||||
int d;
|
||||
};
|
||||
|
||||
/*
|
||||
* EXISTENCE
|
||||
*/
|
||||
struct core_reloc_existence_output {
|
||||
int a_exists;
|
||||
int a_value;
|
||||
int b_exists;
|
||||
int b_value;
|
||||
int c_exists;
|
||||
int c_value;
|
||||
int arr_exists;
|
||||
int arr_value;
|
||||
int s_exists;
|
||||
int s_value;
|
||||
};
|
||||
|
||||
struct core_reloc_existence {
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
int c;
|
||||
int arr[1];
|
||||
struct {
|
||||
int x;
|
||||
} s;
|
||||
};
|
||||
|
||||
struct core_reloc_existence___minimal {
|
||||
int a;
|
||||
};
|
||||
|
||||
struct core_reloc_existence___err_wrong_int_sz {
|
||||
short a;
|
||||
};
|
||||
|
||||
struct core_reloc_existence___err_wrong_int_type {
|
||||
int b[1];
|
||||
};
|
||||
|
||||
struct core_reloc_existence___err_wrong_int_kind {
|
||||
struct{ int x; } c;
|
||||
};
|
||||
|
||||
struct core_reloc_existence___err_wrong_arr_kind {
|
||||
int arr;
|
||||
};
|
||||
|
||||
struct core_reloc_existence___err_wrong_arr_value_type {
|
||||
short arr[1];
|
||||
};
|
||||
|
||||
struct core_reloc_existence___err_wrong_struct_type {
|
||||
int s;
|
||||
};
|
||||
|
@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2019 Facebook
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <stdint.h>
|
||||
#include "bpf_helpers.h"
|
||||
#include "bpf_core_read.h"
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
static volatile struct data {
|
||||
char in[256];
|
||||
char out[256];
|
||||
} data;
|
||||
|
||||
struct core_reloc_existence_output {
|
||||
int a_exists;
|
||||
int a_value;
|
||||
int b_exists;
|
||||
int b_value;
|
||||
int c_exists;
|
||||
int c_value;
|
||||
int arr_exists;
|
||||
int arr_value;
|
||||
int s_exists;
|
||||
int s_value;
|
||||
};
|
||||
|
||||
struct core_reloc_existence {
|
||||
struct {
|
||||
int x;
|
||||
} s;
|
||||
int arr[1];
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
int c;
|
||||
};
|
||||
|
||||
SEC("raw_tracepoint/sys_enter")
|
||||
int test_core_existence(void *ctx)
|
||||
{
|
||||
struct core_reloc_existence *in = (void *)&data.in;
|
||||
struct core_reloc_existence_output *out = (void *)&data.out;
|
||||
|
||||
out->a_exists = bpf_core_field_exists(in->a);
|
||||
if (bpf_core_field_exists(in->a))
|
||||
out->a_value = BPF_CORE_READ(in, a);
|
||||
else
|
||||
out->a_value = 0xff000001u;
|
||||
|
||||
out->b_exists = bpf_core_field_exists(in->b);
|
||||
if (bpf_core_field_exists(in->b))
|
||||
out->b_value = BPF_CORE_READ(in, b);
|
||||
else
|
||||
out->b_value = 0xff000002u;
|
||||
|
||||
out->c_exists = bpf_core_field_exists(in->c);
|
||||
if (bpf_core_field_exists(in->c))
|
||||
out->c_value = BPF_CORE_READ(in, c);
|
||||
else
|
||||
out->c_value = 0xff000003u;
|
||||
|
||||
out->arr_exists = bpf_core_field_exists(in->arr);
|
||||
if (bpf_core_field_exists(in->arr))
|
||||
out->arr_value = BPF_CORE_READ(in, arr[0]);
|
||||
else
|
||||
out->arr_value = 0xff000004u;
|
||||
|
||||
out->s_exists = bpf_core_field_exists(in->s);
|
||||
if (bpf_core_field_exists(in->s))
|
||||
out->s_value = BPF_CORE_READ(in, s.x);
|
||||
else
|
||||
out->s_value = 0xff000005u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user