whatcanGOwrong
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
#include "../../testdata/common.h"
|
||||
#include "bpf_core_read.h"
|
||||
|
||||
enum e {
|
||||
// clang-12 doesn't allow enum relocations with zero value.
|
||||
// See https://reviews.llvm.org/D97659
|
||||
ONE = 1,
|
||||
TWO,
|
||||
};
|
||||
|
||||
typedef enum e e_t;
|
||||
|
||||
struct s {
|
||||
int _1;
|
||||
char _2;
|
||||
unsigned int _3;
|
||||
};
|
||||
|
||||
typedef struct s s_t;
|
||||
|
||||
union u {
|
||||
int *_1;
|
||||
char *_2;
|
||||
unsigned int *_3;
|
||||
};
|
||||
|
||||
typedef union u u_t;
|
||||
|
||||
#define local_id_zero(expr) \
|
||||
({ \
|
||||
if (bpf_core_type_id_local(expr) != 0) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define local_id_not_zero(expr) \
|
||||
({ \
|
||||
if (bpf_core_type_id_local(expr) == 0) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define target_and_local_id_match(expr) \
|
||||
({ \
|
||||
if (bpf_core_type_id_kernel(expr) != bpf_core_type_id_local(expr)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
__section("socket_filter/type_ids") int type_ids() {
|
||||
local_id_not_zero(int);
|
||||
local_id_not_zero(struct { int frob; });
|
||||
local_id_not_zero(enum {FRAP});
|
||||
local_id_not_zero(union { char bar; });
|
||||
|
||||
local_id_not_zero(struct s);
|
||||
local_id_not_zero(s_t);
|
||||
local_id_not_zero(const s_t);
|
||||
local_id_not_zero(volatile s_t);
|
||||
local_id_not_zero(enum e);
|
||||
local_id_not_zero(e_t);
|
||||
local_id_not_zero(const e_t);
|
||||
local_id_not_zero(volatile e_t);
|
||||
local_id_not_zero(union u);
|
||||
local_id_not_zero(u_t);
|
||||
local_id_not_zero(const u_t);
|
||||
local_id_not_zero(volatile u_t);
|
||||
|
||||
// Qualifiers on types crash clang.
|
||||
target_and_local_id_match(struct s);
|
||||
target_and_local_id_match(s_t);
|
||||
// target_and_local_id_match(const s_t);
|
||||
// target_and_local_id_match(volatile s_t);
|
||||
target_and_local_id_match(enum e);
|
||||
target_and_local_id_match(e_t);
|
||||
// target_and_local_id_match(const e_t);
|
||||
// target_and_local_id_match(volatile e_t);
|
||||
target_and_local_id_match(union u);
|
||||
target_and_local_id_match(u_t);
|
||||
// target_and_local_id_match(const u_t);
|
||||
// target_and_local_id_match(volatile u_t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define type_exists(expr) \
|
||||
({ \
|
||||
if (!bpf_core_type_exists(expr)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define type_size_matches(expr) \
|
||||
({ \
|
||||
if (bpf_core_type_size(expr) != sizeof(expr)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
__section("socket_filter/types") int types() {
|
||||
type_exists(struct s);
|
||||
type_exists(s_t);
|
||||
type_exists(const s_t);
|
||||
type_exists(volatile s_t);
|
||||
type_exists(enum e);
|
||||
type_exists(e_t);
|
||||
type_exists(const e_t);
|
||||
type_exists(volatile e_t);
|
||||
type_exists(union u);
|
||||
type_exists(u_t);
|
||||
type_exists(const u_t);
|
||||
type_exists(volatile u_t);
|
||||
// TODO: Check non-existence.
|
||||
|
||||
type_size_matches(struct s);
|
||||
type_size_matches(s_t);
|
||||
type_size_matches(const s_t);
|
||||
type_size_matches(volatile s_t);
|
||||
type_size_matches(enum e);
|
||||
type_size_matches(e_t);
|
||||
type_size_matches(const e_t);
|
||||
type_size_matches(volatile e_t);
|
||||
type_size_matches(union u);
|
||||
type_size_matches(u_t);
|
||||
type_size_matches(const u_t);
|
||||
type_size_matches(volatile u_t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define enum_value_exists(t, v) \
|
||||
({ \
|
||||
if (!bpf_core_enum_value_exists(t, v)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define enum_value_matches(t, v) \
|
||||
({ \
|
||||
if (v != bpf_core_enum_value(t, v)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
__section("socket_filter/enums") int enums() {
|
||||
enum_value_exists(enum e, ONE);
|
||||
enum_value_exists(volatile enum e, ONE);
|
||||
enum_value_exists(const enum e, ONE);
|
||||
enum_value_exists(e_t, TWO);
|
||||
// TODO: Check non-existence.
|
||||
|
||||
enum_value_matches(enum e, TWO);
|
||||
enum_value_matches(e_t, ONE);
|
||||
enum_value_matches(volatile e_t, ONE);
|
||||
enum_value_matches(const e_t, ONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define field_exists(f) \
|
||||
({ \
|
||||
if (!bpf_core_field_exists(f)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define field_size_matches(f) \
|
||||
({ \
|
||||
if (sizeof(f) != bpf_core_field_size(f)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define field_offset_matches(t, f) \
|
||||
({ \
|
||||
if (__builtin_offsetof(t, f) != __builtin_preserve_field_info(((typeof(t) *)0)->f, BPF_FIELD_BYTE_OFFSET)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define field_is_signed(f) \
|
||||
({ \
|
||||
if (!__builtin_preserve_field_info(f, BPF_FIELD_SIGNED)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define field_is_unsigned(f) \
|
||||
({ \
|
||||
if (__builtin_preserve_field_info(f, BPF_FIELD_SIGNED)) { \
|
||||
return __LINE__; \
|
||||
} \
|
||||
})
|
||||
|
||||
__section("socket_filter/fields") int fields() {
|
||||
field_exists((struct s){}._1);
|
||||
field_exists((s_t){}._2);
|
||||
field_exists((union u){}._1);
|
||||
field_exists((u_t){}._2);
|
||||
|
||||
field_is_signed((struct s){}._1);
|
||||
field_is_unsigned((struct s){}._3);
|
||||
// unions crash clang-14.
|
||||
// field_is_signed((union u){}._1);
|
||||
// field_is_unsigned((union u){}._3);
|
||||
|
||||
field_size_matches((struct s){}._1);
|
||||
field_size_matches((s_t){}._2);
|
||||
field_size_matches((union u){}._1);
|
||||
field_size_matches((u_t){}._2);
|
||||
|
||||
field_offset_matches(struct s, _1);
|
||||
field_offset_matches(s_t, _2);
|
||||
field_offset_matches(union u, _1);
|
||||
field_offset_matches(u_t, _2);
|
||||
|
||||
struct t {
|
||||
union {
|
||||
s_t s[10];
|
||||
};
|
||||
struct {
|
||||
union u u;
|
||||
};
|
||||
} bar, *barp = &bar;
|
||||
|
||||
field_exists(bar.s[2]._1);
|
||||
field_exists(bar.s[1]._2);
|
||||
field_exists(bar.u._1);
|
||||
field_exists(bar.u._2);
|
||||
field_exists(barp[1].u._2);
|
||||
|
||||
field_is_signed(bar.s[2]._1);
|
||||
field_is_unsigned(bar.s[2]._3);
|
||||
// unions crash clang-14.
|
||||
// field_is_signed(bar.u._1);
|
||||
// field_is_signed(bar.u._3);
|
||||
|
||||
field_size_matches(bar.s[2]._1);
|
||||
field_size_matches(bar.s[1]._2);
|
||||
field_size_matches(bar.u._1);
|
||||
field_size_matches(bar.u._2);
|
||||
field_size_matches(barp[1].u._2);
|
||||
|
||||
field_offset_matches(struct t, s[2]._1);
|
||||
field_offset_matches(struct t, s[1]._2);
|
||||
field_offset_matches(struct t, u._1);
|
||||
field_offset_matches(struct t, u._2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ambiguous {
|
||||
int _1;
|
||||
char _2;
|
||||
};
|
||||
|
||||
struct ambiguous___flavour {
|
||||
char _1;
|
||||
int _2;
|
||||
};
|
||||
|
||||
__section("socket_filter/err_ambiguous") int err_ambiguous() {
|
||||
return bpf_core_type_id_kernel(struct ambiguous);
|
||||
}
|
||||
|
||||
__section("socket_filter/err_ambiguous_flavour") int err_ambiguous_flavour() {
|
||||
return bpf_core_type_id_kernel(struct ambiguous___flavour);
|
||||
}
|
||||
Reference in New Issue
Block a user