David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ |
| 2 | |
| 3 | /* |
| 4 | * Internal libbpf helpers. |
| 5 | * |
| 6 | * Copyright (c) 2019 Facebook |
| 7 | */ |
| 8 | |
| 9 | #ifndef __LIBBPF_LIBBPF_INTERNAL_H |
| 10 | #define __LIBBPF_LIBBPF_INTERNAL_H |
| 11 | |
| 12 | #include "libbpf.h" |
| 13 | |
| 14 | #define BTF_INFO_ENC(kind, kind_flag, vlen) \ |
| 15 | ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) |
| 16 | #define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type) |
| 17 | #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \ |
| 18 | ((encoding) << 24 | (bits_offset) << 16 | (nr_bits)) |
| 19 | #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \ |
| 20 | BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \ |
| 21 | BTF_INT_ENC(encoding, bits_offset, bits) |
| 22 | #define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset) |
| 23 | #define BTF_PARAM_ENC(name, type) (name), (type) |
| 24 | #define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size) |
| 25 | |
| 26 | #ifndef min |
| 27 | # define min(x, y) ((x) < (y) ? (x) : (y)) |
| 28 | #endif |
| 29 | #ifndef max |
| 30 | # define max(x, y) ((x) < (y) ? (y) : (x)) |
| 31 | #endif |
| 32 | #ifndef offsetofend |
| 33 | # define offsetofend(TYPE, FIELD) \ |
| 34 | (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)) |
| 35 | #endif |
| 36 | |
| 37 | /* Symbol versioning is different between static and shared library. |
| 38 | * Properly versioned symbols are needed for shared library, but |
| 39 | * only the symbol of the new version is needed for static library. |
| 40 | */ |
| 41 | #ifdef SHARED |
| 42 | # define COMPAT_VERSION(internal_name, api_name, version) \ |
| 43 | asm(".symver " #internal_name "," #api_name "@" #version); |
| 44 | # define DEFAULT_VERSION(internal_name, api_name, version) \ |
| 45 | asm(".symver " #internal_name "," #api_name "@@" #version); |
| 46 | #else |
| 47 | # define COMPAT_VERSION(internal_name, api_name, version) |
| 48 | # define DEFAULT_VERSION(internal_name, api_name, version) \ |
| 49 | extern typeof(internal_name) api_name \ |
| 50 | __attribute__((alias(#internal_name))); |
| 51 | #endif |
| 52 | |
| 53 | extern void libbpf_print(enum libbpf_print_level level, |
| 54 | const char *format, ...) |
| 55 | __attribute__((format(printf, 2, 3))); |
| 56 | |
| 57 | #define __pr(level, fmt, ...) \ |
| 58 | do { \ |
| 59 | libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \ |
| 60 | } while (0) |
| 61 | |
| 62 | #define pr_warning(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__) |
| 63 | #define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__) |
| 64 | #define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__) |
| 65 | |
| 66 | int libbpf__load_raw_btf(const char *raw_types, size_t types_len, |
| 67 | const char *str_sec, size_t str_len); |
| 68 | |
| 69 | struct btf_ext_info { |
| 70 | /* |
| 71 | * info points to the individual info section (e.g. func_info and |
| 72 | * line_info) from the .BTF.ext. It does not include the __u32 rec_size. |
| 73 | */ |
| 74 | void *info; |
| 75 | __u32 rec_size; |
| 76 | __u32 len; |
| 77 | }; |
| 78 | |
| 79 | #define for_each_btf_ext_sec(seg, sec) \ |
| 80 | for (sec = (seg)->info; \ |
| 81 | (void *)sec < (seg)->info + (seg)->len; \ |
| 82 | sec = (void *)sec + sizeof(struct btf_ext_info_sec) + \ |
| 83 | (seg)->rec_size * sec->num_info) |
| 84 | |
| 85 | #define for_each_btf_ext_rec(seg, sec, i, rec) \ |
| 86 | for (i = 0, rec = (void *)&(sec)->data; \ |
| 87 | i < (sec)->num_info; \ |
| 88 | i++, rec = (void *)rec + (seg)->rec_size) |
| 89 | |
| 90 | struct btf_ext { |
| 91 | union { |
| 92 | struct btf_ext_header *hdr; |
| 93 | void *data; |
| 94 | }; |
| 95 | struct btf_ext_info func_info; |
| 96 | struct btf_ext_info line_info; |
| 97 | struct btf_ext_info offset_reloc_info; |
| 98 | __u32 data_size; |
| 99 | }; |
| 100 | |
| 101 | struct btf_ext_info_sec { |
| 102 | __u32 sec_name_off; |
| 103 | __u32 num_info; |
| 104 | /* Followed by num_info * record_size number of bytes */ |
| 105 | __u8 data[0]; |
| 106 | }; |
| 107 | |
| 108 | /* The minimum bpf_func_info checked by the loader */ |
| 109 | struct bpf_func_info_min { |
| 110 | __u32 insn_off; |
| 111 | __u32 type_id; |
| 112 | }; |
| 113 | |
| 114 | /* The minimum bpf_line_info checked by the loader */ |
| 115 | struct bpf_line_info_min { |
| 116 | __u32 insn_off; |
| 117 | __u32 file_name_off; |
| 118 | __u32 line_off; |
| 119 | __u32 line_col; |
| 120 | }; |
| 121 | |
| 122 | /* The minimum bpf_offset_reloc checked by the loader |
| 123 | * |
| 124 | * Offset relocation captures the following data: |
| 125 | * - insn_off - instruction offset (in bytes) within a BPF program that needs |
| 126 | * its insn->imm field to be relocated with actual offset; |
| 127 | * - type_id - BTF type ID of the "root" (containing) entity of a relocatable |
| 128 | * offset; |
| 129 | * - access_str_off - offset into corresponding .BTF string section. String |
| 130 | * itself encodes an accessed field using a sequence of field and array |
| 131 | * indicies, separated by colon (:). It's conceptually very close to LLVM's |
| 132 | * getelementptr ([0]) instruction's arguments for identifying offset to |
| 133 | * a field. |
| 134 | * |
| 135 | * Example to provide a better feel. |
| 136 | * |
| 137 | * struct sample { |
| 138 | * int a; |
| 139 | * struct { |
| 140 | * int b[10]; |
| 141 | * }; |
| 142 | * }; |
| 143 | * |
| 144 | * struct sample *s = ...; |
| 145 | * int x = &s->a; // encoded as "0:0" (a is field #0) |
| 146 | * int y = &s->b[5]; // encoded as "0:1:0:5" (anon struct is field #1, |
| 147 | * // b is field #0 inside anon struct, accessing elem #5) |
| 148 | * int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array) |
| 149 | * |
| 150 | * type_id for all relocs in this example will capture BTF type id of |
| 151 | * `struct sample`. |
| 152 | * |
| 153 | * Such relocation is emitted when using __builtin_preserve_access_index() |
| 154 | * Clang built-in, passing expression that captures field address, e.g.: |
| 155 | * |
| 156 | * bpf_probe_read(&dst, sizeof(dst), |
| 157 | * __builtin_preserve_access_index(&src->a.b.c)); |
| 158 | * |
| 159 | * In this case Clang will emit offset relocation recording necessary data to |
| 160 | * be able to find offset of embedded `a.b.c` field within `src` struct. |
| 161 | * |
| 162 | * [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction |
| 163 | */ |
| 164 | struct bpf_offset_reloc { |
| 165 | __u32 insn_off; |
| 166 | __u32 type_id; |
| 167 | __u32 access_str_off; |
| 168 | }; |
| 169 | |
| 170 | #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ |