Add new helper: long bpf_btf_find_by_name_kind(char *name, int name_sz, u32 kind, int flags) Description Find BTF type with given name and kind in vmlinux BTF or in module's BTFs. Return Returns btf_id and btf_obj_fd in lower and upper 32 bits. It will be used by loader program to find btf_id to attach the program to and to find btf_ids of ksyms.
Showing the changes to kernel (2 of 5 files). Show all
Unified · Split
| @@ -6085,3 +6085,65 @@ struct module *btf_try_get_module(const struct btf *btf) · 6084 unmodified lines | |||
| 6085 | 6085 | ||
| 6086 | return res; | 6086 | return res; |
| 6087 | } | 6087 | } |
| 6088 | |||
| 6089 | BPF_CALL_4(bpf_btf_find_by_name_kind, char *, name, int, name_sz, u32, kind, int, flags) | ||
| 6090 | { | ||
| 6091 | struct btf *btf; | ||
| 6092 | long ret; | ||
| 6093 | |||
| 6094 | if (flags) | ||
| 6095 | return -EINVAL; | ||
| 6096 | |||
| 6097 | if (name_sz <= 1 || name[name_sz - 1]) | ||
| 6098 | return -EINVAL; | ||
| 6099 | |||
| 6100 | btf = bpf_get_btf_vmlinux(); | ||
| 6101 | if (IS_ERR(btf)) | ||
| 6102 | return PTR_ERR(btf); | ||
| 6103 | |||
| 6104 | ret = btf_find_by_name_kind(btf, name, kind); | ||
| 6105 | /* ret is never zero, since btf_find_by_name_kind returns | ||
| 6106 | * positive btf_id or negative error. | ||
| 6107 | */ | ||
| 6108 | if (ret < 0) { | ||
| 6109 | struct btf *mod_btf; | ||
| 6110 | int id; | ||
| 6111 | |||
| 6112 | /* If name is not found in vmlinux's BTF then search in module's BTFs */ | ||
| 6113 | spin_lock_bh(&btf_idr_lock); | ||
| 6114 | idr_for_each_entry(&btf_idr, mod_btf, id) { | ||
| 6115 | if (!btf_is_module(mod_btf)) | ||
| 6116 | continue; | ||
| 6117 | /* linear search could be slow hence unlock/lock | ||
| 6118 | * the IDR to avoiding holding it for too long | ||
| 6119 | */ | ||
| 6120 | btf_get(mod_btf); | ||
| 6121 | spin_unlock_bh(&btf_idr_lock); | ||
| 6122 | ret = btf_find_by_name_kind(mod_btf, name, kind); | ||
| 6123 | if (ret > 0) { | ||
| 6124 | int btf_obj_fd; | ||
| 6125 | |||
| 6126 | btf_obj_fd = __btf_new_fd(mod_btf); | ||
| 6127 | if (btf_obj_fd < 0) { | ||
| 6128 | btf_put(mod_btf); | ||
| 6129 | return btf_obj_fd; | ||
| 6130 | } | ||
| 6131 | return ret | (((u64)btf_obj_fd) << 32); | ||
| 6132 | } | ||
| 6133 | spin_lock_bh(&btf_idr_lock); | ||
| 6134 | btf_put(mod_btf); | ||
| 6135 | } | ||
| 6136 | spin_unlock_bh(&btf_idr_lock); | ||
| 6137 | } | ||
| 6138 | return ret; | ||
| 6139 | } | ||
| 6140 | |||
| 6141 | const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = { | ||
| 6142 | .func = bpf_btf_find_by_name_kind, | ||
| 6143 | .gpl_only = false, | ||
| 6144 | .ret_type = RET_INTEGER, | ||
| 6145 | .arg1_type = ARG_PTR_TO_MEM, | ||
| 6146 | .arg2_type = ARG_CONST_SIZE, | ||
| 6147 | .arg3_type = ARG_ANYTHING, | ||
| 6148 | .arg4_type = ARG_ANYTHING, | ||
| 6149 | }; | ||
| @@ -4584,6 +4584,8 @@ syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 4583 unmodified lines | |||
| 4584 | switch (func_id) { | 4584 | switch (func_id) { |
| 4585 | case BPF_FUNC_sys_bpf: | 4585 | case BPF_FUNC_sys_bpf: |
| 4586 | return &bpf_sys_bpf_proto; | 4586 | return &bpf_sys_bpf_proto; |
| 4587 | case BPF_FUNC_btf_find_by_name_kind: | ||
| 4588 | return &bpf_btf_find_by_name_kind_proto; | ||
| 4587 | default: | 4589 | default: |
| 4588 | return tracing_prog_func_proto(func_id, prog); | 4590 | return tracing_prog_func_proto(func_id, prog); |
| 4589 | } | 4591 | } |