In case the kernel doesn't support BTF_FUNC_GLOBAL sanitize BTF produced by the compiler for global functions.
Unified · Split
| @@ -146,6 +146,12 @@ enum { · 145 unmodified lines | ||
| 146 | 146 | BTF_VAR_GLOBAL_EXTERN = 2, |
| 147 | 147 | }; |
| 148 | 148 | |
| 149 | +enum btf_func_linkage { | |
| 150 | + BTF_FUNC_STATIC = 0, | |
| 151 | + BTF_FUNC_GLOBAL = 1, | |
| 152 | + BTF_FUNC_EXTERN = 2, | |
| 153 | +}; | |
| 154 | + | |
| 149 | 155 | /* BTF_KIND_VAR is followed by a single "struct btf_var" to describe |
| 150 | 156 | * additional information related to the variable such as its linkage. |
| 151 | 157 | */ |
| @@ -173,6 +173,8 @@ struct bpf_capabilities { · 172 unmodified lines | ||
| 173 | 173 | __u32 btf_datasec:1; |
| 174 | 174 | /* BPF_F_MMAPABLE is supported for arrays */ |
| 175 | 175 | __u32 array_mmap:1; |
| 176 | + /* BTF_FUNC_GLOBAL is supported */ | |
| 177 | + __u32 btf_func_global:1; | |
| 176 | 178 | }; |
| 177 | 179 | |
| 178 | 180 | enum reloc_type { |
| @@ -2209,13 +2211,14 @@ static bool section_have_execinstr(struct bpf_object *obj, int idx) · 2030 unmodified lines | ||
| 2209 | 2211 | |
| 2210 | 2212 | static void bpf_object__sanitize_btf(struct bpf_object *obj) |
| 2211 | 2213 | { |
| 2214 | + bool has_func_global = obj->caps.btf_func_global; | |
| 2212 | 2215 | bool has_datasec = obj->caps.btf_datasec; |
| 2213 | 2216 | bool has_func = obj->caps.btf_func; |
| 2214 | 2217 | struct btf *btf = obj->btf; |
| 2215 | 2218 | struct btf_type *t; |
| 2216 | 2219 | int i, j, vlen; |
| 2217 | 2220 | |
| 2218 | − if (!obj->btf || (has_func && has_datasec)) | |
| 2221 | + if (!obj->btf || (has_func && has_datasec && has_func_global)) | |
| 2219 | 2222 | return; |
| 2220 | 2223 | |
| 2221 | 2224 | for (i = 1; i <= btf__get_nr_types(btf); i++) { |
| @@ -2263,6 +2266,9 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj) · 41 unmodified lines | ||
| 2263 | 2266 | } else if (!has_func && btf_is_func(t)) { |
| 2264 | 2267 | /* replace FUNC with TYPEDEF */ |
| 2265 | 2268 | t->info = BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0); |
| 2269 | + } else if (!has_func_global && btf_is_func(t)) { | |
| 2270 | + /* replace BTF_FUNC_GLOBAL with BTF_FUNC_STATIC */ | |
| 2271 | + t->info = BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0); | |
| 2266 | 2272 | } |
| 2267 | 2273 | } |
| 2268 | 2274 | } |
| @@ -3205,6 +3211,32 @@ static int bpf_object__probe_btf_func(struct bpf_object *obj) · 936 unmodified lines | ||
| 3205 | 3211 | return 0; |
| 3206 | 3212 | } |
| 3207 | 3213 | |
| 3214 | +static int bpf_object__probe_btf_func_global(struct bpf_object *obj) | |
| 3215 | +{ | |
| 3216 | + static const char strs[] = "\0int\0x\0a"; | |
| 3217 | + /* static void x(int a) {} */ | |
| 3218 | + __u32 types[] = { | |
| 3219 | + /* int */ | |
| 3220 | + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ | |
| 3221 | + /* FUNC_PROTO */ /* [2] */ | |
| 3222 | + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 0), | |
| 3223 | + BTF_PARAM_ENC(7, 1), | |
| 3224 | + /* FUNC x BTF_FUNC_GLOBAL */ /* [3] */ | |
| 3225 | + BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 2), | |
| 3226 | + }; | |
| 3227 | + int btf_fd; | |
| 3228 | + | |
| 3229 | + btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types), | |
| 3230 | + strs, sizeof(strs)); | |
| 3231 | + if (btf_fd >= 0) { | |
| 3232 | + obj->caps.btf_func_global = 1; | |
| 3233 | + close(btf_fd); | |
| 3234 | + return 1; | |
| 3235 | + } | |
| 3236 | + | |
| 3237 | + return 0; | |
| 3238 | +} | |
| 3239 | + | |
| 3208 | 3240 | static int bpf_object__probe_btf_datasec(struct bpf_object *obj) |
| 3209 | 3241 | { |
| 3210 | 3242 | static const char strs[] = "\0x\0.data"; |
| @@ -3260,6 +3292,7 @@ bpf_object__probe_caps(struct bpf_object *obj) · 49 unmodified lines | ||
| 3260 | 3292 | bpf_object__probe_name, |
| 3261 | 3293 | bpf_object__probe_global_data, |
| 3262 | 3294 | bpf_object__probe_btf_func, |
| 3295 | + bpf_object__probe_btf_func_global, | |
| 3263 | 3296 | bpf_object__probe_btf_datasec, |
| 3264 | 3297 | bpf_object__probe_array_mmap, |
| 3265 | 3298 | }; |