1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /* Copyright (c) 2018 Facebook */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #ifndef _LINUX_BTF_H
5*4882a593Smuzhiyun #define _LINUX_BTF_H 1
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/types.h>
8*4882a593Smuzhiyun #include <uapi/linux/btf.h>
9*4882a593Smuzhiyun #include <uapi/linux/bpf.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define BTF_TYPE_EMIT(type) ((void)(type *)0)
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun struct btf;
14*4882a593Smuzhiyun struct btf_member;
15*4882a593Smuzhiyun struct btf_type;
16*4882a593Smuzhiyun union bpf_attr;
17*4882a593Smuzhiyun struct btf_show;
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun extern const struct file_operations btf_fops;
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun void btf_put(struct btf *btf);
22*4882a593Smuzhiyun int btf_new_fd(const union bpf_attr *attr);
23*4882a593Smuzhiyun struct btf *btf_get_by_fd(int fd);
24*4882a593Smuzhiyun int btf_get_info_by_fd(const struct btf *btf,
25*4882a593Smuzhiyun const union bpf_attr *attr,
26*4882a593Smuzhiyun union bpf_attr __user *uattr);
27*4882a593Smuzhiyun /* Figure out the size of a type_id. If type_id is a modifier
28*4882a593Smuzhiyun * (e.g. const), it will be resolved to find out the type with size.
29*4882a593Smuzhiyun *
30*4882a593Smuzhiyun * For example:
31*4882a593Smuzhiyun * In describing "const void *", type_id is "const" and "const"
32*4882a593Smuzhiyun * refers to "void *". The return type will be "void *".
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * If type_id is a simple "int", then return type will be "int".
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * @btf: struct btf object
37*4882a593Smuzhiyun * @type_id: Find out the size of type_id. The type_id of the return
38*4882a593Smuzhiyun * type is set to *type_id.
39*4882a593Smuzhiyun * @ret_size: It can be NULL. If not NULL, the size of the return
40*4882a593Smuzhiyun * type is set to *ret_size.
41*4882a593Smuzhiyun * Return: The btf_type (resolved to another type with size info if needed).
42*4882a593Smuzhiyun * NULL is returned if type_id itself does not have size info
43*4882a593Smuzhiyun * (e.g. void) or it cannot be resolved to another type that
44*4882a593Smuzhiyun * has size info.
45*4882a593Smuzhiyun * *type_id and *ret_size will not be changed in the
46*4882a593Smuzhiyun * NULL return case.
47*4882a593Smuzhiyun */
48*4882a593Smuzhiyun const struct btf_type *btf_type_id_size(const struct btf *btf,
49*4882a593Smuzhiyun u32 *type_id,
50*4882a593Smuzhiyun u32 *ret_size);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /*
53*4882a593Smuzhiyun * Options to control show behaviour.
54*4882a593Smuzhiyun * - BTF_SHOW_COMPACT: no formatting around type information
55*4882a593Smuzhiyun * - BTF_SHOW_NONAME: no struct/union member names/types
56*4882a593Smuzhiyun * - BTF_SHOW_PTR_RAW: show raw (unobfuscated) pointer values;
57*4882a593Smuzhiyun * equivalent to %px.
58*4882a593Smuzhiyun * - BTF_SHOW_ZERO: show zero-valued struct/union members; they
59*4882a593Smuzhiyun * are not displayed by default
60*4882a593Smuzhiyun * - BTF_SHOW_UNSAFE: skip use of bpf_probe_read() to safely read
61*4882a593Smuzhiyun * data before displaying it.
62*4882a593Smuzhiyun */
63*4882a593Smuzhiyun #define BTF_SHOW_COMPACT BTF_F_COMPACT
64*4882a593Smuzhiyun #define BTF_SHOW_NONAME BTF_F_NONAME
65*4882a593Smuzhiyun #define BTF_SHOW_PTR_RAW BTF_F_PTR_RAW
66*4882a593Smuzhiyun #define BTF_SHOW_ZERO BTF_F_ZERO
67*4882a593Smuzhiyun #define BTF_SHOW_UNSAFE (1ULL << 4)
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
70*4882a593Smuzhiyun struct seq_file *m);
71*4882a593Smuzhiyun int btf_type_seq_show_flags(const struct btf *btf, u32 type_id, void *obj,
72*4882a593Smuzhiyun struct seq_file *m, u64 flags);
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /*
75*4882a593Smuzhiyun * Copy len bytes of string representation of obj of BTF type_id into buf.
76*4882a593Smuzhiyun *
77*4882a593Smuzhiyun * @btf: struct btf object
78*4882a593Smuzhiyun * @type_id: type id of type obj points to
79*4882a593Smuzhiyun * @obj: pointer to typed data
80*4882a593Smuzhiyun * @buf: buffer to write to
81*4882a593Smuzhiyun * @len: maximum length to write to buf
82*4882a593Smuzhiyun * @flags: show options (see above)
83*4882a593Smuzhiyun *
84*4882a593Smuzhiyun * Return: length that would have been/was copied as per snprintf, or
85*4882a593Smuzhiyun * negative error.
86*4882a593Smuzhiyun */
87*4882a593Smuzhiyun int btf_type_snprintf_show(const struct btf *btf, u32 type_id, void *obj,
88*4882a593Smuzhiyun char *buf, int len, u64 flags);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun int btf_get_fd_by_id(u32 id);
91*4882a593Smuzhiyun u32 btf_id(const struct btf *btf);
92*4882a593Smuzhiyun bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
93*4882a593Smuzhiyun const struct btf_member *m,
94*4882a593Smuzhiyun u32 expected_offset, u32 expected_size);
95*4882a593Smuzhiyun int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t);
96*4882a593Smuzhiyun bool btf_type_is_void(const struct btf_type *t);
97*4882a593Smuzhiyun s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind);
98*4882a593Smuzhiyun const struct btf_type *btf_type_skip_modifiers(const struct btf *btf,
99*4882a593Smuzhiyun u32 id, u32 *res_id);
100*4882a593Smuzhiyun const struct btf_type *btf_type_resolve_ptr(const struct btf *btf,
101*4882a593Smuzhiyun u32 id, u32 *res_id);
102*4882a593Smuzhiyun const struct btf_type *btf_type_resolve_func_ptr(const struct btf *btf,
103*4882a593Smuzhiyun u32 id, u32 *res_id);
104*4882a593Smuzhiyun const struct btf_type *
105*4882a593Smuzhiyun btf_resolve_size(const struct btf *btf, const struct btf_type *type,
106*4882a593Smuzhiyun u32 *type_size);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun #define for_each_member(i, struct_type, member) \
109*4882a593Smuzhiyun for (i = 0, member = btf_type_member(struct_type); \
110*4882a593Smuzhiyun i < btf_type_vlen(struct_type); \
111*4882a593Smuzhiyun i++, member++)
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun #define for_each_vsi(i, datasec_type, member) \
114*4882a593Smuzhiyun for (i = 0, member = btf_type_var_secinfo(datasec_type); \
115*4882a593Smuzhiyun i < btf_type_vlen(datasec_type); \
116*4882a593Smuzhiyun i++, member++)
117*4882a593Smuzhiyun
btf_type_is_ptr(const struct btf_type * t)118*4882a593Smuzhiyun static inline bool btf_type_is_ptr(const struct btf_type *t)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun return BTF_INFO_KIND(t->info) == BTF_KIND_PTR;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
btf_type_is_int(const struct btf_type * t)123*4882a593Smuzhiyun static inline bool btf_type_is_int(const struct btf_type *t)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun return BTF_INFO_KIND(t->info) == BTF_KIND_INT;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
btf_type_is_small_int(const struct btf_type * t)128*4882a593Smuzhiyun static inline bool btf_type_is_small_int(const struct btf_type *t)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun return btf_type_is_int(t) && t->size <= sizeof(u64);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
btf_type_is_enum(const struct btf_type * t)133*4882a593Smuzhiyun static inline bool btf_type_is_enum(const struct btf_type *t)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
btf_type_is_typedef(const struct btf_type * t)138*4882a593Smuzhiyun static inline bool btf_type_is_typedef(const struct btf_type *t)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun return BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
btf_type_is_func(const struct btf_type * t)143*4882a593Smuzhiyun static inline bool btf_type_is_func(const struct btf_type *t)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
btf_type_is_func_proto(const struct btf_type * t)148*4882a593Smuzhiyun static inline bool btf_type_is_func_proto(const struct btf_type *t)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC_PROTO;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
btf_type_is_var(const struct btf_type * t)153*4882a593Smuzhiyun static inline bool btf_type_is_var(const struct btf_type *t)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun return BTF_INFO_KIND(t->info) == BTF_KIND_VAR;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* union is only a special case of struct:
159*4882a593Smuzhiyun * all its offsetof(member) == 0
160*4882a593Smuzhiyun */
btf_type_is_struct(const struct btf_type * t)161*4882a593Smuzhiyun static inline bool btf_type_is_struct(const struct btf_type *t)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun u8 kind = BTF_INFO_KIND(t->info);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun return kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
btf_type_vlen(const struct btf_type * t)168*4882a593Smuzhiyun static inline u16 btf_type_vlen(const struct btf_type *t)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun return BTF_INFO_VLEN(t->info);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
btf_func_linkage(const struct btf_type * t)173*4882a593Smuzhiyun static inline u16 btf_func_linkage(const struct btf_type *t)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun return BTF_INFO_VLEN(t->info);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
btf_type_kflag(const struct btf_type * t)178*4882a593Smuzhiyun static inline bool btf_type_kflag(const struct btf_type *t)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun return BTF_INFO_KFLAG(t->info);
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
btf_member_bit_offset(const struct btf_type * struct_type,const struct btf_member * member)183*4882a593Smuzhiyun static inline u32 btf_member_bit_offset(const struct btf_type *struct_type,
184*4882a593Smuzhiyun const struct btf_member *member)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun return btf_type_kflag(struct_type) ? BTF_MEMBER_BIT_OFFSET(member->offset)
187*4882a593Smuzhiyun : member->offset;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
btf_member_bitfield_size(const struct btf_type * struct_type,const struct btf_member * member)190*4882a593Smuzhiyun static inline u32 btf_member_bitfield_size(const struct btf_type *struct_type,
191*4882a593Smuzhiyun const struct btf_member *member)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun return btf_type_kflag(struct_type) ? BTF_MEMBER_BITFIELD_SIZE(member->offset)
194*4882a593Smuzhiyun : 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
btf_type_member(const struct btf_type * t)197*4882a593Smuzhiyun static inline const struct btf_member *btf_type_member(const struct btf_type *t)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun return (const struct btf_member *)(t + 1);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
btf_type_var_secinfo(const struct btf_type * t)202*4882a593Smuzhiyun static inline const struct btf_var_secinfo *btf_type_var_secinfo(
203*4882a593Smuzhiyun const struct btf_type *t)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun return (const struct btf_var_secinfo *)(t + 1);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun #ifdef CONFIG_BPF_SYSCALL
209*4882a593Smuzhiyun const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
210*4882a593Smuzhiyun const char *btf_name_by_offset(const struct btf *btf, u32 offset);
211*4882a593Smuzhiyun struct btf *btf_parse_vmlinux(void);
212*4882a593Smuzhiyun struct btf *bpf_prog_get_target_btf(const struct bpf_prog *prog);
213*4882a593Smuzhiyun #else
btf_type_by_id(const struct btf * btf,u32 type_id)214*4882a593Smuzhiyun static inline const struct btf_type *btf_type_by_id(const struct btf *btf,
215*4882a593Smuzhiyun u32 type_id)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun return NULL;
218*4882a593Smuzhiyun }
btf_name_by_offset(const struct btf * btf,u32 offset)219*4882a593Smuzhiyun static inline const char *btf_name_by_offset(const struct btf *btf,
220*4882a593Smuzhiyun u32 offset)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun return NULL;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun #endif
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun #endif
227