github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/testdata/relocs.c (about)

     1  #include "../../testdata/common.h"
     2  #include "bpf_core_read.h"
     3  
     4  enum e {
     5  	ZERO = 0,
     6  	ONE,
     7  	TWO,
     8  };
     9  
    10  enum e64 {
    11  	LARGE = 0x1ffffffff,
    12  };
    13  
    14  typedef enum e e_t;
    15  
    16  struct s {
    17  	int _1;
    18  	char _2;
    19  	unsigned int _3;
    20  };
    21  
    22  typedef struct s s_t;
    23  
    24  union u {
    25  	int *_1;
    26  	char *_2;
    27  	unsigned int *_3;
    28  };
    29  
    30  typedef union u u_t;
    31  
    32  #define local_id_not_zero(expr) \
    33  	({ \
    34  		if (bpf_core_type_id_local(expr) == 0) { \
    35  			return __LINE__; \
    36  		} \
    37  	})
    38  
    39  #define target_and_local_id_dont_match(expr) \
    40  	({ \
    41  		if (bpf_core_type_id_kernel(expr) == bpf_core_type_id_local(expr)) { \
    42  			return __LINE__; \
    43  		} \
    44  	})
    45  
    46  __section("socket/type_ids") int type_ids() {
    47  	local_id_not_zero(int);
    48  	local_id_not_zero(struct { int frob; });
    49  	local_id_not_zero(enum {FRAP});
    50  	local_id_not_zero(union { char bar; });
    51  
    52  	local_id_not_zero(struct s);
    53  	local_id_not_zero(s_t);
    54  	local_id_not_zero(const s_t);
    55  	local_id_not_zero(volatile s_t);
    56  	local_id_not_zero(enum e);
    57  	local_id_not_zero(e_t);
    58  	local_id_not_zero(const e_t);
    59  	local_id_not_zero(volatile e_t);
    60  	local_id_not_zero(union u);
    61  	local_id_not_zero(u_t);
    62  	local_id_not_zero(const u_t);
    63  	local_id_not_zero(volatile u_t);
    64  
    65  	// In this context, target is the BTF generated by clang. local is
    66  	// generated on the fly by the library. There is a low chance that
    67  	// the order on both is the same, so we assert this to make sure that
    68  	// CO-RE uses the IDs from the dynamic BTF.
    69  	// Qualifiers on types crash clang.
    70  	target_and_local_id_dont_match(struct s);
    71  	target_and_local_id_dont_match(s_t);
    72  	// target_and_local_id_dont_match(const s_t);
    73  	// target_and_local_id_dont_match(volatile s_t);
    74  	target_and_local_id_dont_match(enum e);
    75  	target_and_local_id_dont_match(e_t);
    76  	// target_and_local_id_dont_match(const e_t);
    77  	// target_and_local_id_dont_match(volatile e_t);
    78  	target_and_local_id_dont_match(union u);
    79  	target_and_local_id_dont_match(u_t);
    80  	// target_and_local_id_dont_match(const u_t);
    81  	// target_and_local_id_dont_match(volatile u_t);
    82  
    83  	return 0;
    84  }
    85  
    86  #define type_exists(expr) \
    87  	({ \
    88  		if (!bpf_core_type_exists(expr)) { \
    89  			return __LINE__; \
    90  		} \
    91  	})
    92  
    93  #define type_size_matches(expr) \
    94  	({ \
    95  		if (bpf_core_type_size(expr) != sizeof(expr)) { \
    96  			return __LINE__; \
    97  		} \
    98  	})
    99  
   100  #define type_matches(expr) \
   101  	({ \
   102  		if (!bpf_core_type_matches(expr)) { \
   103  			return __LINE__; \
   104  		} \
   105  	})
   106  
   107  __section("socket/types") int types() {
   108  	type_exists(struct s);
   109  	type_exists(s_t);
   110  	type_exists(const s_t);
   111  	type_exists(volatile s_t);
   112  	type_exists(enum e);
   113  	type_exists(e_t);
   114  	type_exists(const e_t);
   115  	type_exists(volatile e_t);
   116  	type_exists(union u);
   117  	type_exists(u_t);
   118  	type_exists(const u_t);
   119  	type_exists(volatile u_t);
   120  	// TODO: Check non-existence.
   121  
   122  	type_size_matches(struct s);
   123  	type_size_matches(s_t);
   124  	type_size_matches(const s_t);
   125  	type_size_matches(volatile s_t);
   126  	type_size_matches(enum e);
   127  	type_size_matches(e_t);
   128  	type_size_matches(const e_t);
   129  	type_size_matches(volatile e_t);
   130  	type_size_matches(union u);
   131  	type_size_matches(u_t);
   132  	type_size_matches(const u_t);
   133  	type_size_matches(volatile u_t);
   134  
   135  	type_matches(struct s);
   136  	type_matches(s_t);
   137  	type_matches(const s_t);
   138  	type_matches(volatile s_t);
   139  	type_matches(enum e);
   140  	type_matches(e_t);
   141  	type_matches(const e_t);
   142  	type_matches(volatile e_t);
   143  	type_matches(union u);
   144  	type_matches(u_t);
   145  	type_matches(const u_t);
   146  	type_matches(volatile u_t);
   147  
   148  	return 0;
   149  }
   150  
   151  #define enum_value_exists(t, v) \
   152  	({ \
   153  		if (!bpf_core_enum_value_exists(t, v)) { \
   154  			return __LINE__; \
   155  		} \
   156  	})
   157  
   158  #define enum_value_matches(t, v) \
   159  	({ \
   160  		if (v != bpf_core_enum_value(t, v)) { \
   161  			return __LINE__; \
   162  		} \
   163  	})
   164  
   165  __section("socket/enums") int enums() {
   166  	enum_value_exists(enum e, ONE);
   167  	enum_value_exists(volatile enum e, ONE);
   168  	enum_value_exists(const enum e, ONE);
   169  	enum_value_exists(e_t, TWO);
   170  	enum_value_exists(enum e64, LARGE);
   171  	// TODO: Check non-existence.
   172  
   173  	enum_value_matches(enum e, ZERO);
   174  	enum_value_matches(enum e, TWO);
   175  	enum_value_matches(e_t, ONE);
   176  	enum_value_matches(volatile e_t, ONE);
   177  	enum_value_matches(const e_t, ONE);
   178  	enum_value_matches(enum e64, LARGE);
   179  
   180  	return 0;
   181  }
   182  
   183  #define field_exists(f) \
   184  	({ \
   185  		if (!bpf_core_field_exists(f)) { \
   186  			return __LINE__; \
   187  		} \
   188  	})
   189  
   190  #define field_size_matches(f) \
   191  	({ \
   192  		if (sizeof(f) != bpf_core_field_size(f)) { \
   193  			return __LINE__; \
   194  		} \
   195  	})
   196  
   197  #define field_offset_matches(t, f) \
   198  	({ \
   199  		if (__builtin_offsetof(t, f) != __builtin_preserve_field_info(((typeof(t) *)0)->f, BPF_FIELD_BYTE_OFFSET)) { \
   200  			return __LINE__; \
   201  		} \
   202  	})
   203  
   204  #define field_is_signed(f) \
   205  	({ \
   206  		if (!__builtin_preserve_field_info(f, BPF_FIELD_SIGNED)) { \
   207  			return __LINE__; \
   208  		} \
   209  	})
   210  
   211  #define field_is_unsigned(f) \
   212  	({ \
   213  		if (__builtin_preserve_field_info(f, BPF_FIELD_SIGNED)) { \
   214  			return __LINE__; \
   215  		} \
   216  	})
   217  
   218  __section("socket/fields") int fields() {
   219  	field_exists((struct s){}._1);
   220  	field_exists((s_t){}._2);
   221  	field_exists((union u){}._1);
   222  	field_exists((u_t){}._2);
   223  
   224  	field_is_signed((struct s){}._1);
   225  	field_is_unsigned((struct s){}._3);
   226  	// unions crash clang-14.
   227  	// field_is_signed((union u){}._1);
   228  	// field_is_unsigned((union u){}._3);
   229  
   230  	field_size_matches((struct s){}._1);
   231  	field_size_matches((s_t){}._2);
   232  	field_size_matches((union u){}._1);
   233  	field_size_matches((u_t){}._2);
   234  
   235  	field_offset_matches(struct s, _1);
   236  	field_offset_matches(s_t, _2);
   237  	field_offset_matches(union u, _1);
   238  	field_offset_matches(u_t, _2);
   239  
   240  	struct t {
   241  		union {
   242  			s_t s[10];
   243  		};
   244  		struct {
   245  			union u u;
   246  		};
   247  	} bar, *barp = &bar;
   248  
   249  	field_exists(bar.s[2]._1);
   250  	field_exists(bar.s[1]._2);
   251  	field_exists(bar.u._1);
   252  	field_exists(bar.u._2);
   253  	field_exists(barp[1].u._2);
   254  
   255  	field_is_signed(bar.s[2]._1);
   256  	field_is_unsigned(bar.s[2]._3);
   257  	// unions crash clang-14.
   258  	// field_is_signed(bar.u._1);
   259  	// field_is_signed(bar.u._3);
   260  
   261  	field_size_matches(bar.s[2]._1);
   262  	field_size_matches(bar.s[1]._2);
   263  	field_size_matches(bar.u._1);
   264  	field_size_matches(bar.u._2);
   265  	field_size_matches(barp[1].u._2);
   266  
   267  	field_offset_matches(struct t, s[2]._1);
   268  	field_offset_matches(struct t, s[1]._2);
   269  	field_offset_matches(struct t, u._1);
   270  	field_offset_matches(struct t, u._2);
   271  
   272  	return 0;
   273  }
   274  
   275  struct ambiguous {
   276  	int _1;
   277  	char _2;
   278  };
   279  
   280  struct ambiguous___flavour {
   281  	char _1;
   282  	int _2;
   283  };
   284  
   285  __section("socket/err_ambiguous") int err_ambiguous() {
   286  	return bpf_core_type_id_kernel(struct ambiguous);
   287  }
   288  
   289  __section("socket/err_ambiguous_flavour") int err_ambiguous_flavour() {
   290  	return bpf_core_type_id_kernel(struct ambiguous___flavour);
   291  }