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 }