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