github.com/cilium/ebpf@v0.10.0/testdata/loader.c (about)

     1  /* This file excercises the ELF loader.
     2   */
     3  
     4  #include "common.h"
     5  
     6  char __license[] __section("license") = "MIT";
     7  
     8  #if __clang_major__ >= 9
     9  // Clang < 9 doesn't emit the necessary BTF for this to work.
    10  struct {
    11  	__uint(type, BPF_MAP_TYPE_HASH);
    12  	__type(key, uint32_t);
    13  	__type(value, uint64_t);
    14  	__uint(max_entries, 1);
    15  	__uint(map_flags, BPF_F_NO_PREALLOC);
    16  } hash_map __section(".maps");
    17  
    18  struct {
    19  	__uint(type, BPF_MAP_TYPE_HASH);
    20  	__uint(key_size, sizeof(uint32_t));
    21  	__uint(value_size, sizeof(uint64_t));
    22  	__uint(max_entries, 2);
    23  } hash_map2 __section(".maps");
    24  
    25  struct {
    26  	__uint(type, BPF_MAP_TYPE_HASH);
    27  	__type(key, uint32_t);
    28  	__type(value, uint64_t);
    29  	__uint(max_entries, 1);
    30  	__uint(pinning, 1 /* LIBBPF_PIN_BY_NAME */);
    31  } btf_pin __section(".maps");
    32  
    33  // Named map type definition, without structure variable declaration.
    34  struct inner_map_t {
    35  	__uint(type, BPF_MAP_TYPE_HASH);
    36  	__type(key, uint32_t);
    37  	__type(value, int);
    38  	__uint(max_entries, 1);
    39  };
    40  
    41  // Anonymous map type definition with structure variable declaration.
    42  struct {
    43  	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
    44  	__uint(key_size, sizeof(uint32_t));
    45  	__uint(max_entries, 1);
    46  	__array(values, struct inner_map_t);
    47  } btf_outer_map __section(".maps");
    48  
    49  // Array of maps with anonymous inner struct.
    50  struct {
    51  	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
    52  	__uint(key_size, sizeof(uint32_t));
    53  	__uint(max_entries, 1);
    54  	__array(
    55  		values, struct {
    56  			__uint(type, BPF_MAP_TYPE_HASH);
    57  			__uint(max_entries, 1);
    58  			__type(key, uint32_t);
    59  			__type(value, uint32_t);
    60  		});
    61  } btf_outer_map_anon __section(".maps");
    62  
    63  struct {
    64  	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    65  	__uint(max_entries, 4096);
    66  } perf_event_array __section(".maps");
    67  #else
    68  struct bpf_map_def hash_map __section("maps") = {
    69  	.type        = BPF_MAP_TYPE_HASH,
    70  	.key_size    = sizeof(uint32_t),
    71  	.value_size  = sizeof(uint64_t),
    72  	.max_entries = 1,
    73  	.map_flags   = BPF_F_NO_PREALLOC,
    74  };
    75  
    76  struct bpf_map_def hash_map2 __section("maps") = {
    77  	.type        = BPF_MAP_TYPE_HASH,
    78  	.key_size    = sizeof(uint32_t),
    79  	.value_size  = sizeof(uint64_t),
    80  	.max_entries = 2,
    81  };
    82  
    83  struct bpf_map_def perf_event_array __section("maps") = {
    84  	.type        = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
    85  	.max_entries = 4096,
    86  };
    87  #endif
    88  
    89  struct bpf_map_def array_of_hash_map __section("maps") = {
    90  	.type        = BPF_MAP_TYPE_ARRAY_OF_MAPS,
    91  	.key_size    = sizeof(uint32_t),
    92  	.max_entries = 2,
    93  };
    94  
    95  static int __attribute__((noinline)) __section("static") static_fn(uint32_t arg) {
    96  	return arg - 1;
    97  }
    98  
    99  int __attribute__((noinline)) global_fn2(uint32_t arg) {
   100  	return arg + 2;
   101  }
   102  
   103  int __attribute__((noinline)) __section("other") global_fn3(uint32_t arg) {
   104  	return arg + 1;
   105  }
   106  
   107  int __attribute__((noinline)) global_fn(uint32_t arg) {
   108  	return static_fn(arg) + global_fn2(arg) + global_fn3(arg);
   109  }
   110  
   111  #if __clang_major__ >= 9
   112  static volatile unsigned int key1 = 0; // .bss
   113  static volatile unsigned int key2 = 1; // .data
   114  volatile const unsigned int key3  = 2; // .rodata
   115  static volatile const uint32_t arg;    // .rodata, populated by loader
   116  // custom .rodata section, populated by loader
   117  static volatile const uint32_t arg2 __section(".rodata.test");
   118  #endif
   119  
   120  __section("xdp") int xdp_prog() {
   121  #if __clang_major__ < 9
   122  	unsigned int key1 = 0;
   123  	unsigned int key2 = 1;
   124  	unsigned int key3 = 2;
   125  	uint32_t arg      = 1;
   126  	uint32_t arg2     = 2;
   127  #endif
   128  	map_lookup_elem(&hash_map, (void *)&key1);
   129  	map_lookup_elem(&hash_map2, (void *)&key2);
   130  	map_lookup_elem(&hash_map2, (void *)&key3);
   131  	return static_fn(arg) + global_fn(arg) + arg2;
   132  }
   133  
   134  // This function has no relocations, and is thus parsed differently.
   135  __section("socket") int no_relocation() {
   136  	return 0;
   137  }
   138  
   139  // Make sure we allow relocations generated by inline assembly.
   140  __section("socket/2") int asm_relocation() {
   141  	int my_const;
   142  	asm("%0 = MY_CONST ll" : "=r"(my_const));
   143  	return my_const;
   144  }
   145  
   146  #if __clang_major__ >= 9
   147  volatile const unsigned int uneg               = -1;
   148  volatile const int neg                         = -2;
   149  static volatile const unsigned int static_uneg = -3;
   150  static volatile const int static_neg           = -4;
   151  
   152  __section("socket/3") int data_sections() {
   153  	if (uneg != (unsigned int)-1)
   154  		return __LINE__;
   155  
   156  	if (neg != -2)
   157  		return __LINE__;
   158  
   159  	if (static_uneg != (unsigned int)-3)
   160  		return __LINE__;
   161  
   162  	if (static_neg != -4)
   163  		return __LINE__;
   164  
   165  	return 0;
   166  }
   167  #else
   168  __section("socket/3") int data_sections() {
   169  	return 0;
   170  }
   171  #endif
   172  
   173  /*
   174   * Up until LLVM 14, this program results in an .rodata.cst32 section
   175   * that is accessed by 'return values[i]'. For this section, no BTF is
   176   * emitted. 'values' cannot be rewritten, since there is no BTF info
   177   * describing the data section.
   178   */
   179  __section("socket/4") int anon_const() {
   180  	volatile int ctx = 0;
   181  
   182  // 32 bytes wide results in a .rodata.cst32 section.
   183  #define values \
   184  	(uint64_t[]) { \
   185  		0x0, 0x1, 0x2, 0x3 \
   186  	}
   187  
   188  	int i;
   189  	for (i = 0; i < 3; i++) {
   190  		if (ctx == values[i]) {
   191  			return values[i];
   192  		}
   193  	}
   194  
   195  	return 0;
   196  }