...

Text file src/github.com/cilium/ebpf/testdata/loader.c

Documentation: github.com/cilium/ebpf/testdata

     1/* This file excercises the ELF loader.
     2 */
     3
     4#include "common.h"
     5
     6char __license[] __section("license") = "MIT";
     7
     8#if __clang_major__ >= 9
     9// Clang < 9 doesn't emit the necessary BTF for this to work.
    10struct {
    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
    18struct {
    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
    25struct {
    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.
    34struct 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.
    42struct {
    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.
    50struct {
    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
    63struct {
    64	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    65	__uint(max_entries, 4096);
    66} perf_event_array __section(".maps");
    67#else
    68struct 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
    76struct 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
    83struct bpf_map_def perf_event_array __section("maps") = {
    84	.type        = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
    85	.max_entries = 4096,
    86};
    87#endif
    88
    89struct 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
    95static int __attribute__((noinline)) __section("static") static_fn(uint32_t arg) {
    96	return arg - 1;
    97}
    98
    99int __attribute__((noinline)) global_fn2(uint32_t arg) {
   100	return arg + 2;
   101}
   102
   103int __attribute__((noinline)) __section("other") global_fn3(uint32_t arg) {
   104	return arg + 1;
   105}
   106
   107int __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
   112static volatile unsigned int key1 = 0; // .bss
   113static volatile unsigned int key2 = 1; // .data
   114volatile const unsigned int key3  = 2; // .rodata
   115static volatile const uint32_t arg;    // .rodata, populated by loader
   116// custom .rodata section, populated by loader
   117static 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
   147volatile const unsigned int uneg               = -1;
   148volatile const int neg                         = -2;
   149static volatile const unsigned int static_uneg = -3;
   150static 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[]) { 0x0, 0x1, 0x2, 0x3 }
   185
   186	int i;
   187	for (i = 0; i < 3; i++) {
   188		if (ctx == values[i]) {
   189			return values[i];
   190		}
   191	}
   192
   193	return 0;
   194}

View as plain text