selftests/bpf: Test TYPE_EXISTS and TYPE_SIZE CO-RE relocations
Add selftests for TYPE_EXISTS and TYPE_SIZE relocations, testing correctness of relocations and handling of type compatiblity/incompatibility. If __builtin_preserve_type_info() is not supported by compiler, skip tests. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20200819194519.3375898-3-andriin@fb.com
This commit is contained in:
parent
3fc32f40c4
commit
124a892d1c
@ -177,14 +177,13 @@
|
|||||||
.fails = true, \
|
.fails = true, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXISTENCE_CASE_COMMON(name) \
|
#define FIELD_EXISTS_CASE_COMMON(name) \
|
||||||
.case_name = #name, \
|
.case_name = #name, \
|
||||||
.bpf_obj_file = "test_core_reloc_existence.o", \
|
.bpf_obj_file = "test_core_reloc_existence.o", \
|
||||||
.btf_src_file = "btf__core_reloc_" #name ".o", \
|
.btf_src_file = "btf__core_reloc_" #name ".o" \
|
||||||
.relaxed_core_relocs = true
|
|
||||||
|
|
||||||
#define EXISTENCE_ERR_CASE(name) { \
|
#define FIELD_EXISTS_ERR_CASE(name) { \
|
||||||
EXISTENCE_CASE_COMMON(name), \
|
FIELD_EXISTS_CASE_COMMON(name), \
|
||||||
.fails = true, \
|
.fails = true, \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,6 +252,23 @@
|
|||||||
.fails = true, \
|
.fails = true, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TYPE_BASED_CASE_COMMON(name) \
|
||||||
|
.case_name = #name, \
|
||||||
|
.bpf_obj_file = "test_core_reloc_type_based.o", \
|
||||||
|
.btf_src_file = "btf__core_reloc_" #name ".o" \
|
||||||
|
|
||||||
|
#define TYPE_BASED_CASE(name, ...) { \
|
||||||
|
TYPE_BASED_CASE_COMMON(name), \
|
||||||
|
.output = STRUCT_TO_CHAR_PTR(core_reloc_type_based_output) \
|
||||||
|
__VA_ARGS__, \
|
||||||
|
.output_len = sizeof(struct core_reloc_type_based_output), \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TYPE_BASED_ERR_CASE(name) { \
|
||||||
|
TYPE_BASED_CASE_COMMON(name), \
|
||||||
|
.fails = true, \
|
||||||
|
}
|
||||||
|
|
||||||
struct core_reloc_test_case {
|
struct core_reloc_test_case {
|
||||||
const char *case_name;
|
const char *case_name;
|
||||||
const char *bpf_obj_file;
|
const char *bpf_obj_file;
|
||||||
@ -364,7 +380,7 @@ static struct core_reloc_test_case test_cases[] = {
|
|||||||
|
|
||||||
/* validate field existence checks */
|
/* validate field existence checks */
|
||||||
{
|
{
|
||||||
EXISTENCE_CASE_COMMON(existence),
|
FIELD_EXISTS_CASE_COMMON(existence),
|
||||||
.input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
|
.input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
|
||||||
.a = 1,
|
.a = 1,
|
||||||
.b = 2,
|
.b = 2,
|
||||||
@ -388,7 +404,7 @@ static struct core_reloc_test_case test_cases[] = {
|
|||||||
.output_len = sizeof(struct core_reloc_existence_output),
|
.output_len = sizeof(struct core_reloc_existence_output),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
EXISTENCE_CASE_COMMON(existence___minimal),
|
FIELD_EXISTS_CASE_COMMON(existence___minimal),
|
||||||
.input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
|
.input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
|
||||||
.a = 42,
|
.a = 42,
|
||||||
},
|
},
|
||||||
@ -408,12 +424,12 @@ static struct core_reloc_test_case test_cases[] = {
|
|||||||
.output_len = sizeof(struct core_reloc_existence_output),
|
.output_len = sizeof(struct core_reloc_existence_output),
|
||||||
},
|
},
|
||||||
|
|
||||||
EXISTENCE_ERR_CASE(existence__err_int_sz),
|
FIELD_EXISTS_ERR_CASE(existence__err_int_sz),
|
||||||
EXISTENCE_ERR_CASE(existence__err_int_type),
|
FIELD_EXISTS_ERR_CASE(existence__err_int_type),
|
||||||
EXISTENCE_ERR_CASE(existence__err_int_kind),
|
FIELD_EXISTS_ERR_CASE(existence__err_int_kind),
|
||||||
EXISTENCE_ERR_CASE(existence__err_arr_kind),
|
FIELD_EXISTS_ERR_CASE(existence__err_arr_kind),
|
||||||
EXISTENCE_ERR_CASE(existence__err_arr_value_type),
|
FIELD_EXISTS_ERR_CASE(existence__err_arr_value_type),
|
||||||
EXISTENCE_ERR_CASE(existence__err_struct_type),
|
FIELD_EXISTS_ERR_CASE(existence__err_struct_type),
|
||||||
|
|
||||||
/* bitfield relocation checks */
|
/* bitfield relocation checks */
|
||||||
BITFIELDS_CASE(bitfields, {
|
BITFIELDS_CASE(bitfields, {
|
||||||
@ -453,11 +469,73 @@ static struct core_reloc_test_case test_cases[] = {
|
|||||||
SIZE_CASE(size),
|
SIZE_CASE(size),
|
||||||
SIZE_CASE(size___diff_sz),
|
SIZE_CASE(size___diff_sz),
|
||||||
SIZE_ERR_CASE(size___err_ambiguous),
|
SIZE_ERR_CASE(size___err_ambiguous),
|
||||||
|
|
||||||
|
/* validate type existence and size relocations */
|
||||||
|
TYPE_BASED_CASE(type_based, {
|
||||||
|
.struct_exists = 1,
|
||||||
|
.union_exists = 1,
|
||||||
|
.enum_exists = 1,
|
||||||
|
.typedef_named_struct_exists = 1,
|
||||||
|
.typedef_anon_struct_exists = 1,
|
||||||
|
.typedef_struct_ptr_exists = 1,
|
||||||
|
.typedef_int_exists = 1,
|
||||||
|
.typedef_enum_exists = 1,
|
||||||
|
.typedef_void_ptr_exists = 1,
|
||||||
|
.typedef_func_proto_exists = 1,
|
||||||
|
.typedef_arr_exists = 1,
|
||||||
|
.struct_sz = sizeof(struct a_struct),
|
||||||
|
.union_sz = sizeof(union a_union),
|
||||||
|
.enum_sz = sizeof(enum an_enum),
|
||||||
|
.typedef_named_struct_sz = sizeof(named_struct_typedef),
|
||||||
|
.typedef_anon_struct_sz = sizeof(anon_struct_typedef),
|
||||||
|
.typedef_struct_ptr_sz = sizeof(struct_ptr_typedef),
|
||||||
|
.typedef_int_sz = sizeof(int_typedef),
|
||||||
|
.typedef_enum_sz = sizeof(enum_typedef),
|
||||||
|
.typedef_void_ptr_sz = sizeof(void_ptr_typedef),
|
||||||
|
.typedef_func_proto_sz = sizeof(func_proto_typedef),
|
||||||
|
.typedef_arr_sz = sizeof(arr_typedef),
|
||||||
|
}),
|
||||||
|
TYPE_BASED_CASE(type_based___all_missing, {
|
||||||
|
/* all zeros */
|
||||||
|
}),
|
||||||
|
TYPE_BASED_CASE(type_based___diff_sz, {
|
||||||
|
.struct_exists = 1,
|
||||||
|
.union_exists = 1,
|
||||||
|
.enum_exists = 1,
|
||||||
|
.typedef_named_struct_exists = 1,
|
||||||
|
.typedef_anon_struct_exists = 1,
|
||||||
|
.typedef_struct_ptr_exists = 1,
|
||||||
|
.typedef_int_exists = 1,
|
||||||
|
.typedef_enum_exists = 1,
|
||||||
|
.typedef_void_ptr_exists = 1,
|
||||||
|
.typedef_func_proto_exists = 1,
|
||||||
|
.typedef_arr_exists = 1,
|
||||||
|
.struct_sz = sizeof(struct a_struct___diff_sz),
|
||||||
|
.union_sz = sizeof(union a_union___diff_sz),
|
||||||
|
.enum_sz = sizeof(enum an_enum___diff_sz),
|
||||||
|
.typedef_named_struct_sz = sizeof(named_struct_typedef___diff_sz),
|
||||||
|
.typedef_anon_struct_sz = sizeof(anon_struct_typedef___diff_sz),
|
||||||
|
.typedef_struct_ptr_sz = sizeof(struct_ptr_typedef___diff_sz),
|
||||||
|
.typedef_int_sz = sizeof(int_typedef___diff_sz),
|
||||||
|
.typedef_enum_sz = sizeof(enum_typedef___diff_sz),
|
||||||
|
.typedef_void_ptr_sz = sizeof(void_ptr_typedef___diff_sz),
|
||||||
|
.typedef_func_proto_sz = sizeof(func_proto_typedef___diff_sz),
|
||||||
|
.typedef_arr_sz = sizeof(arr_typedef___diff_sz),
|
||||||
|
}),
|
||||||
|
TYPE_BASED_CASE(type_based___incompat, {
|
||||||
|
.enum_exists = 1,
|
||||||
|
.enum_sz = sizeof(enum an_enum),
|
||||||
|
}),
|
||||||
|
TYPE_BASED_CASE(type_based___fn_wrong_args, {
|
||||||
|
.struct_exists = 1,
|
||||||
|
.struct_sz = sizeof(struct a_struct),
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct data {
|
struct data {
|
||||||
char in[256];
|
char in[256];
|
||||||
char out[256];
|
char out[256];
|
||||||
|
bool skip;
|
||||||
uint64_t my_pid_tgid;
|
uint64_t my_pid_tgid;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -516,15 +594,10 @@ void test_core_reloc(void)
|
|||||||
load_attr.log_level = 0;
|
load_attr.log_level = 0;
|
||||||
load_attr.target_btf_path = test_case->btf_src_file;
|
load_attr.target_btf_path = test_case->btf_src_file;
|
||||||
err = bpf_object__load_xattr(&load_attr);
|
err = bpf_object__load_xattr(&load_attr);
|
||||||
if (test_case->fails) {
|
if (err) {
|
||||||
CHECK(!err, "obj_load_fail",
|
if (!test_case->fails)
|
||||||
"should fail to load prog '%s'\n", probe_name);
|
CHECK(false, "obj_load", "failed to load prog '%s': %d\n", probe_name, err);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
|
||||||
if (CHECK(err, "obj_load",
|
|
||||||
"failed to load prog '%s': %d\n",
|
|
||||||
probe_name, err))
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data_map = bpf_object__find_map_by_name(obj, "test_cor.bss");
|
data_map = bpf_object__find_map_by_name(obj, "test_cor.bss");
|
||||||
@ -552,6 +625,16 @@ void test_core_reloc(void)
|
|||||||
/* trigger test run */
|
/* trigger test run */
|
||||||
usleep(1);
|
usleep(1);
|
||||||
|
|
||||||
|
if (data->skip) {
|
||||||
|
test__skip();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_case->fails) {
|
||||||
|
CHECK(false, "obj_load_fail", "should fail to load prog '%s'\n", probe_name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
equal = memcmp(data->out, test_case->output,
|
equal = memcmp(data->out, test_case->output,
|
||||||
test_case->output_len) == 0;
|
test_case->output_len) == 0;
|
||||||
if (CHECK(!equal, "check_result",
|
if (CHECK(!equal, "check_result",
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
#include "core_reloc_types.h"
|
||||||
|
|
||||||
|
void f(struct core_reloc_type_based x) {}
|
@ -0,0 +1,3 @@
|
|||||||
|
#include "core_reloc_types.h"
|
||||||
|
|
||||||
|
void f(struct core_reloc_type_based___all_missing x) {}
|
@ -0,0 +1,3 @@
|
|||||||
|
#include "core_reloc_types.h"
|
||||||
|
|
||||||
|
void f(struct core_reloc_type_based___diff_sz x) {}
|
@ -0,0 +1,3 @@
|
|||||||
|
#include "core_reloc_types.h"
|
||||||
|
|
||||||
|
void f(struct core_reloc_type_based___fn_wrong_args x) {}
|
@ -0,0 +1,3 @@
|
|||||||
|
#include "core_reloc_types.h"
|
||||||
|
|
||||||
|
void f(struct core_reloc_type_based___incompat x) {}
|
@ -652,7 +652,7 @@ struct core_reloc_misc_extensible {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EXISTENCE
|
* FIELD EXISTENCE
|
||||||
*/
|
*/
|
||||||
struct core_reloc_existence_output {
|
struct core_reloc_existence_output {
|
||||||
int a_exists;
|
int a_exists;
|
||||||
@ -834,3 +834,203 @@ struct core_reloc_size___err_ambiguous2 {
|
|||||||
void *ptr_field;
|
void *ptr_field;
|
||||||
enum { VALUE___2 = 123 } enum_field;
|
enum { VALUE___2 = 123 } enum_field;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TYPE EXISTENCE & SIZE
|
||||||
|
*/
|
||||||
|
struct core_reloc_type_based_output {
|
||||||
|
bool struct_exists;
|
||||||
|
bool union_exists;
|
||||||
|
bool enum_exists;
|
||||||
|
bool typedef_named_struct_exists;
|
||||||
|
bool typedef_anon_struct_exists;
|
||||||
|
bool typedef_struct_ptr_exists;
|
||||||
|
bool typedef_int_exists;
|
||||||
|
bool typedef_enum_exists;
|
||||||
|
bool typedef_void_ptr_exists;
|
||||||
|
bool typedef_func_proto_exists;
|
||||||
|
bool typedef_arr_exists;
|
||||||
|
|
||||||
|
int struct_sz;
|
||||||
|
int union_sz;
|
||||||
|
int enum_sz;
|
||||||
|
int typedef_named_struct_sz;
|
||||||
|
int typedef_anon_struct_sz;
|
||||||
|
int typedef_struct_ptr_sz;
|
||||||
|
int typedef_int_sz;
|
||||||
|
int typedef_enum_sz;
|
||||||
|
int typedef_void_ptr_sz;
|
||||||
|
int typedef_func_proto_sz;
|
||||||
|
int typedef_arr_sz;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct a_struct {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
union a_union {
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct a_struct named_struct_typedef;
|
||||||
|
|
||||||
|
typedef struct { int x, y, z; } anon_struct_typedef;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int a, b, c;
|
||||||
|
} *struct_ptr_typedef;
|
||||||
|
|
||||||
|
enum an_enum {
|
||||||
|
AN_ENUM_VAL1 = 1,
|
||||||
|
AN_ENUM_VAL2 = 2,
|
||||||
|
AN_ENUM_VAL3 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int int_typedef;
|
||||||
|
|
||||||
|
typedef enum { TYPEDEF_ENUM_VAL1, TYPEDEF_ENUM_VAL2 } enum_typedef;
|
||||||
|
|
||||||
|
typedef void *void_ptr_typedef;
|
||||||
|
|
||||||
|
typedef int (*func_proto_typedef)(long);
|
||||||
|
|
||||||
|
typedef char arr_typedef[20];
|
||||||
|
|
||||||
|
struct core_reloc_type_based {
|
||||||
|
struct a_struct f1;
|
||||||
|
union a_union f2;
|
||||||
|
enum an_enum f3;
|
||||||
|
named_struct_typedef f4;
|
||||||
|
anon_struct_typedef f5;
|
||||||
|
struct_ptr_typedef f6;
|
||||||
|
int_typedef f7;
|
||||||
|
enum_typedef f8;
|
||||||
|
void_ptr_typedef f9;
|
||||||
|
func_proto_typedef f10;
|
||||||
|
arr_typedef f11;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* no types in target */
|
||||||
|
struct core_reloc_type_based___all_missing {
|
||||||
|
};
|
||||||
|
|
||||||
|
/* different type sizes, extra modifiers, anon vs named enums, etc */
|
||||||
|
struct a_struct___diff_sz {
|
||||||
|
long x;
|
||||||
|
int y;
|
||||||
|
char z;
|
||||||
|
};
|
||||||
|
|
||||||
|
union a_union___diff_sz {
|
||||||
|
char yy;
|
||||||
|
char zz;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct a_struct___diff_sz named_struct_typedef___diff_sz;
|
||||||
|
|
||||||
|
typedef struct { long xx, yy, zzz; } anon_struct_typedef___diff_sz;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char aa[1], bb[2], cc[3];
|
||||||
|
} *struct_ptr_typedef___diff_sz;
|
||||||
|
|
||||||
|
enum an_enum___diff_sz {
|
||||||
|
AN_ENUM_VAL1___diff_sz = 0x123412341234,
|
||||||
|
AN_ENUM_VAL2___diff_sz = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned long int_typedef___diff_sz;
|
||||||
|
|
||||||
|
typedef enum an_enum___diff_sz enum_typedef___diff_sz;
|
||||||
|
|
||||||
|
typedef const void * const void_ptr_typedef___diff_sz;
|
||||||
|
|
||||||
|
typedef int_typedef___diff_sz (*func_proto_typedef___diff_sz)(char);
|
||||||
|
|
||||||
|
typedef int arr_typedef___diff_sz[2];
|
||||||
|
|
||||||
|
struct core_reloc_type_based___diff_sz {
|
||||||
|
struct a_struct___diff_sz f1;
|
||||||
|
union a_union___diff_sz f2;
|
||||||
|
enum an_enum___diff_sz f3;
|
||||||
|
named_struct_typedef___diff_sz f4;
|
||||||
|
anon_struct_typedef___diff_sz f5;
|
||||||
|
struct_ptr_typedef___diff_sz f6;
|
||||||
|
int_typedef___diff_sz f7;
|
||||||
|
enum_typedef___diff_sz f8;
|
||||||
|
void_ptr_typedef___diff_sz f9;
|
||||||
|
func_proto_typedef___diff_sz f10;
|
||||||
|
arr_typedef___diff_sz f11;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* incompatibilities between target and local types */
|
||||||
|
union a_struct___incompat { /* union instead of struct */
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct a_union___incompat { /* struct instead of union */
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* typedef to union, not to struct */
|
||||||
|
typedef union a_struct___incompat named_struct_typedef___incompat;
|
||||||
|
|
||||||
|
/* typedef to void pointer, instead of struct */
|
||||||
|
typedef void *anon_struct_typedef___incompat;
|
||||||
|
|
||||||
|
/* extra pointer indirection */
|
||||||
|
typedef struct {
|
||||||
|
int a, b, c;
|
||||||
|
} **struct_ptr_typedef___incompat;
|
||||||
|
|
||||||
|
/* typedef of a struct with int, instead of int */
|
||||||
|
typedef struct { int x; } int_typedef___incompat;
|
||||||
|
|
||||||
|
/* typedef to func_proto, instead of enum */
|
||||||
|
typedef int (*enum_typedef___incompat)(void);
|
||||||
|
|
||||||
|
/* pointer to char instead of void */
|
||||||
|
typedef char *void_ptr_typedef___incompat;
|
||||||
|
|
||||||
|
/* void return type instead of int */
|
||||||
|
typedef void (*func_proto_typedef___incompat)(long);
|
||||||
|
|
||||||
|
/* multi-dimensional array instead of a single-dimensional */
|
||||||
|
typedef int arr_typedef___incompat[20][2];
|
||||||
|
|
||||||
|
struct core_reloc_type_based___incompat {
|
||||||
|
union a_struct___incompat f1;
|
||||||
|
struct a_union___incompat f2;
|
||||||
|
/* the only valid one is enum, to check that something still succeeds */
|
||||||
|
enum an_enum f3;
|
||||||
|
named_struct_typedef___incompat f4;
|
||||||
|
anon_struct_typedef___incompat f5;
|
||||||
|
struct_ptr_typedef___incompat f6;
|
||||||
|
int_typedef___incompat f7;
|
||||||
|
enum_typedef___incompat f8;
|
||||||
|
void_ptr_typedef___incompat f9;
|
||||||
|
func_proto_typedef___incompat f10;
|
||||||
|
arr_typedef___incompat f11;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* func_proto with incompatible signature */
|
||||||
|
typedef void (*func_proto_typedef___fn_wrong_ret1)(long);
|
||||||
|
typedef int * (*func_proto_typedef___fn_wrong_ret2)(long);
|
||||||
|
typedef struct { int x; } int_struct_typedef;
|
||||||
|
typedef int_struct_typedef (*func_proto_typedef___fn_wrong_ret3)(long);
|
||||||
|
typedef int (*func_proto_typedef___fn_wrong_arg)(void *);
|
||||||
|
typedef int (*func_proto_typedef___fn_wrong_arg_cnt1)(long, long);
|
||||||
|
typedef int (*func_proto_typedef___fn_wrong_arg_cnt2)(void);
|
||||||
|
|
||||||
|
struct core_reloc_type_based___fn_wrong_args {
|
||||||
|
/* one valid type to make sure relos still work */
|
||||||
|
struct a_struct f1;
|
||||||
|
func_proto_typedef___fn_wrong_ret1 f2;
|
||||||
|
func_proto_typedef___fn_wrong_ret2 f3;
|
||||||
|
func_proto_typedef___fn_wrong_ret3 f4;
|
||||||
|
func_proto_typedef___fn_wrong_arg f5;
|
||||||
|
func_proto_typedef___fn_wrong_arg_cnt1 f6;
|
||||||
|
func_proto_typedef___fn_wrong_arg_cnt2 f7;
|
||||||
|
};
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <linux/bpf.h>
|
#include <linux/bpf.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <bpf/bpf_helpers.h>
|
#include <bpf/bpf_helpers.h>
|
||||||
#include <bpf/bpf_core_read.h>
|
#include <bpf/bpf_core_read.h>
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ char _license[] SEC("license") = "GPL";
|
|||||||
struct {
|
struct {
|
||||||
char in[256];
|
char in[256];
|
||||||
char out[256];
|
char out[256];
|
||||||
|
bool skip;
|
||||||
uint64_t my_pid_tgid;
|
uint64_t my_pid_tgid;
|
||||||
} data = {};
|
} data = {};
|
||||||
|
|
||||||
|
124
tools/testing/selftests/bpf/progs/test_core_reloc_type_based.c
Normal file
124
tools/testing/selftests/bpf/progs/test_core_reloc_type_based.c
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (c) 2020 Facebook
|
||||||
|
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <bpf/bpf_helpers.h>
|
||||||
|
#include <bpf/bpf_core_read.h>
|
||||||
|
|
||||||
|
char _license[] SEC("license") = "GPL";
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char in[256];
|
||||||
|
char out[256];
|
||||||
|
bool skip;
|
||||||
|
} data = {};
|
||||||
|
|
||||||
|
struct a_struct {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
union a_union {
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct a_struct named_struct_typedef;
|
||||||
|
|
||||||
|
typedef struct { int x, y, z; } anon_struct_typedef;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int a, b, c;
|
||||||
|
} *struct_ptr_typedef;
|
||||||
|
|
||||||
|
enum an_enum {
|
||||||
|
AN_ENUM_VAL1 = 1,
|
||||||
|
AN_ENUM_VAL2 = 2,
|
||||||
|
AN_ENUM_VAL3 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int int_typedef;
|
||||||
|
|
||||||
|
typedef enum { TYPEDEF_ENUM_VAL1, TYPEDEF_ENUM_VAL2 } enum_typedef;
|
||||||
|
|
||||||
|
typedef void *void_ptr_typedef;
|
||||||
|
|
||||||
|
typedef int (*func_proto_typedef)(long);
|
||||||
|
|
||||||
|
typedef char arr_typedef[20];
|
||||||
|
|
||||||
|
struct core_reloc_type_based {
|
||||||
|
struct a_struct f1;
|
||||||
|
union a_union f2;
|
||||||
|
enum an_enum f3;
|
||||||
|
named_struct_typedef f4;
|
||||||
|
anon_struct_typedef f5;
|
||||||
|
struct_ptr_typedef f6;
|
||||||
|
int_typedef f7;
|
||||||
|
enum_typedef f8;
|
||||||
|
void_ptr_typedef f9;
|
||||||
|
func_proto_typedef f10;
|
||||||
|
arr_typedef f11;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct core_reloc_type_based_output {
|
||||||
|
bool struct_exists;
|
||||||
|
bool union_exists;
|
||||||
|
bool enum_exists;
|
||||||
|
bool typedef_named_struct_exists;
|
||||||
|
bool typedef_anon_struct_exists;
|
||||||
|
bool typedef_struct_ptr_exists;
|
||||||
|
bool typedef_int_exists;
|
||||||
|
bool typedef_enum_exists;
|
||||||
|
bool typedef_void_ptr_exists;
|
||||||
|
bool typedef_func_proto_exists;
|
||||||
|
bool typedef_arr_exists;
|
||||||
|
|
||||||
|
int struct_sz;
|
||||||
|
int union_sz;
|
||||||
|
int enum_sz;
|
||||||
|
int typedef_named_struct_sz;
|
||||||
|
int typedef_anon_struct_sz;
|
||||||
|
int typedef_struct_ptr_sz;
|
||||||
|
int typedef_int_sz;
|
||||||
|
int typedef_enum_sz;
|
||||||
|
int typedef_void_ptr_sz;
|
||||||
|
int typedef_func_proto_sz;
|
||||||
|
int typedef_arr_sz;
|
||||||
|
};
|
||||||
|
|
||||||
|
SEC("raw_tracepoint/sys_enter")
|
||||||
|
int test_core_type_based(void *ctx)
|
||||||
|
{
|
||||||
|
#if __has_builtin(__builtin_preserve_type_info)
|
||||||
|
struct core_reloc_type_based_output *out = (void *)&data.out;
|
||||||
|
|
||||||
|
out->struct_exists = bpf_core_type_exists(struct a_struct);
|
||||||
|
out->union_exists = bpf_core_type_exists(union a_union);
|
||||||
|
out->enum_exists = bpf_core_type_exists(enum an_enum);
|
||||||
|
out->typedef_named_struct_exists = bpf_core_type_exists(named_struct_typedef);
|
||||||
|
out->typedef_anon_struct_exists = bpf_core_type_exists(anon_struct_typedef);
|
||||||
|
out->typedef_struct_ptr_exists = bpf_core_type_exists(struct_ptr_typedef);
|
||||||
|
out->typedef_int_exists = bpf_core_type_exists(int_typedef);
|
||||||
|
out->typedef_enum_exists = bpf_core_type_exists(enum_typedef);
|
||||||
|
out->typedef_void_ptr_exists = bpf_core_type_exists(void_ptr_typedef);
|
||||||
|
out->typedef_func_proto_exists = bpf_core_type_exists(func_proto_typedef);
|
||||||
|
out->typedef_arr_exists = bpf_core_type_exists(arr_typedef);
|
||||||
|
|
||||||
|
out->struct_sz = bpf_core_type_size(struct a_struct);
|
||||||
|
out->union_sz = bpf_core_type_size(union a_union);
|
||||||
|
out->enum_sz = bpf_core_type_size(enum an_enum);
|
||||||
|
out->typedef_named_struct_sz = bpf_core_type_size(named_struct_typedef);
|
||||||
|
out->typedef_anon_struct_sz = bpf_core_type_size(anon_struct_typedef);
|
||||||
|
out->typedef_struct_ptr_sz = bpf_core_type_size(struct_ptr_typedef);
|
||||||
|
out->typedef_int_sz = bpf_core_type_size(int_typedef);
|
||||||
|
out->typedef_enum_sz = bpf_core_type_size(enum_typedef);
|
||||||
|
out->typedef_void_ptr_sz = bpf_core_type_size(void_ptr_typedef);
|
||||||
|
out->typedef_func_proto_sz = bpf_core_type_size(func_proto_typedef);
|
||||||
|
out->typedef_arr_sz = bpf_core_type_size(arr_typedef);
|
||||||
|
#else
|
||||||
|
data.skip = true;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user