xref: /aosp_15_r20/external/libbpf/src/btf.c (revision f7c14bbac8cf49633f2740db462ea43457973ec4)
1*f7c14bbaSAndroid Build Coastguard Worker // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2*f7c14bbaSAndroid Build Coastguard Worker /* Copyright (c) 2018 Facebook */
3*f7c14bbaSAndroid Build Coastguard Worker 
4*f7c14bbaSAndroid Build Coastguard Worker #include <byteswap.h>
5*f7c14bbaSAndroid Build Coastguard Worker #include <endian.h>
6*f7c14bbaSAndroid Build Coastguard Worker #include <stdio.h>
7*f7c14bbaSAndroid Build Coastguard Worker #include <stdlib.h>
8*f7c14bbaSAndroid Build Coastguard Worker #include <string.h>
9*f7c14bbaSAndroid Build Coastguard Worker #include <fcntl.h>
10*f7c14bbaSAndroid Build Coastguard Worker #include <unistd.h>
11*f7c14bbaSAndroid Build Coastguard Worker #include <errno.h>
12*f7c14bbaSAndroid Build Coastguard Worker #include <sys/utsname.h>
13*f7c14bbaSAndroid Build Coastguard Worker #include <sys/param.h>
14*f7c14bbaSAndroid Build Coastguard Worker #include <sys/stat.h>
15*f7c14bbaSAndroid Build Coastguard Worker #include <linux/kernel.h>
16*f7c14bbaSAndroid Build Coastguard Worker #include <linux/err.h>
17*f7c14bbaSAndroid Build Coastguard Worker #include <linux/btf.h>
18*f7c14bbaSAndroid Build Coastguard Worker #include <gelf.h>
19*f7c14bbaSAndroid Build Coastguard Worker #include "btf.h"
20*f7c14bbaSAndroid Build Coastguard Worker #include "bpf.h"
21*f7c14bbaSAndroid Build Coastguard Worker #include "libbpf.h"
22*f7c14bbaSAndroid Build Coastguard Worker #include "libbpf_internal.h"
23*f7c14bbaSAndroid Build Coastguard Worker #include "hashmap.h"
24*f7c14bbaSAndroid Build Coastguard Worker #include "strset.h"
25*f7c14bbaSAndroid Build Coastguard Worker 
26*f7c14bbaSAndroid Build Coastguard Worker #define BTF_MAX_NR_TYPES 0x7fffffffU
27*f7c14bbaSAndroid Build Coastguard Worker #define BTF_MAX_STR_OFFSET 0x7fffffffU
28*f7c14bbaSAndroid Build Coastguard Worker 
29*f7c14bbaSAndroid Build Coastguard Worker static struct btf_type btf_void;
30*f7c14bbaSAndroid Build Coastguard Worker 
31*f7c14bbaSAndroid Build Coastguard Worker struct btf {
32*f7c14bbaSAndroid Build Coastguard Worker 	/* raw BTF data in native endianness */
33*f7c14bbaSAndroid Build Coastguard Worker 	void *raw_data;
34*f7c14bbaSAndroid Build Coastguard Worker 	/* raw BTF data in non-native endianness */
35*f7c14bbaSAndroid Build Coastguard Worker 	void *raw_data_swapped;
36*f7c14bbaSAndroid Build Coastguard Worker 	__u32 raw_size;
37*f7c14bbaSAndroid Build Coastguard Worker 	/* whether target endianness differs from the native one */
38*f7c14bbaSAndroid Build Coastguard Worker 	bool swapped_endian;
39*f7c14bbaSAndroid Build Coastguard Worker 
40*f7c14bbaSAndroid Build Coastguard Worker 	/*
41*f7c14bbaSAndroid Build Coastguard Worker 	 * When BTF is loaded from an ELF or raw memory it is stored
42*f7c14bbaSAndroid Build Coastguard Worker 	 * in a contiguous memory block. The hdr, type_data, and, strs_data
43*f7c14bbaSAndroid Build Coastguard Worker 	 * point inside that memory region to their respective parts of BTF
44*f7c14bbaSAndroid Build Coastguard Worker 	 * representation:
45*f7c14bbaSAndroid Build Coastguard Worker 	 *
46*f7c14bbaSAndroid Build Coastguard Worker 	 * +--------------------------------+
47*f7c14bbaSAndroid Build Coastguard Worker 	 * |  Header  |  Types  |  Strings  |
48*f7c14bbaSAndroid Build Coastguard Worker 	 * +--------------------------------+
49*f7c14bbaSAndroid Build Coastguard Worker 	 * ^          ^         ^
50*f7c14bbaSAndroid Build Coastguard Worker 	 * |          |         |
51*f7c14bbaSAndroid Build Coastguard Worker 	 * hdr        |         |
52*f7c14bbaSAndroid Build Coastguard Worker 	 * types_data-+         |
53*f7c14bbaSAndroid Build Coastguard Worker 	 * strs_data------------+
54*f7c14bbaSAndroid Build Coastguard Worker 	 *
55*f7c14bbaSAndroid Build Coastguard Worker 	 * If BTF data is later modified, e.g., due to types added or
56*f7c14bbaSAndroid Build Coastguard Worker 	 * removed, BTF deduplication performed, etc, this contiguous
57*f7c14bbaSAndroid Build Coastguard Worker 	 * representation is broken up into three independently allocated
58*f7c14bbaSAndroid Build Coastguard Worker 	 * memory regions to be able to modify them independently.
59*f7c14bbaSAndroid Build Coastguard Worker 	 * raw_data is nulled out at that point, but can be later allocated
60*f7c14bbaSAndroid Build Coastguard Worker 	 * and cached again if user calls btf__raw_data(), at which point
61*f7c14bbaSAndroid Build Coastguard Worker 	 * raw_data will contain a contiguous copy of header, types, and
62*f7c14bbaSAndroid Build Coastguard Worker 	 * strings:
63*f7c14bbaSAndroid Build Coastguard Worker 	 *
64*f7c14bbaSAndroid Build Coastguard Worker 	 * +----------+  +---------+  +-----------+
65*f7c14bbaSAndroid Build Coastguard Worker 	 * |  Header  |  |  Types  |  |  Strings  |
66*f7c14bbaSAndroid Build Coastguard Worker 	 * +----------+  +---------+  +-----------+
67*f7c14bbaSAndroid Build Coastguard Worker 	 * ^             ^            ^
68*f7c14bbaSAndroid Build Coastguard Worker 	 * |             |            |
69*f7c14bbaSAndroid Build Coastguard Worker 	 * hdr           |            |
70*f7c14bbaSAndroid Build Coastguard Worker 	 * types_data----+            |
71*f7c14bbaSAndroid Build Coastguard Worker 	 * strset__data(strs_set)-----+
72*f7c14bbaSAndroid Build Coastguard Worker 	 *
73*f7c14bbaSAndroid Build Coastguard Worker 	 *               +----------+---------+-----------+
74*f7c14bbaSAndroid Build Coastguard Worker 	 *               |  Header  |  Types  |  Strings  |
75*f7c14bbaSAndroid Build Coastguard Worker 	 * raw_data----->+----------+---------+-----------+
76*f7c14bbaSAndroid Build Coastguard Worker 	 */
77*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_header *hdr;
78*f7c14bbaSAndroid Build Coastguard Worker 
79*f7c14bbaSAndroid Build Coastguard Worker 	void *types_data;
80*f7c14bbaSAndroid Build Coastguard Worker 	size_t types_data_cap; /* used size stored in hdr->type_len */
81*f7c14bbaSAndroid Build Coastguard Worker 
82*f7c14bbaSAndroid Build Coastguard Worker 	/* type ID to `struct btf_type *` lookup index
83*f7c14bbaSAndroid Build Coastguard Worker 	 * type_offs[0] corresponds to the first non-VOID type:
84*f7c14bbaSAndroid Build Coastguard Worker 	 *   - for base BTF it's type [1];
85*f7c14bbaSAndroid Build Coastguard Worker 	 *   - for split BTF it's the first non-base BTF type.
86*f7c14bbaSAndroid Build Coastguard Worker 	 */
87*f7c14bbaSAndroid Build Coastguard Worker 	__u32 *type_offs;
88*f7c14bbaSAndroid Build Coastguard Worker 	size_t type_offs_cap;
89*f7c14bbaSAndroid Build Coastguard Worker 	/* number of types in this BTF instance:
90*f7c14bbaSAndroid Build Coastguard Worker 	 *   - doesn't include special [0] void type;
91*f7c14bbaSAndroid Build Coastguard Worker 	 *   - for split BTF counts number of types added on top of base BTF.
92*f7c14bbaSAndroid Build Coastguard Worker 	 */
93*f7c14bbaSAndroid Build Coastguard Worker 	__u32 nr_types;
94*f7c14bbaSAndroid Build Coastguard Worker 	/* if not NULL, points to the base BTF on top of which the current
95*f7c14bbaSAndroid Build Coastguard Worker 	 * split BTF is based
96*f7c14bbaSAndroid Build Coastguard Worker 	 */
97*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *base_btf;
98*f7c14bbaSAndroid Build Coastguard Worker 	/* BTF type ID of the first type in this BTF instance:
99*f7c14bbaSAndroid Build Coastguard Worker 	 *   - for base BTF it's equal to 1;
100*f7c14bbaSAndroid Build Coastguard Worker 	 *   - for split BTF it's equal to biggest type ID of base BTF plus 1.
101*f7c14bbaSAndroid Build Coastguard Worker 	 */
102*f7c14bbaSAndroid Build Coastguard Worker 	int start_id;
103*f7c14bbaSAndroid Build Coastguard Worker 	/* logical string offset of this BTF instance:
104*f7c14bbaSAndroid Build Coastguard Worker 	 *   - for base BTF it's equal to 0;
105*f7c14bbaSAndroid Build Coastguard Worker 	 *   - for split BTF it's equal to total size of base BTF's string section size.
106*f7c14bbaSAndroid Build Coastguard Worker 	 */
107*f7c14bbaSAndroid Build Coastguard Worker 	int start_str_off;
108*f7c14bbaSAndroid Build Coastguard Worker 
109*f7c14bbaSAndroid Build Coastguard Worker 	/* only one of strs_data or strs_set can be non-NULL, depending on
110*f7c14bbaSAndroid Build Coastguard Worker 	 * whether BTF is in a modifiable state (strs_set is used) or not
111*f7c14bbaSAndroid Build Coastguard Worker 	 * (strs_data points inside raw_data)
112*f7c14bbaSAndroid Build Coastguard Worker 	 */
113*f7c14bbaSAndroid Build Coastguard Worker 	void *strs_data;
114*f7c14bbaSAndroid Build Coastguard Worker 	/* a set of unique strings */
115*f7c14bbaSAndroid Build Coastguard Worker 	struct strset *strs_set;
116*f7c14bbaSAndroid Build Coastguard Worker 	/* whether strings are already deduplicated */
117*f7c14bbaSAndroid Build Coastguard Worker 	bool strs_deduped;
118*f7c14bbaSAndroid Build Coastguard Worker 
119*f7c14bbaSAndroid Build Coastguard Worker 	/* BTF object FD, if loaded into kernel */
120*f7c14bbaSAndroid Build Coastguard Worker 	int fd;
121*f7c14bbaSAndroid Build Coastguard Worker 
122*f7c14bbaSAndroid Build Coastguard Worker 	/* Pointer size (in bytes) for a target architecture of this BTF */
123*f7c14bbaSAndroid Build Coastguard Worker 	int ptr_sz;
124*f7c14bbaSAndroid Build Coastguard Worker };
125*f7c14bbaSAndroid Build Coastguard Worker 
ptr_to_u64(const void * ptr)126*f7c14bbaSAndroid Build Coastguard Worker static inline __u64 ptr_to_u64(const void *ptr)
127*f7c14bbaSAndroid Build Coastguard Worker {
128*f7c14bbaSAndroid Build Coastguard Worker 	return (__u64) (unsigned long) ptr;
129*f7c14bbaSAndroid Build Coastguard Worker }
130*f7c14bbaSAndroid Build Coastguard Worker 
131*f7c14bbaSAndroid Build Coastguard Worker /* Ensure given dynamically allocated memory region pointed to by *data* with
132*f7c14bbaSAndroid Build Coastguard Worker  * capacity of *cap_cnt* elements each taking *elem_sz* bytes has enough
133*f7c14bbaSAndroid Build Coastguard Worker  * memory to accommodate *add_cnt* new elements, assuming *cur_cnt* elements
134*f7c14bbaSAndroid Build Coastguard Worker  * are already used. At most *max_cnt* elements can be ever allocated.
135*f7c14bbaSAndroid Build Coastguard Worker  * If necessary, memory is reallocated and all existing data is copied over,
136*f7c14bbaSAndroid Build Coastguard Worker  * new pointer to the memory region is stored at *data, new memory region
137*f7c14bbaSAndroid Build Coastguard Worker  * capacity (in number of elements) is stored in *cap.
138*f7c14bbaSAndroid Build Coastguard Worker  * On success, memory pointer to the beginning of unused memory is returned.
139*f7c14bbaSAndroid Build Coastguard Worker  * On error, NULL is returned.
140*f7c14bbaSAndroid Build Coastguard Worker  */
libbpf_add_mem(void ** data,size_t * cap_cnt,size_t elem_sz,size_t cur_cnt,size_t max_cnt,size_t add_cnt)141*f7c14bbaSAndroid Build Coastguard Worker void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
142*f7c14bbaSAndroid Build Coastguard Worker 		     size_t cur_cnt, size_t max_cnt, size_t add_cnt)
143*f7c14bbaSAndroid Build Coastguard Worker {
144*f7c14bbaSAndroid Build Coastguard Worker 	size_t new_cnt;
145*f7c14bbaSAndroid Build Coastguard Worker 	void *new_data;
146*f7c14bbaSAndroid Build Coastguard Worker 
147*f7c14bbaSAndroid Build Coastguard Worker 	if (cur_cnt + add_cnt <= *cap_cnt)
148*f7c14bbaSAndroid Build Coastguard Worker 		return *data + cur_cnt * elem_sz;
149*f7c14bbaSAndroid Build Coastguard Worker 
150*f7c14bbaSAndroid Build Coastguard Worker 	/* requested more than the set limit */
151*f7c14bbaSAndroid Build Coastguard Worker 	if (cur_cnt + add_cnt > max_cnt)
152*f7c14bbaSAndroid Build Coastguard Worker 		return NULL;
153*f7c14bbaSAndroid Build Coastguard Worker 
154*f7c14bbaSAndroid Build Coastguard Worker 	new_cnt = *cap_cnt;
155*f7c14bbaSAndroid Build Coastguard Worker 	new_cnt += new_cnt / 4;		  /* expand by 25% */
156*f7c14bbaSAndroid Build Coastguard Worker 	if (new_cnt < 16)		  /* but at least 16 elements */
157*f7c14bbaSAndroid Build Coastguard Worker 		new_cnt = 16;
158*f7c14bbaSAndroid Build Coastguard Worker 	if (new_cnt > max_cnt)		  /* but not exceeding a set limit */
159*f7c14bbaSAndroid Build Coastguard Worker 		new_cnt = max_cnt;
160*f7c14bbaSAndroid Build Coastguard Worker 	if (new_cnt < cur_cnt + add_cnt)  /* also ensure we have enough memory */
161*f7c14bbaSAndroid Build Coastguard Worker 		new_cnt = cur_cnt + add_cnt;
162*f7c14bbaSAndroid Build Coastguard Worker 
163*f7c14bbaSAndroid Build Coastguard Worker 	new_data = libbpf_reallocarray(*data, new_cnt, elem_sz);
164*f7c14bbaSAndroid Build Coastguard Worker 	if (!new_data)
165*f7c14bbaSAndroid Build Coastguard Worker 		return NULL;
166*f7c14bbaSAndroid Build Coastguard Worker 
167*f7c14bbaSAndroid Build Coastguard Worker 	/* zero out newly allocated portion of memory */
168*f7c14bbaSAndroid Build Coastguard Worker 	memset(new_data + (*cap_cnt) * elem_sz, 0, (new_cnt - *cap_cnt) * elem_sz);
169*f7c14bbaSAndroid Build Coastguard Worker 
170*f7c14bbaSAndroid Build Coastguard Worker 	*data = new_data;
171*f7c14bbaSAndroid Build Coastguard Worker 	*cap_cnt = new_cnt;
172*f7c14bbaSAndroid Build Coastguard Worker 	return new_data + cur_cnt * elem_sz;
173*f7c14bbaSAndroid Build Coastguard Worker }
174*f7c14bbaSAndroid Build Coastguard Worker 
175*f7c14bbaSAndroid Build Coastguard Worker /* Ensure given dynamically allocated memory region has enough allocated space
176*f7c14bbaSAndroid Build Coastguard Worker  * to accommodate *need_cnt* elements of size *elem_sz* bytes each
177*f7c14bbaSAndroid Build Coastguard Worker  */
libbpf_ensure_mem(void ** data,size_t * cap_cnt,size_t elem_sz,size_t need_cnt)178*f7c14bbaSAndroid Build Coastguard Worker int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt)
179*f7c14bbaSAndroid Build Coastguard Worker {
180*f7c14bbaSAndroid Build Coastguard Worker 	void *p;
181*f7c14bbaSAndroid Build Coastguard Worker 
182*f7c14bbaSAndroid Build Coastguard Worker 	if (need_cnt <= *cap_cnt)
183*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
184*f7c14bbaSAndroid Build Coastguard Worker 
185*f7c14bbaSAndroid Build Coastguard Worker 	p = libbpf_add_mem(data, cap_cnt, elem_sz, *cap_cnt, SIZE_MAX, need_cnt - *cap_cnt);
186*f7c14bbaSAndroid Build Coastguard Worker 	if (!p)
187*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOMEM;
188*f7c14bbaSAndroid Build Coastguard Worker 
189*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
190*f7c14bbaSAndroid Build Coastguard Worker }
191*f7c14bbaSAndroid Build Coastguard Worker 
btf_add_type_offs_mem(struct btf * btf,size_t add_cnt)192*f7c14bbaSAndroid Build Coastguard Worker static void *btf_add_type_offs_mem(struct btf *btf, size_t add_cnt)
193*f7c14bbaSAndroid Build Coastguard Worker {
194*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_add_mem((void **)&btf->type_offs, &btf->type_offs_cap, sizeof(__u32),
195*f7c14bbaSAndroid Build Coastguard Worker 			      btf->nr_types, BTF_MAX_NR_TYPES, add_cnt);
196*f7c14bbaSAndroid Build Coastguard Worker }
197*f7c14bbaSAndroid Build Coastguard Worker 
btf_add_type_idx_entry(struct btf * btf,__u32 type_off)198*f7c14bbaSAndroid Build Coastguard Worker static int btf_add_type_idx_entry(struct btf *btf, __u32 type_off)
199*f7c14bbaSAndroid Build Coastguard Worker {
200*f7c14bbaSAndroid Build Coastguard Worker 	__u32 *p;
201*f7c14bbaSAndroid Build Coastguard Worker 
202*f7c14bbaSAndroid Build Coastguard Worker 	p = btf_add_type_offs_mem(btf, 1);
203*f7c14bbaSAndroid Build Coastguard Worker 	if (!p)
204*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOMEM;
205*f7c14bbaSAndroid Build Coastguard Worker 
206*f7c14bbaSAndroid Build Coastguard Worker 	*p = type_off;
207*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
208*f7c14bbaSAndroid Build Coastguard Worker }
209*f7c14bbaSAndroid Build Coastguard Worker 
btf_bswap_hdr(struct btf_header * h)210*f7c14bbaSAndroid Build Coastguard Worker static void btf_bswap_hdr(struct btf_header *h)
211*f7c14bbaSAndroid Build Coastguard Worker {
212*f7c14bbaSAndroid Build Coastguard Worker 	h->magic = bswap_16(h->magic);
213*f7c14bbaSAndroid Build Coastguard Worker 	h->hdr_len = bswap_32(h->hdr_len);
214*f7c14bbaSAndroid Build Coastguard Worker 	h->type_off = bswap_32(h->type_off);
215*f7c14bbaSAndroid Build Coastguard Worker 	h->type_len = bswap_32(h->type_len);
216*f7c14bbaSAndroid Build Coastguard Worker 	h->str_off = bswap_32(h->str_off);
217*f7c14bbaSAndroid Build Coastguard Worker 	h->str_len = bswap_32(h->str_len);
218*f7c14bbaSAndroid Build Coastguard Worker }
219*f7c14bbaSAndroid Build Coastguard Worker 
btf_parse_hdr(struct btf * btf)220*f7c14bbaSAndroid Build Coastguard Worker static int btf_parse_hdr(struct btf *btf)
221*f7c14bbaSAndroid Build Coastguard Worker {
222*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_header *hdr = btf->hdr;
223*f7c14bbaSAndroid Build Coastguard Worker 	__u32 meta_left;
224*f7c14bbaSAndroid Build Coastguard Worker 
225*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->raw_size < sizeof(struct btf_header)) {
226*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("BTF header not found\n");
227*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
228*f7c14bbaSAndroid Build Coastguard Worker 	}
229*f7c14bbaSAndroid Build Coastguard Worker 
230*f7c14bbaSAndroid Build Coastguard Worker 	if (hdr->magic == bswap_16(BTF_MAGIC)) {
231*f7c14bbaSAndroid Build Coastguard Worker 		btf->swapped_endian = true;
232*f7c14bbaSAndroid Build Coastguard Worker 		if (bswap_32(hdr->hdr_len) != sizeof(struct btf_header)) {
233*f7c14bbaSAndroid Build Coastguard Worker 			pr_warn("Can't load BTF with non-native endianness due to unsupported header length %u\n",
234*f7c14bbaSAndroid Build Coastguard Worker 				bswap_32(hdr->hdr_len));
235*f7c14bbaSAndroid Build Coastguard Worker 			return -ENOTSUP;
236*f7c14bbaSAndroid Build Coastguard Worker 		}
237*f7c14bbaSAndroid Build Coastguard Worker 		btf_bswap_hdr(hdr);
238*f7c14bbaSAndroid Build Coastguard Worker 	} else if (hdr->magic != BTF_MAGIC) {
239*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Invalid BTF magic: %x\n", hdr->magic);
240*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
241*f7c14bbaSAndroid Build Coastguard Worker 	}
242*f7c14bbaSAndroid Build Coastguard Worker 
243*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->raw_size < hdr->hdr_len) {
244*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("BTF header len %u larger than data size %u\n",
245*f7c14bbaSAndroid Build Coastguard Worker 			 hdr->hdr_len, btf->raw_size);
246*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
247*f7c14bbaSAndroid Build Coastguard Worker 	}
248*f7c14bbaSAndroid Build Coastguard Worker 
249*f7c14bbaSAndroid Build Coastguard Worker 	meta_left = btf->raw_size - hdr->hdr_len;
250*f7c14bbaSAndroid Build Coastguard Worker 	if (meta_left < (long long)hdr->str_off + hdr->str_len) {
251*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Invalid BTF total size: %u\n", btf->raw_size);
252*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
253*f7c14bbaSAndroid Build Coastguard Worker 	}
254*f7c14bbaSAndroid Build Coastguard Worker 
255*f7c14bbaSAndroid Build Coastguard Worker 	if ((long long)hdr->type_off + hdr->type_len > hdr->str_off) {
256*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Invalid BTF data sections layout: type data at %u + %u, strings data at %u + %u\n",
257*f7c14bbaSAndroid Build Coastguard Worker 			 hdr->type_off, hdr->type_len, hdr->str_off, hdr->str_len);
258*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
259*f7c14bbaSAndroid Build Coastguard Worker 	}
260*f7c14bbaSAndroid Build Coastguard Worker 
261*f7c14bbaSAndroid Build Coastguard Worker 	if (hdr->type_off % 4) {
262*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("BTF type section is not aligned to 4 bytes\n");
263*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
264*f7c14bbaSAndroid Build Coastguard Worker 	}
265*f7c14bbaSAndroid Build Coastguard Worker 
266*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
267*f7c14bbaSAndroid Build Coastguard Worker }
268*f7c14bbaSAndroid Build Coastguard Worker 
btf_parse_str_sec(struct btf * btf)269*f7c14bbaSAndroid Build Coastguard Worker static int btf_parse_str_sec(struct btf *btf)
270*f7c14bbaSAndroid Build Coastguard Worker {
271*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_header *hdr = btf->hdr;
272*f7c14bbaSAndroid Build Coastguard Worker 	const char *start = btf->strs_data;
273*f7c14bbaSAndroid Build Coastguard Worker 	const char *end = start + btf->hdr->str_len;
274*f7c14bbaSAndroid Build Coastguard Worker 
275*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->base_btf && hdr->str_len == 0)
276*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
277*f7c14bbaSAndroid Build Coastguard Worker 	if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_STR_OFFSET || end[-1]) {
278*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Invalid BTF string section\n");
279*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
280*f7c14bbaSAndroid Build Coastguard Worker 	}
281*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf->base_btf && start[0]) {
282*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Invalid BTF string section\n");
283*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
284*f7c14bbaSAndroid Build Coastguard Worker 	}
285*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
286*f7c14bbaSAndroid Build Coastguard Worker }
287*f7c14bbaSAndroid Build Coastguard Worker 
btf_type_size(const struct btf_type * t)288*f7c14bbaSAndroid Build Coastguard Worker static int btf_type_size(const struct btf_type *t)
289*f7c14bbaSAndroid Build Coastguard Worker {
290*f7c14bbaSAndroid Build Coastguard Worker 	const int base_size = sizeof(struct btf_type);
291*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen = btf_vlen(t);
292*f7c14bbaSAndroid Build Coastguard Worker 
293*f7c14bbaSAndroid Build Coastguard Worker 	switch (btf_kind(t)) {
294*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FWD:
295*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
296*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
297*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
298*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
299*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
300*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC:
301*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FLOAT:
302*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
303*f7c14bbaSAndroid Build Coastguard Worker 		return base_size;
304*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_INT:
305*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + sizeof(__u32);
306*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM:
307*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + vlen * sizeof(struct btf_enum);
308*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64:
309*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + vlen * sizeof(struct btf_enum64);
310*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY:
311*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + sizeof(struct btf_array);
312*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
313*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION:
314*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + vlen * sizeof(struct btf_member);
315*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO:
316*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + vlen * sizeof(struct btf_param);
317*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VAR:
318*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + sizeof(struct btf_var);
319*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DATASEC:
320*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + vlen * sizeof(struct btf_var_secinfo);
321*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DECL_TAG:
322*f7c14bbaSAndroid Build Coastguard Worker 		return base_size + sizeof(struct btf_decl_tag);
323*f7c14bbaSAndroid Build Coastguard Worker 	default:
324*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Unsupported BTF_KIND:%u\n", btf_kind(t));
325*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
326*f7c14bbaSAndroid Build Coastguard Worker 	}
327*f7c14bbaSAndroid Build Coastguard Worker }
328*f7c14bbaSAndroid Build Coastguard Worker 
btf_bswap_type_base(struct btf_type * t)329*f7c14bbaSAndroid Build Coastguard Worker static void btf_bswap_type_base(struct btf_type *t)
330*f7c14bbaSAndroid Build Coastguard Worker {
331*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = bswap_32(t->name_off);
332*f7c14bbaSAndroid Build Coastguard Worker 	t->info = bswap_32(t->info);
333*f7c14bbaSAndroid Build Coastguard Worker 	t->type = bswap_32(t->type);
334*f7c14bbaSAndroid Build Coastguard Worker }
335*f7c14bbaSAndroid Build Coastguard Worker 
btf_bswap_type_rest(struct btf_type * t)336*f7c14bbaSAndroid Build Coastguard Worker static int btf_bswap_type_rest(struct btf_type *t)
337*f7c14bbaSAndroid Build Coastguard Worker {
338*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_var_secinfo *v;
339*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_enum64 *e64;
340*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_member *m;
341*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_array *a;
342*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_param *p;
343*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_enum *e;
344*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen = btf_vlen(t);
345*f7c14bbaSAndroid Build Coastguard Worker 	int i;
346*f7c14bbaSAndroid Build Coastguard Worker 
347*f7c14bbaSAndroid Build Coastguard Worker 	switch (btf_kind(t)) {
348*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FWD:
349*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
350*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
351*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
352*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
353*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
354*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC:
355*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FLOAT:
356*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
357*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
358*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_INT:
359*f7c14bbaSAndroid Build Coastguard Worker 		*(__u32 *)(t + 1) = bswap_32(*(__u32 *)(t + 1));
360*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
361*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM:
362*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, e = btf_enum(t); i < vlen; i++, e++) {
363*f7c14bbaSAndroid Build Coastguard Worker 			e->name_off = bswap_32(e->name_off);
364*f7c14bbaSAndroid Build Coastguard Worker 			e->val = bswap_32(e->val);
365*f7c14bbaSAndroid Build Coastguard Worker 		}
366*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
367*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64:
368*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, e64 = btf_enum64(t); i < vlen; i++, e64++) {
369*f7c14bbaSAndroid Build Coastguard Worker 			e64->name_off = bswap_32(e64->name_off);
370*f7c14bbaSAndroid Build Coastguard Worker 			e64->val_lo32 = bswap_32(e64->val_lo32);
371*f7c14bbaSAndroid Build Coastguard Worker 			e64->val_hi32 = bswap_32(e64->val_hi32);
372*f7c14bbaSAndroid Build Coastguard Worker 		}
373*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
374*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY:
375*f7c14bbaSAndroid Build Coastguard Worker 		a = btf_array(t);
376*f7c14bbaSAndroid Build Coastguard Worker 		a->type = bswap_32(a->type);
377*f7c14bbaSAndroid Build Coastguard Worker 		a->index_type = bswap_32(a->index_type);
378*f7c14bbaSAndroid Build Coastguard Worker 		a->nelems = bswap_32(a->nelems);
379*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
380*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
381*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION:
382*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, m = btf_members(t); i < vlen; i++, m++) {
383*f7c14bbaSAndroid Build Coastguard Worker 			m->name_off = bswap_32(m->name_off);
384*f7c14bbaSAndroid Build Coastguard Worker 			m->type = bswap_32(m->type);
385*f7c14bbaSAndroid Build Coastguard Worker 			m->offset = bswap_32(m->offset);
386*f7c14bbaSAndroid Build Coastguard Worker 		}
387*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
388*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO:
389*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, p = btf_params(t); i < vlen; i++, p++) {
390*f7c14bbaSAndroid Build Coastguard Worker 			p->name_off = bswap_32(p->name_off);
391*f7c14bbaSAndroid Build Coastguard Worker 			p->type = bswap_32(p->type);
392*f7c14bbaSAndroid Build Coastguard Worker 		}
393*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
394*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VAR:
395*f7c14bbaSAndroid Build Coastguard Worker 		btf_var(t)->linkage = bswap_32(btf_var(t)->linkage);
396*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
397*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DATASEC:
398*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, v = btf_var_secinfos(t); i < vlen; i++, v++) {
399*f7c14bbaSAndroid Build Coastguard Worker 			v->type = bswap_32(v->type);
400*f7c14bbaSAndroid Build Coastguard Worker 			v->offset = bswap_32(v->offset);
401*f7c14bbaSAndroid Build Coastguard Worker 			v->size = bswap_32(v->size);
402*f7c14bbaSAndroid Build Coastguard Worker 		}
403*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
404*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DECL_TAG:
405*f7c14bbaSAndroid Build Coastguard Worker 		btf_decl_tag(t)->component_idx = bswap_32(btf_decl_tag(t)->component_idx);
406*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
407*f7c14bbaSAndroid Build Coastguard Worker 	default:
408*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Unsupported BTF_KIND:%u\n", btf_kind(t));
409*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
410*f7c14bbaSAndroid Build Coastguard Worker 	}
411*f7c14bbaSAndroid Build Coastguard Worker }
412*f7c14bbaSAndroid Build Coastguard Worker 
btf_parse_type_sec(struct btf * btf)413*f7c14bbaSAndroid Build Coastguard Worker static int btf_parse_type_sec(struct btf *btf)
414*f7c14bbaSAndroid Build Coastguard Worker {
415*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_header *hdr = btf->hdr;
416*f7c14bbaSAndroid Build Coastguard Worker 	void *next_type = btf->types_data;
417*f7c14bbaSAndroid Build Coastguard Worker 	void *end_type = next_type + hdr->type_len;
418*f7c14bbaSAndroid Build Coastguard Worker 	int err, type_size;
419*f7c14bbaSAndroid Build Coastguard Worker 
420*f7c14bbaSAndroid Build Coastguard Worker 	while (next_type + sizeof(struct btf_type) <= end_type) {
421*f7c14bbaSAndroid Build Coastguard Worker 		if (btf->swapped_endian)
422*f7c14bbaSAndroid Build Coastguard Worker 			btf_bswap_type_base(next_type);
423*f7c14bbaSAndroid Build Coastguard Worker 
424*f7c14bbaSAndroid Build Coastguard Worker 		type_size = btf_type_size(next_type);
425*f7c14bbaSAndroid Build Coastguard Worker 		if (type_size < 0)
426*f7c14bbaSAndroid Build Coastguard Worker 			return type_size;
427*f7c14bbaSAndroid Build Coastguard Worker 		if (next_type + type_size > end_type) {
428*f7c14bbaSAndroid Build Coastguard Worker 			pr_warn("BTF type [%d] is malformed\n", btf->start_id + btf->nr_types);
429*f7c14bbaSAndroid Build Coastguard Worker 			return -EINVAL;
430*f7c14bbaSAndroid Build Coastguard Worker 		}
431*f7c14bbaSAndroid Build Coastguard Worker 
432*f7c14bbaSAndroid Build Coastguard Worker 		if (btf->swapped_endian && btf_bswap_type_rest(next_type))
433*f7c14bbaSAndroid Build Coastguard Worker 			return -EINVAL;
434*f7c14bbaSAndroid Build Coastguard Worker 
435*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_add_type_idx_entry(btf, next_type - btf->types_data);
436*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
437*f7c14bbaSAndroid Build Coastguard Worker 			return err;
438*f7c14bbaSAndroid Build Coastguard Worker 
439*f7c14bbaSAndroid Build Coastguard Worker 		next_type += type_size;
440*f7c14bbaSAndroid Build Coastguard Worker 		btf->nr_types++;
441*f7c14bbaSAndroid Build Coastguard Worker 	}
442*f7c14bbaSAndroid Build Coastguard Worker 
443*f7c14bbaSAndroid Build Coastguard Worker 	if (next_type != end_type) {
444*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("BTF types data is malformed\n");
445*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
446*f7c14bbaSAndroid Build Coastguard Worker 	}
447*f7c14bbaSAndroid Build Coastguard Worker 
448*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
449*f7c14bbaSAndroid Build Coastguard Worker }
450*f7c14bbaSAndroid Build Coastguard Worker 
btf_validate_str(const struct btf * btf,__u32 str_off,const char * what,__u32 type_id)451*f7c14bbaSAndroid Build Coastguard Worker static int btf_validate_str(const struct btf *btf, __u32 str_off, const char *what, __u32 type_id)
452*f7c14bbaSAndroid Build Coastguard Worker {
453*f7c14bbaSAndroid Build Coastguard Worker 	const char *s;
454*f7c14bbaSAndroid Build Coastguard Worker 
455*f7c14bbaSAndroid Build Coastguard Worker 	s = btf__str_by_offset(btf, str_off);
456*f7c14bbaSAndroid Build Coastguard Worker 	if (!s) {
457*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("btf: type [%u]: invalid %s (string offset %u)\n", type_id, what, str_off);
458*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
459*f7c14bbaSAndroid Build Coastguard Worker 	}
460*f7c14bbaSAndroid Build Coastguard Worker 
461*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
462*f7c14bbaSAndroid Build Coastguard Worker }
463*f7c14bbaSAndroid Build Coastguard Worker 
btf_validate_id(const struct btf * btf,__u32 id,__u32 ctx_id)464*f7c14bbaSAndroid Build Coastguard Worker static int btf_validate_id(const struct btf *btf, __u32 id, __u32 ctx_id)
465*f7c14bbaSAndroid Build Coastguard Worker {
466*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_type *t;
467*f7c14bbaSAndroid Build Coastguard Worker 
468*f7c14bbaSAndroid Build Coastguard Worker 	t = btf__type_by_id(btf, id);
469*f7c14bbaSAndroid Build Coastguard Worker 	if (!t) {
470*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("btf: type [%u]: invalid referenced type ID %u\n", ctx_id, id);
471*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
472*f7c14bbaSAndroid Build Coastguard Worker 	}
473*f7c14bbaSAndroid Build Coastguard Worker 
474*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
475*f7c14bbaSAndroid Build Coastguard Worker }
476*f7c14bbaSAndroid Build Coastguard Worker 
btf_validate_type(const struct btf * btf,const struct btf_type * t,__u32 id)477*f7c14bbaSAndroid Build Coastguard Worker static int btf_validate_type(const struct btf *btf, const struct btf_type *t, __u32 id)
478*f7c14bbaSAndroid Build Coastguard Worker {
479*f7c14bbaSAndroid Build Coastguard Worker 	__u32 kind = btf_kind(t);
480*f7c14bbaSAndroid Build Coastguard Worker 	int err, i, n;
481*f7c14bbaSAndroid Build Coastguard Worker 
482*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_validate_str(btf, t->name_off, "type name", id);
483*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
484*f7c14bbaSAndroid Build Coastguard Worker 		return err;
485*f7c14bbaSAndroid Build Coastguard Worker 
486*f7c14bbaSAndroid Build Coastguard Worker 	switch (kind) {
487*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNKN:
488*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_INT:
489*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FWD:
490*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FLOAT:
491*f7c14bbaSAndroid Build Coastguard Worker 		break;
492*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
493*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
494*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
495*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
496*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
497*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VAR:
498*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DECL_TAG:
499*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
500*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_validate_id(btf, t->type, id);
501*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
502*f7c14bbaSAndroid Build Coastguard Worker 			return err;
503*f7c14bbaSAndroid Build Coastguard Worker 		break;
504*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY: {
505*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_array *a = btf_array(t);
506*f7c14bbaSAndroid Build Coastguard Worker 
507*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_validate_id(btf, a->type, id);
508*f7c14bbaSAndroid Build Coastguard Worker 		err = err ?: btf_validate_id(btf, a->index_type, id);
509*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
510*f7c14bbaSAndroid Build Coastguard Worker 			return err;
511*f7c14bbaSAndroid Build Coastguard Worker 		break;
512*f7c14bbaSAndroid Build Coastguard Worker 	}
513*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
514*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION: {
515*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_member *m = btf_members(t);
516*f7c14bbaSAndroid Build Coastguard Worker 
517*f7c14bbaSAndroid Build Coastguard Worker 		n = btf_vlen(t);
518*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < n; i++, m++) {
519*f7c14bbaSAndroid Build Coastguard Worker 			err = btf_validate_str(btf, m->name_off, "field name", id);
520*f7c14bbaSAndroid Build Coastguard Worker 			err = err ?: btf_validate_id(btf, m->type, id);
521*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
522*f7c14bbaSAndroid Build Coastguard Worker 				return err;
523*f7c14bbaSAndroid Build Coastguard Worker 		}
524*f7c14bbaSAndroid Build Coastguard Worker 		break;
525*f7c14bbaSAndroid Build Coastguard Worker 	}
526*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM: {
527*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_enum *m = btf_enum(t);
528*f7c14bbaSAndroid Build Coastguard Worker 
529*f7c14bbaSAndroid Build Coastguard Worker 		n = btf_vlen(t);
530*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < n; i++, m++) {
531*f7c14bbaSAndroid Build Coastguard Worker 			err = btf_validate_str(btf, m->name_off, "enum name", id);
532*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
533*f7c14bbaSAndroid Build Coastguard Worker 				return err;
534*f7c14bbaSAndroid Build Coastguard Worker 		}
535*f7c14bbaSAndroid Build Coastguard Worker 		break;
536*f7c14bbaSAndroid Build Coastguard Worker 	}
537*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64: {
538*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_enum64 *m = btf_enum64(t);
539*f7c14bbaSAndroid Build Coastguard Worker 
540*f7c14bbaSAndroid Build Coastguard Worker 		n = btf_vlen(t);
541*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < n; i++, m++) {
542*f7c14bbaSAndroid Build Coastguard Worker 			err = btf_validate_str(btf, m->name_off, "enum name", id);
543*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
544*f7c14bbaSAndroid Build Coastguard Worker 				return err;
545*f7c14bbaSAndroid Build Coastguard Worker 		}
546*f7c14bbaSAndroid Build Coastguard Worker 		break;
547*f7c14bbaSAndroid Build Coastguard Worker 	}
548*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC: {
549*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_type *ft;
550*f7c14bbaSAndroid Build Coastguard Worker 
551*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_validate_id(btf, t->type, id);
552*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
553*f7c14bbaSAndroid Build Coastguard Worker 			return err;
554*f7c14bbaSAndroid Build Coastguard Worker 		ft = btf__type_by_id(btf, t->type);
555*f7c14bbaSAndroid Build Coastguard Worker 		if (btf_kind(ft) != BTF_KIND_FUNC_PROTO) {
556*f7c14bbaSAndroid Build Coastguard Worker 			pr_warn("btf: type [%u]: referenced type [%u] is not FUNC_PROTO\n", id, t->type);
557*f7c14bbaSAndroid Build Coastguard Worker 			return -EINVAL;
558*f7c14bbaSAndroid Build Coastguard Worker 		}
559*f7c14bbaSAndroid Build Coastguard Worker 		break;
560*f7c14bbaSAndroid Build Coastguard Worker 	}
561*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO: {
562*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_param *m = btf_params(t);
563*f7c14bbaSAndroid Build Coastguard Worker 
564*f7c14bbaSAndroid Build Coastguard Worker 		n = btf_vlen(t);
565*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < n; i++, m++) {
566*f7c14bbaSAndroid Build Coastguard Worker 			err = btf_validate_str(btf, m->name_off, "param name", id);
567*f7c14bbaSAndroid Build Coastguard Worker 			err = err ?: btf_validate_id(btf, m->type, id);
568*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
569*f7c14bbaSAndroid Build Coastguard Worker 				return err;
570*f7c14bbaSAndroid Build Coastguard Worker 		}
571*f7c14bbaSAndroid Build Coastguard Worker 		break;
572*f7c14bbaSAndroid Build Coastguard Worker 	}
573*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DATASEC: {
574*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_var_secinfo *m = btf_var_secinfos(t);
575*f7c14bbaSAndroid Build Coastguard Worker 
576*f7c14bbaSAndroid Build Coastguard Worker 		n = btf_vlen(t);
577*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < n; i++, m++) {
578*f7c14bbaSAndroid Build Coastguard Worker 			err = btf_validate_id(btf, m->type, id);
579*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
580*f7c14bbaSAndroid Build Coastguard Worker 				return err;
581*f7c14bbaSAndroid Build Coastguard Worker 		}
582*f7c14bbaSAndroid Build Coastguard Worker 		break;
583*f7c14bbaSAndroid Build Coastguard Worker 	}
584*f7c14bbaSAndroid Build Coastguard Worker 	default:
585*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("btf: type [%u]: unrecognized kind %u\n", id, kind);
586*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
587*f7c14bbaSAndroid Build Coastguard Worker 	}
588*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
589*f7c14bbaSAndroid Build Coastguard Worker }
590*f7c14bbaSAndroid Build Coastguard Worker 
591*f7c14bbaSAndroid Build Coastguard Worker /* Validate basic sanity of BTF. It's intentionally less thorough than
592*f7c14bbaSAndroid Build Coastguard Worker  * kernel's validation and validates only properties of BTF that libbpf relies
593*f7c14bbaSAndroid Build Coastguard Worker  * on to be correct (e.g., valid type IDs, valid string offsets, etc)
594*f7c14bbaSAndroid Build Coastguard Worker  */
btf_sanity_check(const struct btf * btf)595*f7c14bbaSAndroid Build Coastguard Worker static int btf_sanity_check(const struct btf *btf)
596*f7c14bbaSAndroid Build Coastguard Worker {
597*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_type *t;
598*f7c14bbaSAndroid Build Coastguard Worker 	__u32 i, n = btf__type_cnt(btf);
599*f7c14bbaSAndroid Build Coastguard Worker 	int err;
600*f7c14bbaSAndroid Build Coastguard Worker 
601*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 1; i < n; i++) {
602*f7c14bbaSAndroid Build Coastguard Worker 		t = btf_type_by_id(btf, i);
603*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_validate_type(btf, t, i);
604*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
605*f7c14bbaSAndroid Build Coastguard Worker 			return err;
606*f7c14bbaSAndroid Build Coastguard Worker 	}
607*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
608*f7c14bbaSAndroid Build Coastguard Worker }
609*f7c14bbaSAndroid Build Coastguard Worker 
btf__type_cnt(const struct btf * btf)610*f7c14bbaSAndroid Build Coastguard Worker __u32 btf__type_cnt(const struct btf *btf)
611*f7c14bbaSAndroid Build Coastguard Worker {
612*f7c14bbaSAndroid Build Coastguard Worker 	return btf->start_id + btf->nr_types;
613*f7c14bbaSAndroid Build Coastguard Worker }
614*f7c14bbaSAndroid Build Coastguard Worker 
btf__base_btf(const struct btf * btf)615*f7c14bbaSAndroid Build Coastguard Worker const struct btf *btf__base_btf(const struct btf *btf)
616*f7c14bbaSAndroid Build Coastguard Worker {
617*f7c14bbaSAndroid Build Coastguard Worker 	return btf->base_btf;
618*f7c14bbaSAndroid Build Coastguard Worker }
619*f7c14bbaSAndroid Build Coastguard Worker 
620*f7c14bbaSAndroid Build Coastguard Worker /* internal helper returning non-const pointer to a type */
btf_type_by_id(const struct btf * btf,__u32 type_id)621*f7c14bbaSAndroid Build Coastguard Worker struct btf_type *btf_type_by_id(const struct btf *btf, __u32 type_id)
622*f7c14bbaSAndroid Build Coastguard Worker {
623*f7c14bbaSAndroid Build Coastguard Worker 	if (type_id == 0)
624*f7c14bbaSAndroid Build Coastguard Worker 		return &btf_void;
625*f7c14bbaSAndroid Build Coastguard Worker 	if (type_id < btf->start_id)
626*f7c14bbaSAndroid Build Coastguard Worker 		return btf_type_by_id(btf->base_btf, type_id);
627*f7c14bbaSAndroid Build Coastguard Worker 	return btf->types_data + btf->type_offs[type_id - btf->start_id];
628*f7c14bbaSAndroid Build Coastguard Worker }
629*f7c14bbaSAndroid Build Coastguard Worker 
btf__type_by_id(const struct btf * btf,__u32 type_id)630*f7c14bbaSAndroid Build Coastguard Worker const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id)
631*f7c14bbaSAndroid Build Coastguard Worker {
632*f7c14bbaSAndroid Build Coastguard Worker 	if (type_id >= btf->start_id + btf->nr_types)
633*f7c14bbaSAndroid Build Coastguard Worker 		return errno = EINVAL, NULL;
634*f7c14bbaSAndroid Build Coastguard Worker 	return btf_type_by_id((struct btf *)btf, type_id);
635*f7c14bbaSAndroid Build Coastguard Worker }
636*f7c14bbaSAndroid Build Coastguard Worker 
determine_ptr_size(const struct btf * btf)637*f7c14bbaSAndroid Build Coastguard Worker static int determine_ptr_size(const struct btf *btf)
638*f7c14bbaSAndroid Build Coastguard Worker {
639*f7c14bbaSAndroid Build Coastguard Worker 	static const char * const long_aliases[] = {
640*f7c14bbaSAndroid Build Coastguard Worker 		"long",
641*f7c14bbaSAndroid Build Coastguard Worker 		"long int",
642*f7c14bbaSAndroid Build Coastguard Worker 		"int long",
643*f7c14bbaSAndroid Build Coastguard Worker 		"unsigned long",
644*f7c14bbaSAndroid Build Coastguard Worker 		"long unsigned",
645*f7c14bbaSAndroid Build Coastguard Worker 		"unsigned long int",
646*f7c14bbaSAndroid Build Coastguard Worker 		"unsigned int long",
647*f7c14bbaSAndroid Build Coastguard Worker 		"long unsigned int",
648*f7c14bbaSAndroid Build Coastguard Worker 		"long int unsigned",
649*f7c14bbaSAndroid Build Coastguard Worker 		"int unsigned long",
650*f7c14bbaSAndroid Build Coastguard Worker 		"int long unsigned",
651*f7c14bbaSAndroid Build Coastguard Worker 	};
652*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_type *t;
653*f7c14bbaSAndroid Build Coastguard Worker 	const char *name;
654*f7c14bbaSAndroid Build Coastguard Worker 	int i, j, n;
655*f7c14bbaSAndroid Build Coastguard Worker 
656*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->base_btf && btf->base_btf->ptr_sz > 0)
657*f7c14bbaSAndroid Build Coastguard Worker 		return btf->base_btf->ptr_sz;
658*f7c14bbaSAndroid Build Coastguard Worker 
659*f7c14bbaSAndroid Build Coastguard Worker 	n = btf__type_cnt(btf);
660*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 1; i < n; i++) {
661*f7c14bbaSAndroid Build Coastguard Worker 		t = btf__type_by_id(btf, i);
662*f7c14bbaSAndroid Build Coastguard Worker 		if (!btf_is_int(t))
663*f7c14bbaSAndroid Build Coastguard Worker 			continue;
664*f7c14bbaSAndroid Build Coastguard Worker 
665*f7c14bbaSAndroid Build Coastguard Worker 		if (t->size != 4 && t->size != 8)
666*f7c14bbaSAndroid Build Coastguard Worker 			continue;
667*f7c14bbaSAndroid Build Coastguard Worker 
668*f7c14bbaSAndroid Build Coastguard Worker 		name = btf__name_by_offset(btf, t->name_off);
669*f7c14bbaSAndroid Build Coastguard Worker 		if (!name)
670*f7c14bbaSAndroid Build Coastguard Worker 			continue;
671*f7c14bbaSAndroid Build Coastguard Worker 
672*f7c14bbaSAndroid Build Coastguard Worker 		for (j = 0; j < ARRAY_SIZE(long_aliases); j++) {
673*f7c14bbaSAndroid Build Coastguard Worker 			if (strcmp(name, long_aliases[j]) == 0)
674*f7c14bbaSAndroid Build Coastguard Worker 				return t->size;
675*f7c14bbaSAndroid Build Coastguard Worker 		}
676*f7c14bbaSAndroid Build Coastguard Worker 	}
677*f7c14bbaSAndroid Build Coastguard Worker 
678*f7c14bbaSAndroid Build Coastguard Worker 	return -1;
679*f7c14bbaSAndroid Build Coastguard Worker }
680*f7c14bbaSAndroid Build Coastguard Worker 
btf_ptr_sz(const struct btf * btf)681*f7c14bbaSAndroid Build Coastguard Worker static size_t btf_ptr_sz(const struct btf *btf)
682*f7c14bbaSAndroid Build Coastguard Worker {
683*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf->ptr_sz)
684*f7c14bbaSAndroid Build Coastguard Worker 		((struct btf *)btf)->ptr_sz = determine_ptr_size(btf);
685*f7c14bbaSAndroid Build Coastguard Worker 	return btf->ptr_sz < 0 ? sizeof(void *) : btf->ptr_sz;
686*f7c14bbaSAndroid Build Coastguard Worker }
687*f7c14bbaSAndroid Build Coastguard Worker 
688*f7c14bbaSAndroid Build Coastguard Worker /* Return pointer size this BTF instance assumes. The size is heuristically
689*f7c14bbaSAndroid Build Coastguard Worker  * determined by looking for 'long' or 'unsigned long' integer type and
690*f7c14bbaSAndroid Build Coastguard Worker  * recording its size in bytes. If BTF type information doesn't have any such
691*f7c14bbaSAndroid Build Coastguard Worker  * type, this function returns 0. In the latter case, native architecture's
692*f7c14bbaSAndroid Build Coastguard Worker  * pointer size is assumed, so will be either 4 or 8, depending on
693*f7c14bbaSAndroid Build Coastguard Worker  * architecture that libbpf was compiled for. It's possible to override
694*f7c14bbaSAndroid Build Coastguard Worker  * guessed value by using btf__set_pointer_size() API.
695*f7c14bbaSAndroid Build Coastguard Worker  */
btf__pointer_size(const struct btf * btf)696*f7c14bbaSAndroid Build Coastguard Worker size_t btf__pointer_size(const struct btf *btf)
697*f7c14bbaSAndroid Build Coastguard Worker {
698*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf->ptr_sz)
699*f7c14bbaSAndroid Build Coastguard Worker 		((struct btf *)btf)->ptr_sz = determine_ptr_size(btf);
700*f7c14bbaSAndroid Build Coastguard Worker 
701*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->ptr_sz < 0)
702*f7c14bbaSAndroid Build Coastguard Worker 		/* not enough BTF type info to guess */
703*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
704*f7c14bbaSAndroid Build Coastguard Worker 
705*f7c14bbaSAndroid Build Coastguard Worker 	return btf->ptr_sz;
706*f7c14bbaSAndroid Build Coastguard Worker }
707*f7c14bbaSAndroid Build Coastguard Worker 
708*f7c14bbaSAndroid Build Coastguard Worker /* Override or set pointer size in bytes. Only values of 4 and 8 are
709*f7c14bbaSAndroid Build Coastguard Worker  * supported.
710*f7c14bbaSAndroid Build Coastguard Worker  */
btf__set_pointer_size(struct btf * btf,size_t ptr_sz)711*f7c14bbaSAndroid Build Coastguard Worker int btf__set_pointer_size(struct btf *btf, size_t ptr_sz)
712*f7c14bbaSAndroid Build Coastguard Worker {
713*f7c14bbaSAndroid Build Coastguard Worker 	if (ptr_sz != 4 && ptr_sz != 8)
714*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
715*f7c14bbaSAndroid Build Coastguard Worker 	btf->ptr_sz = ptr_sz;
716*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
717*f7c14bbaSAndroid Build Coastguard Worker }
718*f7c14bbaSAndroid Build Coastguard Worker 
is_host_big_endian(void)719*f7c14bbaSAndroid Build Coastguard Worker static bool is_host_big_endian(void)
720*f7c14bbaSAndroid Build Coastguard Worker {
721*f7c14bbaSAndroid Build Coastguard Worker #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
722*f7c14bbaSAndroid Build Coastguard Worker 	return false;
723*f7c14bbaSAndroid Build Coastguard Worker #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
724*f7c14bbaSAndroid Build Coastguard Worker 	return true;
725*f7c14bbaSAndroid Build Coastguard Worker #else
726*f7c14bbaSAndroid Build Coastguard Worker # error "Unrecognized __BYTE_ORDER__"
727*f7c14bbaSAndroid Build Coastguard Worker #endif
728*f7c14bbaSAndroid Build Coastguard Worker }
729*f7c14bbaSAndroid Build Coastguard Worker 
btf__endianness(const struct btf * btf)730*f7c14bbaSAndroid Build Coastguard Worker enum btf_endianness btf__endianness(const struct btf *btf)
731*f7c14bbaSAndroid Build Coastguard Worker {
732*f7c14bbaSAndroid Build Coastguard Worker 	if (is_host_big_endian())
733*f7c14bbaSAndroid Build Coastguard Worker 		return btf->swapped_endian ? BTF_LITTLE_ENDIAN : BTF_BIG_ENDIAN;
734*f7c14bbaSAndroid Build Coastguard Worker 	else
735*f7c14bbaSAndroid Build Coastguard Worker 		return btf->swapped_endian ? BTF_BIG_ENDIAN : BTF_LITTLE_ENDIAN;
736*f7c14bbaSAndroid Build Coastguard Worker }
737*f7c14bbaSAndroid Build Coastguard Worker 
btf__set_endianness(struct btf * btf,enum btf_endianness endian)738*f7c14bbaSAndroid Build Coastguard Worker int btf__set_endianness(struct btf *btf, enum btf_endianness endian)
739*f7c14bbaSAndroid Build Coastguard Worker {
740*f7c14bbaSAndroid Build Coastguard Worker 	if (endian != BTF_LITTLE_ENDIAN && endian != BTF_BIG_ENDIAN)
741*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
742*f7c14bbaSAndroid Build Coastguard Worker 
743*f7c14bbaSAndroid Build Coastguard Worker 	btf->swapped_endian = is_host_big_endian() != (endian == BTF_BIG_ENDIAN);
744*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf->swapped_endian) {
745*f7c14bbaSAndroid Build Coastguard Worker 		free(btf->raw_data_swapped);
746*f7c14bbaSAndroid Build Coastguard Worker 		btf->raw_data_swapped = NULL;
747*f7c14bbaSAndroid Build Coastguard Worker 	}
748*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
749*f7c14bbaSAndroid Build Coastguard Worker }
750*f7c14bbaSAndroid Build Coastguard Worker 
btf_type_is_void(const struct btf_type * t)751*f7c14bbaSAndroid Build Coastguard Worker static bool btf_type_is_void(const struct btf_type *t)
752*f7c14bbaSAndroid Build Coastguard Worker {
753*f7c14bbaSAndroid Build Coastguard Worker 	return t == &btf_void || btf_is_fwd(t);
754*f7c14bbaSAndroid Build Coastguard Worker }
755*f7c14bbaSAndroid Build Coastguard Worker 
btf_type_is_void_or_null(const struct btf_type * t)756*f7c14bbaSAndroid Build Coastguard Worker static bool btf_type_is_void_or_null(const struct btf_type *t)
757*f7c14bbaSAndroid Build Coastguard Worker {
758*f7c14bbaSAndroid Build Coastguard Worker 	return !t || btf_type_is_void(t);
759*f7c14bbaSAndroid Build Coastguard Worker }
760*f7c14bbaSAndroid Build Coastguard Worker 
761*f7c14bbaSAndroid Build Coastguard Worker #define MAX_RESOLVE_DEPTH 32
762*f7c14bbaSAndroid Build Coastguard Worker 
btf__resolve_size(const struct btf * btf,__u32 type_id)763*f7c14bbaSAndroid Build Coastguard Worker __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
764*f7c14bbaSAndroid Build Coastguard Worker {
765*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_array *array;
766*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_type *t;
767*f7c14bbaSAndroid Build Coastguard Worker 	__u32 nelems = 1;
768*f7c14bbaSAndroid Build Coastguard Worker 	__s64 size = -1;
769*f7c14bbaSAndroid Build Coastguard Worker 	int i;
770*f7c14bbaSAndroid Build Coastguard Worker 
771*f7c14bbaSAndroid Build Coastguard Worker 	t = btf__type_by_id(btf, type_id);
772*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t); i++) {
773*f7c14bbaSAndroid Build Coastguard Worker 		switch (btf_kind(t)) {
774*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_INT:
775*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_STRUCT:
776*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_UNION:
777*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_ENUM:
778*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_ENUM64:
779*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_DATASEC:
780*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_FLOAT:
781*f7c14bbaSAndroid Build Coastguard Worker 			size = t->size;
782*f7c14bbaSAndroid Build Coastguard Worker 			goto done;
783*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_PTR:
784*f7c14bbaSAndroid Build Coastguard Worker 			size = btf_ptr_sz(btf);
785*f7c14bbaSAndroid Build Coastguard Worker 			goto done;
786*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_TYPEDEF:
787*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_VOLATILE:
788*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_CONST:
789*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_RESTRICT:
790*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_VAR:
791*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_DECL_TAG:
792*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_TYPE_TAG:
793*f7c14bbaSAndroid Build Coastguard Worker 			type_id = t->type;
794*f7c14bbaSAndroid Build Coastguard Worker 			break;
795*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_ARRAY:
796*f7c14bbaSAndroid Build Coastguard Worker 			array = btf_array(t);
797*f7c14bbaSAndroid Build Coastguard Worker 			if (nelems && array->nelems > UINT32_MAX / nelems)
798*f7c14bbaSAndroid Build Coastguard Worker 				return libbpf_err(-E2BIG);
799*f7c14bbaSAndroid Build Coastguard Worker 			nelems *= array->nelems;
800*f7c14bbaSAndroid Build Coastguard Worker 			type_id = array->type;
801*f7c14bbaSAndroid Build Coastguard Worker 			break;
802*f7c14bbaSAndroid Build Coastguard Worker 		default:
803*f7c14bbaSAndroid Build Coastguard Worker 			return libbpf_err(-EINVAL);
804*f7c14bbaSAndroid Build Coastguard Worker 		}
805*f7c14bbaSAndroid Build Coastguard Worker 
806*f7c14bbaSAndroid Build Coastguard Worker 		t = btf__type_by_id(btf, type_id);
807*f7c14bbaSAndroid Build Coastguard Worker 	}
808*f7c14bbaSAndroid Build Coastguard Worker 
809*f7c14bbaSAndroid Build Coastguard Worker done:
810*f7c14bbaSAndroid Build Coastguard Worker 	if (size < 0)
811*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
812*f7c14bbaSAndroid Build Coastguard Worker 	if (nelems && size > UINT32_MAX / nelems)
813*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-E2BIG);
814*f7c14bbaSAndroid Build Coastguard Worker 
815*f7c14bbaSAndroid Build Coastguard Worker 	return nelems * size;
816*f7c14bbaSAndroid Build Coastguard Worker }
817*f7c14bbaSAndroid Build Coastguard Worker 
btf__align_of(const struct btf * btf,__u32 id)818*f7c14bbaSAndroid Build Coastguard Worker int btf__align_of(const struct btf *btf, __u32 id)
819*f7c14bbaSAndroid Build Coastguard Worker {
820*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_type *t = btf__type_by_id(btf, id);
821*f7c14bbaSAndroid Build Coastguard Worker 	__u16 kind = btf_kind(t);
822*f7c14bbaSAndroid Build Coastguard Worker 
823*f7c14bbaSAndroid Build Coastguard Worker 	switch (kind) {
824*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_INT:
825*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM:
826*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64:
827*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FLOAT:
828*f7c14bbaSAndroid Build Coastguard Worker 		return min(btf_ptr_sz(btf), (size_t)t->size);
829*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
830*f7c14bbaSAndroid Build Coastguard Worker 		return btf_ptr_sz(btf);
831*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
832*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
833*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
834*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
835*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
836*f7c14bbaSAndroid Build Coastguard Worker 		return btf__align_of(btf, t->type);
837*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY:
838*f7c14bbaSAndroid Build Coastguard Worker 		return btf__align_of(btf, btf_array(t)->type);
839*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
840*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION: {
841*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_member *m = btf_members(t);
842*f7c14bbaSAndroid Build Coastguard Worker 		__u16 vlen = btf_vlen(t);
843*f7c14bbaSAndroid Build Coastguard Worker 		int i, max_align = 1, align;
844*f7c14bbaSAndroid Build Coastguard Worker 
845*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < vlen; i++, m++) {
846*f7c14bbaSAndroid Build Coastguard Worker 			align = btf__align_of(btf, m->type);
847*f7c14bbaSAndroid Build Coastguard Worker 			if (align <= 0)
848*f7c14bbaSAndroid Build Coastguard Worker 				return libbpf_err(align);
849*f7c14bbaSAndroid Build Coastguard Worker 			max_align = max(max_align, align);
850*f7c14bbaSAndroid Build Coastguard Worker 
851*f7c14bbaSAndroid Build Coastguard Worker 			/* if field offset isn't aligned according to field
852*f7c14bbaSAndroid Build Coastguard Worker 			 * type's alignment, then struct must be packed
853*f7c14bbaSAndroid Build Coastguard Worker 			 */
854*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_member_bitfield_size(t, i) == 0 &&
855*f7c14bbaSAndroid Build Coastguard Worker 			    (m->offset % (8 * align)) != 0)
856*f7c14bbaSAndroid Build Coastguard Worker 				return 1;
857*f7c14bbaSAndroid Build Coastguard Worker 		}
858*f7c14bbaSAndroid Build Coastguard Worker 
859*f7c14bbaSAndroid Build Coastguard Worker 		/* if struct/union size isn't a multiple of its alignment,
860*f7c14bbaSAndroid Build Coastguard Worker 		 * then struct must be packed
861*f7c14bbaSAndroid Build Coastguard Worker 		 */
862*f7c14bbaSAndroid Build Coastguard Worker 		if ((t->size % max_align) != 0)
863*f7c14bbaSAndroid Build Coastguard Worker 			return 1;
864*f7c14bbaSAndroid Build Coastguard Worker 
865*f7c14bbaSAndroid Build Coastguard Worker 		return max_align;
866*f7c14bbaSAndroid Build Coastguard Worker 	}
867*f7c14bbaSAndroid Build Coastguard Worker 	default:
868*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
869*f7c14bbaSAndroid Build Coastguard Worker 		return errno = EINVAL, 0;
870*f7c14bbaSAndroid Build Coastguard Worker 	}
871*f7c14bbaSAndroid Build Coastguard Worker }
872*f7c14bbaSAndroid Build Coastguard Worker 
btf__resolve_type(const struct btf * btf,__u32 type_id)873*f7c14bbaSAndroid Build Coastguard Worker int btf__resolve_type(const struct btf *btf, __u32 type_id)
874*f7c14bbaSAndroid Build Coastguard Worker {
875*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_type *t;
876*f7c14bbaSAndroid Build Coastguard Worker 	int depth = 0;
877*f7c14bbaSAndroid Build Coastguard Worker 
878*f7c14bbaSAndroid Build Coastguard Worker 	t = btf__type_by_id(btf, type_id);
879*f7c14bbaSAndroid Build Coastguard Worker 	while (depth < MAX_RESOLVE_DEPTH &&
880*f7c14bbaSAndroid Build Coastguard Worker 	       !btf_type_is_void_or_null(t) &&
881*f7c14bbaSAndroid Build Coastguard Worker 	       (btf_is_mod(t) || btf_is_typedef(t) || btf_is_var(t))) {
882*f7c14bbaSAndroid Build Coastguard Worker 		type_id = t->type;
883*f7c14bbaSAndroid Build Coastguard Worker 		t = btf__type_by_id(btf, type_id);
884*f7c14bbaSAndroid Build Coastguard Worker 		depth++;
885*f7c14bbaSAndroid Build Coastguard Worker 	}
886*f7c14bbaSAndroid Build Coastguard Worker 
887*f7c14bbaSAndroid Build Coastguard Worker 	if (depth == MAX_RESOLVE_DEPTH || btf_type_is_void_or_null(t))
888*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
889*f7c14bbaSAndroid Build Coastguard Worker 
890*f7c14bbaSAndroid Build Coastguard Worker 	return type_id;
891*f7c14bbaSAndroid Build Coastguard Worker }
892*f7c14bbaSAndroid Build Coastguard Worker 
btf__find_by_name(const struct btf * btf,const char * type_name)893*f7c14bbaSAndroid Build Coastguard Worker __s32 btf__find_by_name(const struct btf *btf, const char *type_name)
894*f7c14bbaSAndroid Build Coastguard Worker {
895*f7c14bbaSAndroid Build Coastguard Worker 	__u32 i, nr_types = btf__type_cnt(btf);
896*f7c14bbaSAndroid Build Coastguard Worker 
897*f7c14bbaSAndroid Build Coastguard Worker 	if (!strcmp(type_name, "void"))
898*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
899*f7c14bbaSAndroid Build Coastguard Worker 
900*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 1; i < nr_types; i++) {
901*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_type *t = btf__type_by_id(btf, i);
902*f7c14bbaSAndroid Build Coastguard Worker 		const char *name = btf__name_by_offset(btf, t->name_off);
903*f7c14bbaSAndroid Build Coastguard Worker 
904*f7c14bbaSAndroid Build Coastguard Worker 		if (name && !strcmp(type_name, name))
905*f7c14bbaSAndroid Build Coastguard Worker 			return i;
906*f7c14bbaSAndroid Build Coastguard Worker 	}
907*f7c14bbaSAndroid Build Coastguard Worker 
908*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_err(-ENOENT);
909*f7c14bbaSAndroid Build Coastguard Worker }
910*f7c14bbaSAndroid Build Coastguard Worker 
btf_find_by_name_kind(const struct btf * btf,int start_id,const char * type_name,__u32 kind)911*f7c14bbaSAndroid Build Coastguard Worker static __s32 btf_find_by_name_kind(const struct btf *btf, int start_id,
912*f7c14bbaSAndroid Build Coastguard Worker 				   const char *type_name, __u32 kind)
913*f7c14bbaSAndroid Build Coastguard Worker {
914*f7c14bbaSAndroid Build Coastguard Worker 	__u32 i, nr_types = btf__type_cnt(btf);
915*f7c14bbaSAndroid Build Coastguard Worker 
916*f7c14bbaSAndroid Build Coastguard Worker 	if (kind == BTF_KIND_UNKN || !strcmp(type_name, "void"))
917*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
918*f7c14bbaSAndroid Build Coastguard Worker 
919*f7c14bbaSAndroid Build Coastguard Worker 	for (i = start_id; i < nr_types; i++) {
920*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_type *t = btf__type_by_id(btf, i);
921*f7c14bbaSAndroid Build Coastguard Worker 		const char *name;
922*f7c14bbaSAndroid Build Coastguard Worker 
923*f7c14bbaSAndroid Build Coastguard Worker 		if (btf_kind(t) != kind)
924*f7c14bbaSAndroid Build Coastguard Worker 			continue;
925*f7c14bbaSAndroid Build Coastguard Worker 		name = btf__name_by_offset(btf, t->name_off);
926*f7c14bbaSAndroid Build Coastguard Worker 		if (name && !strcmp(type_name, name))
927*f7c14bbaSAndroid Build Coastguard Worker 			return i;
928*f7c14bbaSAndroid Build Coastguard Worker 	}
929*f7c14bbaSAndroid Build Coastguard Worker 
930*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_err(-ENOENT);
931*f7c14bbaSAndroid Build Coastguard Worker }
932*f7c14bbaSAndroid Build Coastguard Worker 
btf__find_by_name_kind_own(const struct btf * btf,const char * type_name,__u32 kind)933*f7c14bbaSAndroid Build Coastguard Worker __s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name,
934*f7c14bbaSAndroid Build Coastguard Worker 				 __u32 kind)
935*f7c14bbaSAndroid Build Coastguard Worker {
936*f7c14bbaSAndroid Build Coastguard Worker 	return btf_find_by_name_kind(btf, btf->start_id, type_name, kind);
937*f7c14bbaSAndroid Build Coastguard Worker }
938*f7c14bbaSAndroid Build Coastguard Worker 
btf__find_by_name_kind(const struct btf * btf,const char * type_name,__u32 kind)939*f7c14bbaSAndroid Build Coastguard Worker __s32 btf__find_by_name_kind(const struct btf *btf, const char *type_name,
940*f7c14bbaSAndroid Build Coastguard Worker 			     __u32 kind)
941*f7c14bbaSAndroid Build Coastguard Worker {
942*f7c14bbaSAndroid Build Coastguard Worker 	return btf_find_by_name_kind(btf, 1, type_name, kind);
943*f7c14bbaSAndroid Build Coastguard Worker }
944*f7c14bbaSAndroid Build Coastguard Worker 
btf_is_modifiable(const struct btf * btf)945*f7c14bbaSAndroid Build Coastguard Worker static bool btf_is_modifiable(const struct btf *btf)
946*f7c14bbaSAndroid Build Coastguard Worker {
947*f7c14bbaSAndroid Build Coastguard Worker 	return (void *)btf->hdr != btf->raw_data;
948*f7c14bbaSAndroid Build Coastguard Worker }
949*f7c14bbaSAndroid Build Coastguard Worker 
btf__free(struct btf * btf)950*f7c14bbaSAndroid Build Coastguard Worker void btf__free(struct btf *btf)
951*f7c14bbaSAndroid Build Coastguard Worker {
952*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR_OR_NULL(btf))
953*f7c14bbaSAndroid Build Coastguard Worker 		return;
954*f7c14bbaSAndroid Build Coastguard Worker 
955*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->fd >= 0)
956*f7c14bbaSAndroid Build Coastguard Worker 		close(btf->fd);
957*f7c14bbaSAndroid Build Coastguard Worker 
958*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_is_modifiable(btf)) {
959*f7c14bbaSAndroid Build Coastguard Worker 		/* if BTF was modified after loading, it will have a split
960*f7c14bbaSAndroid Build Coastguard Worker 		 * in-memory representation for header, types, and strings
961*f7c14bbaSAndroid Build Coastguard Worker 		 * sections, so we need to free all of them individually. It
962*f7c14bbaSAndroid Build Coastguard Worker 		 * might still have a cached contiguous raw data present,
963*f7c14bbaSAndroid Build Coastguard Worker 		 * which will be unconditionally freed below.
964*f7c14bbaSAndroid Build Coastguard Worker 		 */
965*f7c14bbaSAndroid Build Coastguard Worker 		free(btf->hdr);
966*f7c14bbaSAndroid Build Coastguard Worker 		free(btf->types_data);
967*f7c14bbaSAndroid Build Coastguard Worker 		strset__free(btf->strs_set);
968*f7c14bbaSAndroid Build Coastguard Worker 	}
969*f7c14bbaSAndroid Build Coastguard Worker 	free(btf->raw_data);
970*f7c14bbaSAndroid Build Coastguard Worker 	free(btf->raw_data_swapped);
971*f7c14bbaSAndroid Build Coastguard Worker 	free(btf->type_offs);
972*f7c14bbaSAndroid Build Coastguard Worker 	free(btf);
973*f7c14bbaSAndroid Build Coastguard Worker }
974*f7c14bbaSAndroid Build Coastguard Worker 
btf_new_empty(struct btf * base_btf)975*f7c14bbaSAndroid Build Coastguard Worker static struct btf *btf_new_empty(struct btf *base_btf)
976*f7c14bbaSAndroid Build Coastguard Worker {
977*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf;
978*f7c14bbaSAndroid Build Coastguard Worker 
979*f7c14bbaSAndroid Build Coastguard Worker 	btf = calloc(1, sizeof(*btf));
980*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf)
981*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(-ENOMEM);
982*f7c14bbaSAndroid Build Coastguard Worker 
983*f7c14bbaSAndroid Build Coastguard Worker 	btf->nr_types = 0;
984*f7c14bbaSAndroid Build Coastguard Worker 	btf->start_id = 1;
985*f7c14bbaSAndroid Build Coastguard Worker 	btf->start_str_off = 0;
986*f7c14bbaSAndroid Build Coastguard Worker 	btf->fd = -1;
987*f7c14bbaSAndroid Build Coastguard Worker 	btf->ptr_sz = sizeof(void *);
988*f7c14bbaSAndroid Build Coastguard Worker 	btf->swapped_endian = false;
989*f7c14bbaSAndroid Build Coastguard Worker 
990*f7c14bbaSAndroid Build Coastguard Worker 	if (base_btf) {
991*f7c14bbaSAndroid Build Coastguard Worker 		btf->base_btf = base_btf;
992*f7c14bbaSAndroid Build Coastguard Worker 		btf->start_id = btf__type_cnt(base_btf);
993*f7c14bbaSAndroid Build Coastguard Worker 		btf->start_str_off = base_btf->hdr->str_len;
994*f7c14bbaSAndroid Build Coastguard Worker 	}
995*f7c14bbaSAndroid Build Coastguard Worker 
996*f7c14bbaSAndroid Build Coastguard Worker 	/* +1 for empty string at offset 0 */
997*f7c14bbaSAndroid Build Coastguard Worker 	btf->raw_size = sizeof(struct btf_header) + (base_btf ? 0 : 1);
998*f7c14bbaSAndroid Build Coastguard Worker 	btf->raw_data = calloc(1, btf->raw_size);
999*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf->raw_data) {
1000*f7c14bbaSAndroid Build Coastguard Worker 		free(btf);
1001*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(-ENOMEM);
1002*f7c14bbaSAndroid Build Coastguard Worker 	}
1003*f7c14bbaSAndroid Build Coastguard Worker 
1004*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr = btf->raw_data;
1005*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->hdr_len = sizeof(struct btf_header);
1006*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->magic = BTF_MAGIC;
1007*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->version = BTF_VERSION;
1008*f7c14bbaSAndroid Build Coastguard Worker 
1009*f7c14bbaSAndroid Build Coastguard Worker 	btf->types_data = btf->raw_data + btf->hdr->hdr_len;
1010*f7c14bbaSAndroid Build Coastguard Worker 	btf->strs_data = btf->raw_data + btf->hdr->hdr_len;
1011*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_len = base_btf ? 0 : 1; /* empty string at offset 0 */
1012*f7c14bbaSAndroid Build Coastguard Worker 
1013*f7c14bbaSAndroid Build Coastguard Worker 	return btf;
1014*f7c14bbaSAndroid Build Coastguard Worker }
1015*f7c14bbaSAndroid Build Coastguard Worker 
btf__new_empty(void)1016*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__new_empty(void)
1017*f7c14bbaSAndroid Build Coastguard Worker {
1018*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_new_empty(NULL));
1019*f7c14bbaSAndroid Build Coastguard Worker }
1020*f7c14bbaSAndroid Build Coastguard Worker 
btf__new_empty_split(struct btf * base_btf)1021*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__new_empty_split(struct btf *base_btf)
1022*f7c14bbaSAndroid Build Coastguard Worker {
1023*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_new_empty(base_btf));
1024*f7c14bbaSAndroid Build Coastguard Worker }
1025*f7c14bbaSAndroid Build Coastguard Worker 
btf_new(const void * data,__u32 size,struct btf * base_btf)1026*f7c14bbaSAndroid Build Coastguard Worker static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
1027*f7c14bbaSAndroid Build Coastguard Worker {
1028*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf;
1029*f7c14bbaSAndroid Build Coastguard Worker 	int err;
1030*f7c14bbaSAndroid Build Coastguard Worker 
1031*f7c14bbaSAndroid Build Coastguard Worker 	btf = calloc(1, sizeof(struct btf));
1032*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf)
1033*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(-ENOMEM);
1034*f7c14bbaSAndroid Build Coastguard Worker 
1035*f7c14bbaSAndroid Build Coastguard Worker 	btf->nr_types = 0;
1036*f7c14bbaSAndroid Build Coastguard Worker 	btf->start_id = 1;
1037*f7c14bbaSAndroid Build Coastguard Worker 	btf->start_str_off = 0;
1038*f7c14bbaSAndroid Build Coastguard Worker 	btf->fd = -1;
1039*f7c14bbaSAndroid Build Coastguard Worker 
1040*f7c14bbaSAndroid Build Coastguard Worker 	if (base_btf) {
1041*f7c14bbaSAndroid Build Coastguard Worker 		btf->base_btf = base_btf;
1042*f7c14bbaSAndroid Build Coastguard Worker 		btf->start_id = btf__type_cnt(base_btf);
1043*f7c14bbaSAndroid Build Coastguard Worker 		btf->start_str_off = base_btf->hdr->str_len;
1044*f7c14bbaSAndroid Build Coastguard Worker 	}
1045*f7c14bbaSAndroid Build Coastguard Worker 
1046*f7c14bbaSAndroid Build Coastguard Worker 	btf->raw_data = malloc(size);
1047*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf->raw_data) {
1048*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENOMEM;
1049*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1050*f7c14bbaSAndroid Build Coastguard Worker 	}
1051*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(btf->raw_data, data, size);
1052*f7c14bbaSAndroid Build Coastguard Worker 	btf->raw_size = size;
1053*f7c14bbaSAndroid Build Coastguard Worker 
1054*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr = btf->raw_data;
1055*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_parse_hdr(btf);
1056*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
1057*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1058*f7c14bbaSAndroid Build Coastguard Worker 
1059*f7c14bbaSAndroid Build Coastguard Worker 	btf->strs_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->str_off;
1060*f7c14bbaSAndroid Build Coastguard Worker 	btf->types_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->type_off;
1061*f7c14bbaSAndroid Build Coastguard Worker 
1062*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_parse_str_sec(btf);
1063*f7c14bbaSAndroid Build Coastguard Worker 	err = err ?: btf_parse_type_sec(btf);
1064*f7c14bbaSAndroid Build Coastguard Worker 	err = err ?: btf_sanity_check(btf);
1065*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
1066*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1067*f7c14bbaSAndroid Build Coastguard Worker 
1068*f7c14bbaSAndroid Build Coastguard Worker done:
1069*f7c14bbaSAndroid Build Coastguard Worker 	if (err) {
1070*f7c14bbaSAndroid Build Coastguard Worker 		btf__free(btf);
1071*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(err);
1072*f7c14bbaSAndroid Build Coastguard Worker 	}
1073*f7c14bbaSAndroid Build Coastguard Worker 
1074*f7c14bbaSAndroid Build Coastguard Worker 	return btf;
1075*f7c14bbaSAndroid Build Coastguard Worker }
1076*f7c14bbaSAndroid Build Coastguard Worker 
btf__new(const void * data,__u32 size)1077*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__new(const void *data, __u32 size)
1078*f7c14bbaSAndroid Build Coastguard Worker {
1079*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_new(data, size, NULL));
1080*f7c14bbaSAndroid Build Coastguard Worker }
1081*f7c14bbaSAndroid Build Coastguard Worker 
btf__new_split(const void * data,__u32 size,struct btf * base_btf)1082*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__new_split(const void *data, __u32 size, struct btf *base_btf)
1083*f7c14bbaSAndroid Build Coastguard Worker {
1084*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_new(data, size, base_btf));
1085*f7c14bbaSAndroid Build Coastguard Worker }
1086*f7c14bbaSAndroid Build Coastguard Worker 
btf_parse_elf(const char * path,struct btf * base_btf,struct btf_ext ** btf_ext)1087*f7c14bbaSAndroid Build Coastguard Worker static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
1088*f7c14bbaSAndroid Build Coastguard Worker 				 struct btf_ext **btf_ext)
1089*f7c14bbaSAndroid Build Coastguard Worker {
1090*f7c14bbaSAndroid Build Coastguard Worker 	Elf_Data *btf_data = NULL, *btf_ext_data = NULL;
1091*f7c14bbaSAndroid Build Coastguard Worker 	int err = 0, fd = -1, idx = 0;
1092*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf = NULL;
1093*f7c14bbaSAndroid Build Coastguard Worker 	Elf_Scn *scn = NULL;
1094*f7c14bbaSAndroid Build Coastguard Worker 	Elf *elf = NULL;
1095*f7c14bbaSAndroid Build Coastguard Worker 	GElf_Ehdr ehdr;
1096*f7c14bbaSAndroid Build Coastguard Worker 	size_t shstrndx;
1097*f7c14bbaSAndroid Build Coastguard Worker 
1098*f7c14bbaSAndroid Build Coastguard Worker 	if (elf_version(EV_CURRENT) == EV_NONE) {
1099*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to init libelf for %s\n", path);
1100*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(-LIBBPF_ERRNO__LIBELF);
1101*f7c14bbaSAndroid Build Coastguard Worker 	}
1102*f7c14bbaSAndroid Build Coastguard Worker 
1103*f7c14bbaSAndroid Build Coastguard Worker 	fd = open(path, O_RDONLY | O_CLOEXEC);
1104*f7c14bbaSAndroid Build Coastguard Worker 	if (fd < 0) {
1105*f7c14bbaSAndroid Build Coastguard Worker 		err = -errno;
1106*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to open %s: %s\n", path, strerror(errno));
1107*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(err);
1108*f7c14bbaSAndroid Build Coastguard Worker 	}
1109*f7c14bbaSAndroid Build Coastguard Worker 
1110*f7c14bbaSAndroid Build Coastguard Worker 	err = -LIBBPF_ERRNO__FORMAT;
1111*f7c14bbaSAndroid Build Coastguard Worker 
1112*f7c14bbaSAndroid Build Coastguard Worker 	elf = elf_begin(fd, ELF_C_READ, NULL);
1113*f7c14bbaSAndroid Build Coastguard Worker 	if (!elf) {
1114*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to open %s as ELF file\n", path);
1115*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1116*f7c14bbaSAndroid Build Coastguard Worker 	}
1117*f7c14bbaSAndroid Build Coastguard Worker 	if (!gelf_getehdr(elf, &ehdr)) {
1118*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to get EHDR from %s\n", path);
1119*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1120*f7c14bbaSAndroid Build Coastguard Worker 	}
1121*f7c14bbaSAndroid Build Coastguard Worker 
1122*f7c14bbaSAndroid Build Coastguard Worker 	if (elf_getshdrstrndx(elf, &shstrndx)) {
1123*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to get section names section index for %s\n",
1124*f7c14bbaSAndroid Build Coastguard Worker 			path);
1125*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1126*f7c14bbaSAndroid Build Coastguard Worker 	}
1127*f7c14bbaSAndroid Build Coastguard Worker 
1128*f7c14bbaSAndroid Build Coastguard Worker 	if (!elf_rawdata(elf_getscn(elf, shstrndx), NULL)) {
1129*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to get e_shstrndx from %s\n", path);
1130*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1131*f7c14bbaSAndroid Build Coastguard Worker 	}
1132*f7c14bbaSAndroid Build Coastguard Worker 
1133*f7c14bbaSAndroid Build Coastguard Worker 	while ((scn = elf_nextscn(elf, scn)) != NULL) {
1134*f7c14bbaSAndroid Build Coastguard Worker 		GElf_Shdr sh;
1135*f7c14bbaSAndroid Build Coastguard Worker 		char *name;
1136*f7c14bbaSAndroid Build Coastguard Worker 
1137*f7c14bbaSAndroid Build Coastguard Worker 		idx++;
1138*f7c14bbaSAndroid Build Coastguard Worker 		if (gelf_getshdr(scn, &sh) != &sh) {
1139*f7c14bbaSAndroid Build Coastguard Worker 			pr_warn("failed to get section(%d) header from %s\n",
1140*f7c14bbaSAndroid Build Coastguard Worker 				idx, path);
1141*f7c14bbaSAndroid Build Coastguard Worker 			goto done;
1142*f7c14bbaSAndroid Build Coastguard Worker 		}
1143*f7c14bbaSAndroid Build Coastguard Worker 		name = elf_strptr(elf, shstrndx, sh.sh_name);
1144*f7c14bbaSAndroid Build Coastguard Worker 		if (!name) {
1145*f7c14bbaSAndroid Build Coastguard Worker 			pr_warn("failed to get section(%d) name from %s\n",
1146*f7c14bbaSAndroid Build Coastguard Worker 				idx, path);
1147*f7c14bbaSAndroid Build Coastguard Worker 			goto done;
1148*f7c14bbaSAndroid Build Coastguard Worker 		}
1149*f7c14bbaSAndroid Build Coastguard Worker 		if (strcmp(name, BTF_ELF_SEC) == 0) {
1150*f7c14bbaSAndroid Build Coastguard Worker 			btf_data = elf_getdata(scn, 0);
1151*f7c14bbaSAndroid Build Coastguard Worker 			if (!btf_data) {
1152*f7c14bbaSAndroid Build Coastguard Worker 				pr_warn("failed to get section(%d, %s) data from %s\n",
1153*f7c14bbaSAndroid Build Coastguard Worker 					idx, name, path);
1154*f7c14bbaSAndroid Build Coastguard Worker 				goto done;
1155*f7c14bbaSAndroid Build Coastguard Worker 			}
1156*f7c14bbaSAndroid Build Coastguard Worker 			continue;
1157*f7c14bbaSAndroid Build Coastguard Worker 		} else if (btf_ext && strcmp(name, BTF_EXT_ELF_SEC) == 0) {
1158*f7c14bbaSAndroid Build Coastguard Worker 			btf_ext_data = elf_getdata(scn, 0);
1159*f7c14bbaSAndroid Build Coastguard Worker 			if (!btf_ext_data) {
1160*f7c14bbaSAndroid Build Coastguard Worker 				pr_warn("failed to get section(%d, %s) data from %s\n",
1161*f7c14bbaSAndroid Build Coastguard Worker 					idx, name, path);
1162*f7c14bbaSAndroid Build Coastguard Worker 				goto done;
1163*f7c14bbaSAndroid Build Coastguard Worker 			}
1164*f7c14bbaSAndroid Build Coastguard Worker 			continue;
1165*f7c14bbaSAndroid Build Coastguard Worker 		}
1166*f7c14bbaSAndroid Build Coastguard Worker 	}
1167*f7c14bbaSAndroid Build Coastguard Worker 
1168*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_data) {
1169*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to find '%s' ELF section in %s\n", BTF_ELF_SEC, path);
1170*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENODATA;
1171*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1172*f7c14bbaSAndroid Build Coastguard Worker 	}
1173*f7c14bbaSAndroid Build Coastguard Worker 	btf = btf_new(btf_data->d_buf, btf_data->d_size, base_btf);
1174*f7c14bbaSAndroid Build Coastguard Worker 	err = libbpf_get_error(btf);
1175*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
1176*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1177*f7c14bbaSAndroid Build Coastguard Worker 
1178*f7c14bbaSAndroid Build Coastguard Worker 	switch (gelf_getclass(elf)) {
1179*f7c14bbaSAndroid Build Coastguard Worker 	case ELFCLASS32:
1180*f7c14bbaSAndroid Build Coastguard Worker 		btf__set_pointer_size(btf, 4);
1181*f7c14bbaSAndroid Build Coastguard Worker 		break;
1182*f7c14bbaSAndroid Build Coastguard Worker 	case ELFCLASS64:
1183*f7c14bbaSAndroid Build Coastguard Worker 		btf__set_pointer_size(btf, 8);
1184*f7c14bbaSAndroid Build Coastguard Worker 		break;
1185*f7c14bbaSAndroid Build Coastguard Worker 	default:
1186*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("failed to get ELF class (bitness) for %s\n", path);
1187*f7c14bbaSAndroid Build Coastguard Worker 		break;
1188*f7c14bbaSAndroid Build Coastguard Worker 	}
1189*f7c14bbaSAndroid Build Coastguard Worker 
1190*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ext && btf_ext_data) {
1191*f7c14bbaSAndroid Build Coastguard Worker 		*btf_ext = btf_ext__new(btf_ext_data->d_buf, btf_ext_data->d_size);
1192*f7c14bbaSAndroid Build Coastguard Worker 		err = libbpf_get_error(*btf_ext);
1193*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
1194*f7c14bbaSAndroid Build Coastguard Worker 			goto done;
1195*f7c14bbaSAndroid Build Coastguard Worker 	} else if (btf_ext) {
1196*f7c14bbaSAndroid Build Coastguard Worker 		*btf_ext = NULL;
1197*f7c14bbaSAndroid Build Coastguard Worker 	}
1198*f7c14bbaSAndroid Build Coastguard Worker done:
1199*f7c14bbaSAndroid Build Coastguard Worker 	if (elf)
1200*f7c14bbaSAndroid Build Coastguard Worker 		elf_end(elf);
1201*f7c14bbaSAndroid Build Coastguard Worker 	close(fd);
1202*f7c14bbaSAndroid Build Coastguard Worker 
1203*f7c14bbaSAndroid Build Coastguard Worker 	if (!err)
1204*f7c14bbaSAndroid Build Coastguard Worker 		return btf;
1205*f7c14bbaSAndroid Build Coastguard Worker 
1206*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ext)
1207*f7c14bbaSAndroid Build Coastguard Worker 		btf_ext__free(*btf_ext);
1208*f7c14bbaSAndroid Build Coastguard Worker 	btf__free(btf);
1209*f7c14bbaSAndroid Build Coastguard Worker 
1210*f7c14bbaSAndroid Build Coastguard Worker 	return ERR_PTR(err);
1211*f7c14bbaSAndroid Build Coastguard Worker }
1212*f7c14bbaSAndroid Build Coastguard Worker 
btf__parse_elf(const char * path,struct btf_ext ** btf_ext)1213*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext)
1214*f7c14bbaSAndroid Build Coastguard Worker {
1215*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_parse_elf(path, NULL, btf_ext));
1216*f7c14bbaSAndroid Build Coastguard Worker }
1217*f7c14bbaSAndroid Build Coastguard Worker 
btf__parse_elf_split(const char * path,struct btf * base_btf)1218*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__parse_elf_split(const char *path, struct btf *base_btf)
1219*f7c14bbaSAndroid Build Coastguard Worker {
1220*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_parse_elf(path, base_btf, NULL));
1221*f7c14bbaSAndroid Build Coastguard Worker }
1222*f7c14bbaSAndroid Build Coastguard Worker 
btf_parse_raw(const char * path,struct btf * base_btf)1223*f7c14bbaSAndroid Build Coastguard Worker static struct btf *btf_parse_raw(const char *path, struct btf *base_btf)
1224*f7c14bbaSAndroid Build Coastguard Worker {
1225*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf = NULL;
1226*f7c14bbaSAndroid Build Coastguard Worker 	void *data = NULL;
1227*f7c14bbaSAndroid Build Coastguard Worker 	FILE *f = NULL;
1228*f7c14bbaSAndroid Build Coastguard Worker 	__u16 magic;
1229*f7c14bbaSAndroid Build Coastguard Worker 	int err = 0;
1230*f7c14bbaSAndroid Build Coastguard Worker 	long sz;
1231*f7c14bbaSAndroid Build Coastguard Worker 
1232*f7c14bbaSAndroid Build Coastguard Worker 	f = fopen(path, "rbe");
1233*f7c14bbaSAndroid Build Coastguard Worker 	if (!f) {
1234*f7c14bbaSAndroid Build Coastguard Worker 		err = -errno;
1235*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1236*f7c14bbaSAndroid Build Coastguard Worker 	}
1237*f7c14bbaSAndroid Build Coastguard Worker 
1238*f7c14bbaSAndroid Build Coastguard Worker 	/* check BTF magic */
1239*f7c14bbaSAndroid Build Coastguard Worker 	if (fread(&magic, 1, sizeof(magic), f) < sizeof(magic)) {
1240*f7c14bbaSAndroid Build Coastguard Worker 		err = -EIO;
1241*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1242*f7c14bbaSAndroid Build Coastguard Worker 	}
1243*f7c14bbaSAndroid Build Coastguard Worker 	if (magic != BTF_MAGIC && magic != bswap_16(BTF_MAGIC)) {
1244*f7c14bbaSAndroid Build Coastguard Worker 		/* definitely not a raw BTF */
1245*f7c14bbaSAndroid Build Coastguard Worker 		err = -EPROTO;
1246*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1247*f7c14bbaSAndroid Build Coastguard Worker 	}
1248*f7c14bbaSAndroid Build Coastguard Worker 
1249*f7c14bbaSAndroid Build Coastguard Worker 	/* get file size */
1250*f7c14bbaSAndroid Build Coastguard Worker 	if (fseek(f, 0, SEEK_END)) {
1251*f7c14bbaSAndroid Build Coastguard Worker 		err = -errno;
1252*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1253*f7c14bbaSAndroid Build Coastguard Worker 	}
1254*f7c14bbaSAndroid Build Coastguard Worker 	sz = ftell(f);
1255*f7c14bbaSAndroid Build Coastguard Worker 	if (sz < 0) {
1256*f7c14bbaSAndroid Build Coastguard Worker 		err = -errno;
1257*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1258*f7c14bbaSAndroid Build Coastguard Worker 	}
1259*f7c14bbaSAndroid Build Coastguard Worker 	/* rewind to the start */
1260*f7c14bbaSAndroid Build Coastguard Worker 	if (fseek(f, 0, SEEK_SET)) {
1261*f7c14bbaSAndroid Build Coastguard Worker 		err = -errno;
1262*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1263*f7c14bbaSAndroid Build Coastguard Worker 	}
1264*f7c14bbaSAndroid Build Coastguard Worker 
1265*f7c14bbaSAndroid Build Coastguard Worker 	/* pre-alloc memory and read all of BTF data */
1266*f7c14bbaSAndroid Build Coastguard Worker 	data = malloc(sz);
1267*f7c14bbaSAndroid Build Coastguard Worker 	if (!data) {
1268*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENOMEM;
1269*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1270*f7c14bbaSAndroid Build Coastguard Worker 	}
1271*f7c14bbaSAndroid Build Coastguard Worker 	if (fread(data, 1, sz, f) < sz) {
1272*f7c14bbaSAndroid Build Coastguard Worker 		err = -EIO;
1273*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1274*f7c14bbaSAndroid Build Coastguard Worker 	}
1275*f7c14bbaSAndroid Build Coastguard Worker 
1276*f7c14bbaSAndroid Build Coastguard Worker 	/* finally parse BTF data */
1277*f7c14bbaSAndroid Build Coastguard Worker 	btf = btf_new(data, sz, base_btf);
1278*f7c14bbaSAndroid Build Coastguard Worker 
1279*f7c14bbaSAndroid Build Coastguard Worker err_out:
1280*f7c14bbaSAndroid Build Coastguard Worker 	free(data);
1281*f7c14bbaSAndroid Build Coastguard Worker 	if (f)
1282*f7c14bbaSAndroid Build Coastguard Worker 		fclose(f);
1283*f7c14bbaSAndroid Build Coastguard Worker 	return err ? ERR_PTR(err) : btf;
1284*f7c14bbaSAndroid Build Coastguard Worker }
1285*f7c14bbaSAndroid Build Coastguard Worker 
btf__parse_raw(const char * path)1286*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__parse_raw(const char *path)
1287*f7c14bbaSAndroid Build Coastguard Worker {
1288*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_parse_raw(path, NULL));
1289*f7c14bbaSAndroid Build Coastguard Worker }
1290*f7c14bbaSAndroid Build Coastguard Worker 
btf__parse_raw_split(const char * path,struct btf * base_btf)1291*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__parse_raw_split(const char *path, struct btf *base_btf)
1292*f7c14bbaSAndroid Build Coastguard Worker {
1293*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_parse_raw(path, base_btf));
1294*f7c14bbaSAndroid Build Coastguard Worker }
1295*f7c14bbaSAndroid Build Coastguard Worker 
btf_parse(const char * path,struct btf * base_btf,struct btf_ext ** btf_ext)1296*f7c14bbaSAndroid Build Coastguard Worker static struct btf *btf_parse(const char *path, struct btf *base_btf, struct btf_ext **btf_ext)
1297*f7c14bbaSAndroid Build Coastguard Worker {
1298*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf;
1299*f7c14bbaSAndroid Build Coastguard Worker 	int err;
1300*f7c14bbaSAndroid Build Coastguard Worker 
1301*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ext)
1302*f7c14bbaSAndroid Build Coastguard Worker 		*btf_ext = NULL;
1303*f7c14bbaSAndroid Build Coastguard Worker 
1304*f7c14bbaSAndroid Build Coastguard Worker 	btf = btf_parse_raw(path, base_btf);
1305*f7c14bbaSAndroid Build Coastguard Worker 	err = libbpf_get_error(btf);
1306*f7c14bbaSAndroid Build Coastguard Worker 	if (!err)
1307*f7c14bbaSAndroid Build Coastguard Worker 		return btf;
1308*f7c14bbaSAndroid Build Coastguard Worker 	if (err != -EPROTO)
1309*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(err);
1310*f7c14bbaSAndroid Build Coastguard Worker 	return btf_parse_elf(path, base_btf, btf_ext);
1311*f7c14bbaSAndroid Build Coastguard Worker }
1312*f7c14bbaSAndroid Build Coastguard Worker 
btf__parse(const char * path,struct btf_ext ** btf_ext)1313*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__parse(const char *path, struct btf_ext **btf_ext)
1314*f7c14bbaSAndroid Build Coastguard Worker {
1315*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_parse(path, NULL, btf_ext));
1316*f7c14bbaSAndroid Build Coastguard Worker }
1317*f7c14bbaSAndroid Build Coastguard Worker 
btf__parse_split(const char * path,struct btf * base_btf)1318*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__parse_split(const char *path, struct btf *base_btf)
1319*f7c14bbaSAndroid Build Coastguard Worker {
1320*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf_parse(path, base_btf, NULL));
1321*f7c14bbaSAndroid Build Coastguard Worker }
1322*f7c14bbaSAndroid Build Coastguard Worker 
1323*f7c14bbaSAndroid Build Coastguard Worker static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endian);
1324*f7c14bbaSAndroid Build Coastguard Worker 
btf_load_into_kernel(struct btf * btf,char * log_buf,size_t log_sz,__u32 log_level,int token_fd)1325*f7c14bbaSAndroid Build Coastguard Worker int btf_load_into_kernel(struct btf *btf,
1326*f7c14bbaSAndroid Build Coastguard Worker 			 char *log_buf, size_t log_sz, __u32 log_level,
1327*f7c14bbaSAndroid Build Coastguard Worker 			 int token_fd)
1328*f7c14bbaSAndroid Build Coastguard Worker {
1329*f7c14bbaSAndroid Build Coastguard Worker 	LIBBPF_OPTS(bpf_btf_load_opts, opts);
1330*f7c14bbaSAndroid Build Coastguard Worker 	__u32 buf_sz = 0, raw_size;
1331*f7c14bbaSAndroid Build Coastguard Worker 	char *buf = NULL, *tmp;
1332*f7c14bbaSAndroid Build Coastguard Worker 	void *raw_data;
1333*f7c14bbaSAndroid Build Coastguard Worker 	int err = 0;
1334*f7c14bbaSAndroid Build Coastguard Worker 
1335*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->fd >= 0)
1336*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EEXIST);
1337*f7c14bbaSAndroid Build Coastguard Worker 	if (log_sz && !log_buf)
1338*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
1339*f7c14bbaSAndroid Build Coastguard Worker 
1340*f7c14bbaSAndroid Build Coastguard Worker 	/* cache native raw data representation */
1341*f7c14bbaSAndroid Build Coastguard Worker 	raw_data = btf_get_raw_data(btf, &raw_size, false);
1342*f7c14bbaSAndroid Build Coastguard Worker 	if (!raw_data) {
1343*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENOMEM;
1344*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
1345*f7c14bbaSAndroid Build Coastguard Worker 	}
1346*f7c14bbaSAndroid Build Coastguard Worker 	btf->raw_size = raw_size;
1347*f7c14bbaSAndroid Build Coastguard Worker 	btf->raw_data = raw_data;
1348*f7c14bbaSAndroid Build Coastguard Worker 
1349*f7c14bbaSAndroid Build Coastguard Worker retry_load:
1350*f7c14bbaSAndroid Build Coastguard Worker 	/* if log_level is 0, we won't provide log_buf/log_size to the kernel,
1351*f7c14bbaSAndroid Build Coastguard Worker 	 * initially. Only if BTF loading fails, we bump log_level to 1 and
1352*f7c14bbaSAndroid Build Coastguard Worker 	 * retry, using either auto-allocated or custom log_buf. This way
1353*f7c14bbaSAndroid Build Coastguard Worker 	 * non-NULL custom log_buf provides a buffer just in case, but hopes
1354*f7c14bbaSAndroid Build Coastguard Worker 	 * for successful load and no need for log_buf.
1355*f7c14bbaSAndroid Build Coastguard Worker 	 */
1356*f7c14bbaSAndroid Build Coastguard Worker 	if (log_level) {
1357*f7c14bbaSAndroid Build Coastguard Worker 		/* if caller didn't provide custom log_buf, we'll keep
1358*f7c14bbaSAndroid Build Coastguard Worker 		 * allocating our own progressively bigger buffers for BTF
1359*f7c14bbaSAndroid Build Coastguard Worker 		 * verification log
1360*f7c14bbaSAndroid Build Coastguard Worker 		 */
1361*f7c14bbaSAndroid Build Coastguard Worker 		if (!log_buf) {
1362*f7c14bbaSAndroid Build Coastguard Worker 			buf_sz = max((__u32)BPF_LOG_BUF_SIZE, buf_sz * 2);
1363*f7c14bbaSAndroid Build Coastguard Worker 			tmp = realloc(buf, buf_sz);
1364*f7c14bbaSAndroid Build Coastguard Worker 			if (!tmp) {
1365*f7c14bbaSAndroid Build Coastguard Worker 				err = -ENOMEM;
1366*f7c14bbaSAndroid Build Coastguard Worker 				goto done;
1367*f7c14bbaSAndroid Build Coastguard Worker 			}
1368*f7c14bbaSAndroid Build Coastguard Worker 			buf = tmp;
1369*f7c14bbaSAndroid Build Coastguard Worker 			buf[0] = '\0';
1370*f7c14bbaSAndroid Build Coastguard Worker 		}
1371*f7c14bbaSAndroid Build Coastguard Worker 
1372*f7c14bbaSAndroid Build Coastguard Worker 		opts.log_buf = log_buf ? log_buf : buf;
1373*f7c14bbaSAndroid Build Coastguard Worker 		opts.log_size = log_buf ? log_sz : buf_sz;
1374*f7c14bbaSAndroid Build Coastguard Worker 		opts.log_level = log_level;
1375*f7c14bbaSAndroid Build Coastguard Worker 	}
1376*f7c14bbaSAndroid Build Coastguard Worker 
1377*f7c14bbaSAndroid Build Coastguard Worker 	opts.token_fd = token_fd;
1378*f7c14bbaSAndroid Build Coastguard Worker 	if (token_fd)
1379*f7c14bbaSAndroid Build Coastguard Worker 		opts.btf_flags |= BPF_F_TOKEN_FD;
1380*f7c14bbaSAndroid Build Coastguard Worker 
1381*f7c14bbaSAndroid Build Coastguard Worker 	btf->fd = bpf_btf_load(raw_data, raw_size, &opts);
1382*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->fd < 0) {
1383*f7c14bbaSAndroid Build Coastguard Worker 		/* time to turn on verbose mode and try again */
1384*f7c14bbaSAndroid Build Coastguard Worker 		if (log_level == 0) {
1385*f7c14bbaSAndroid Build Coastguard Worker 			log_level = 1;
1386*f7c14bbaSAndroid Build Coastguard Worker 			goto retry_load;
1387*f7c14bbaSAndroid Build Coastguard Worker 		}
1388*f7c14bbaSAndroid Build Coastguard Worker 		/* only retry if caller didn't provide custom log_buf, but
1389*f7c14bbaSAndroid Build Coastguard Worker 		 * make sure we can never overflow buf_sz
1390*f7c14bbaSAndroid Build Coastguard Worker 		 */
1391*f7c14bbaSAndroid Build Coastguard Worker 		if (!log_buf && errno == ENOSPC && buf_sz <= UINT_MAX / 2)
1392*f7c14bbaSAndroid Build Coastguard Worker 			goto retry_load;
1393*f7c14bbaSAndroid Build Coastguard Worker 
1394*f7c14bbaSAndroid Build Coastguard Worker 		err = -errno;
1395*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("BTF loading error: %d\n", err);
1396*f7c14bbaSAndroid Build Coastguard Worker 		/* don't print out contents of custom log_buf */
1397*f7c14bbaSAndroid Build Coastguard Worker 		if (!log_buf && buf[0])
1398*f7c14bbaSAndroid Build Coastguard Worker 			pr_warn("-- BEGIN BTF LOAD LOG ---\n%s\n-- END BTF LOAD LOG --\n", buf);
1399*f7c14bbaSAndroid Build Coastguard Worker 	}
1400*f7c14bbaSAndroid Build Coastguard Worker 
1401*f7c14bbaSAndroid Build Coastguard Worker done:
1402*f7c14bbaSAndroid Build Coastguard Worker 	free(buf);
1403*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_err(err);
1404*f7c14bbaSAndroid Build Coastguard Worker }
1405*f7c14bbaSAndroid Build Coastguard Worker 
btf__load_into_kernel(struct btf * btf)1406*f7c14bbaSAndroid Build Coastguard Worker int btf__load_into_kernel(struct btf *btf)
1407*f7c14bbaSAndroid Build Coastguard Worker {
1408*f7c14bbaSAndroid Build Coastguard Worker 	return btf_load_into_kernel(btf, NULL, 0, 0, 0);
1409*f7c14bbaSAndroid Build Coastguard Worker }
1410*f7c14bbaSAndroid Build Coastguard Worker 
btf__fd(const struct btf * btf)1411*f7c14bbaSAndroid Build Coastguard Worker int btf__fd(const struct btf *btf)
1412*f7c14bbaSAndroid Build Coastguard Worker {
1413*f7c14bbaSAndroid Build Coastguard Worker 	return btf->fd;
1414*f7c14bbaSAndroid Build Coastguard Worker }
1415*f7c14bbaSAndroid Build Coastguard Worker 
btf__set_fd(struct btf * btf,int fd)1416*f7c14bbaSAndroid Build Coastguard Worker void btf__set_fd(struct btf *btf, int fd)
1417*f7c14bbaSAndroid Build Coastguard Worker {
1418*f7c14bbaSAndroid Build Coastguard Worker 	btf->fd = fd;
1419*f7c14bbaSAndroid Build Coastguard Worker }
1420*f7c14bbaSAndroid Build Coastguard Worker 
btf_strs_data(const struct btf * btf)1421*f7c14bbaSAndroid Build Coastguard Worker static const void *btf_strs_data(const struct btf *btf)
1422*f7c14bbaSAndroid Build Coastguard Worker {
1423*f7c14bbaSAndroid Build Coastguard Worker 	return btf->strs_data ? btf->strs_data : strset__data(btf->strs_set);
1424*f7c14bbaSAndroid Build Coastguard Worker }
1425*f7c14bbaSAndroid Build Coastguard Worker 
btf_get_raw_data(const struct btf * btf,__u32 * size,bool swap_endian)1426*f7c14bbaSAndroid Build Coastguard Worker static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endian)
1427*f7c14bbaSAndroid Build Coastguard Worker {
1428*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_header *hdr = btf->hdr;
1429*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
1430*f7c14bbaSAndroid Build Coastguard Worker 	void *data, *p;
1431*f7c14bbaSAndroid Build Coastguard Worker 	__u32 data_sz;
1432*f7c14bbaSAndroid Build Coastguard Worker 	int i;
1433*f7c14bbaSAndroid Build Coastguard Worker 
1434*f7c14bbaSAndroid Build Coastguard Worker 	data = swap_endian ? btf->raw_data_swapped : btf->raw_data;
1435*f7c14bbaSAndroid Build Coastguard Worker 	if (data) {
1436*f7c14bbaSAndroid Build Coastguard Worker 		*size = btf->raw_size;
1437*f7c14bbaSAndroid Build Coastguard Worker 		return data;
1438*f7c14bbaSAndroid Build Coastguard Worker 	}
1439*f7c14bbaSAndroid Build Coastguard Worker 
1440*f7c14bbaSAndroid Build Coastguard Worker 	data_sz = hdr->hdr_len + hdr->type_len + hdr->str_len;
1441*f7c14bbaSAndroid Build Coastguard Worker 	data = calloc(1, data_sz);
1442*f7c14bbaSAndroid Build Coastguard Worker 	if (!data)
1443*f7c14bbaSAndroid Build Coastguard Worker 		return NULL;
1444*f7c14bbaSAndroid Build Coastguard Worker 	p = data;
1445*f7c14bbaSAndroid Build Coastguard Worker 
1446*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(p, hdr, hdr->hdr_len);
1447*f7c14bbaSAndroid Build Coastguard Worker 	if (swap_endian)
1448*f7c14bbaSAndroid Build Coastguard Worker 		btf_bswap_hdr(p);
1449*f7c14bbaSAndroid Build Coastguard Worker 	p += hdr->hdr_len;
1450*f7c14bbaSAndroid Build Coastguard Worker 
1451*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(p, btf->types_data, hdr->type_len);
1452*f7c14bbaSAndroid Build Coastguard Worker 	if (swap_endian) {
1453*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < btf->nr_types; i++) {
1454*f7c14bbaSAndroid Build Coastguard Worker 			t = p + btf->type_offs[i];
1455*f7c14bbaSAndroid Build Coastguard Worker 			/* btf_bswap_type_rest() relies on native t->info, so
1456*f7c14bbaSAndroid Build Coastguard Worker 			 * we swap base type info after we swapped all the
1457*f7c14bbaSAndroid Build Coastguard Worker 			 * additional information
1458*f7c14bbaSAndroid Build Coastguard Worker 			 */
1459*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_bswap_type_rest(t))
1460*f7c14bbaSAndroid Build Coastguard Worker 				goto err_out;
1461*f7c14bbaSAndroid Build Coastguard Worker 			btf_bswap_type_base(t);
1462*f7c14bbaSAndroid Build Coastguard Worker 		}
1463*f7c14bbaSAndroid Build Coastguard Worker 	}
1464*f7c14bbaSAndroid Build Coastguard Worker 	p += hdr->type_len;
1465*f7c14bbaSAndroid Build Coastguard Worker 
1466*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(p, btf_strs_data(btf), hdr->str_len);
1467*f7c14bbaSAndroid Build Coastguard Worker 	p += hdr->str_len;
1468*f7c14bbaSAndroid Build Coastguard Worker 
1469*f7c14bbaSAndroid Build Coastguard Worker 	*size = data_sz;
1470*f7c14bbaSAndroid Build Coastguard Worker 	return data;
1471*f7c14bbaSAndroid Build Coastguard Worker err_out:
1472*f7c14bbaSAndroid Build Coastguard Worker 	free(data);
1473*f7c14bbaSAndroid Build Coastguard Worker 	return NULL;
1474*f7c14bbaSAndroid Build Coastguard Worker }
1475*f7c14bbaSAndroid Build Coastguard Worker 
btf__raw_data(const struct btf * btf_ro,__u32 * size)1476*f7c14bbaSAndroid Build Coastguard Worker const void *btf__raw_data(const struct btf *btf_ro, __u32 *size)
1477*f7c14bbaSAndroid Build Coastguard Worker {
1478*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf = (struct btf *)btf_ro;
1479*f7c14bbaSAndroid Build Coastguard Worker 	__u32 data_sz;
1480*f7c14bbaSAndroid Build Coastguard Worker 	void *data;
1481*f7c14bbaSAndroid Build Coastguard Worker 
1482*f7c14bbaSAndroid Build Coastguard Worker 	data = btf_get_raw_data(btf, &data_sz, btf->swapped_endian);
1483*f7c14bbaSAndroid Build Coastguard Worker 	if (!data)
1484*f7c14bbaSAndroid Build Coastguard Worker 		return errno = ENOMEM, NULL;
1485*f7c14bbaSAndroid Build Coastguard Worker 
1486*f7c14bbaSAndroid Build Coastguard Worker 	btf->raw_size = data_sz;
1487*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->swapped_endian)
1488*f7c14bbaSAndroid Build Coastguard Worker 		btf->raw_data_swapped = data;
1489*f7c14bbaSAndroid Build Coastguard Worker 	else
1490*f7c14bbaSAndroid Build Coastguard Worker 		btf->raw_data = data;
1491*f7c14bbaSAndroid Build Coastguard Worker 	*size = data_sz;
1492*f7c14bbaSAndroid Build Coastguard Worker 	return data;
1493*f7c14bbaSAndroid Build Coastguard Worker }
1494*f7c14bbaSAndroid Build Coastguard Worker 
1495*f7c14bbaSAndroid Build Coastguard Worker __attribute__((alias("btf__raw_data")))
1496*f7c14bbaSAndroid Build Coastguard Worker const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
1497*f7c14bbaSAndroid Build Coastguard Worker 
btf__str_by_offset(const struct btf * btf,__u32 offset)1498*f7c14bbaSAndroid Build Coastguard Worker const char *btf__str_by_offset(const struct btf *btf, __u32 offset)
1499*f7c14bbaSAndroid Build Coastguard Worker {
1500*f7c14bbaSAndroid Build Coastguard Worker 	if (offset < btf->start_str_off)
1501*f7c14bbaSAndroid Build Coastguard Worker 		return btf__str_by_offset(btf->base_btf, offset);
1502*f7c14bbaSAndroid Build Coastguard Worker 	else if (offset - btf->start_str_off < btf->hdr->str_len)
1503*f7c14bbaSAndroid Build Coastguard Worker 		return btf_strs_data(btf) + (offset - btf->start_str_off);
1504*f7c14bbaSAndroid Build Coastguard Worker 	else
1505*f7c14bbaSAndroid Build Coastguard Worker 		return errno = EINVAL, NULL;
1506*f7c14bbaSAndroid Build Coastguard Worker }
1507*f7c14bbaSAndroid Build Coastguard Worker 
btf__name_by_offset(const struct btf * btf,__u32 offset)1508*f7c14bbaSAndroid Build Coastguard Worker const char *btf__name_by_offset(const struct btf *btf, __u32 offset)
1509*f7c14bbaSAndroid Build Coastguard Worker {
1510*f7c14bbaSAndroid Build Coastguard Worker 	return btf__str_by_offset(btf, offset);
1511*f7c14bbaSAndroid Build Coastguard Worker }
1512*f7c14bbaSAndroid Build Coastguard Worker 
btf_get_from_fd(int btf_fd,struct btf * base_btf)1513*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf)
1514*f7c14bbaSAndroid Build Coastguard Worker {
1515*f7c14bbaSAndroid Build Coastguard Worker 	struct bpf_btf_info btf_info;
1516*f7c14bbaSAndroid Build Coastguard Worker 	__u32 len = sizeof(btf_info);
1517*f7c14bbaSAndroid Build Coastguard Worker 	__u32 last_size;
1518*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf;
1519*f7c14bbaSAndroid Build Coastguard Worker 	void *ptr;
1520*f7c14bbaSAndroid Build Coastguard Worker 	int err;
1521*f7c14bbaSAndroid Build Coastguard Worker 
1522*f7c14bbaSAndroid Build Coastguard Worker 	/* we won't know btf_size until we call bpf_btf_get_info_by_fd(). so
1523*f7c14bbaSAndroid Build Coastguard Worker 	 * let's start with a sane default - 4KiB here - and resize it only if
1524*f7c14bbaSAndroid Build Coastguard Worker 	 * bpf_btf_get_info_by_fd() needs a bigger buffer.
1525*f7c14bbaSAndroid Build Coastguard Worker 	 */
1526*f7c14bbaSAndroid Build Coastguard Worker 	last_size = 4096;
1527*f7c14bbaSAndroid Build Coastguard Worker 	ptr = malloc(last_size);
1528*f7c14bbaSAndroid Build Coastguard Worker 	if (!ptr)
1529*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(-ENOMEM);
1530*f7c14bbaSAndroid Build Coastguard Worker 
1531*f7c14bbaSAndroid Build Coastguard Worker 	memset(&btf_info, 0, sizeof(btf_info));
1532*f7c14bbaSAndroid Build Coastguard Worker 	btf_info.btf = ptr_to_u64(ptr);
1533*f7c14bbaSAndroid Build Coastguard Worker 	btf_info.btf_size = last_size;
1534*f7c14bbaSAndroid Build Coastguard Worker 	err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len);
1535*f7c14bbaSAndroid Build Coastguard Worker 
1536*f7c14bbaSAndroid Build Coastguard Worker 	if (!err && btf_info.btf_size > last_size) {
1537*f7c14bbaSAndroid Build Coastguard Worker 		void *temp_ptr;
1538*f7c14bbaSAndroid Build Coastguard Worker 
1539*f7c14bbaSAndroid Build Coastguard Worker 		last_size = btf_info.btf_size;
1540*f7c14bbaSAndroid Build Coastguard Worker 		temp_ptr = realloc(ptr, last_size);
1541*f7c14bbaSAndroid Build Coastguard Worker 		if (!temp_ptr) {
1542*f7c14bbaSAndroid Build Coastguard Worker 			btf = ERR_PTR(-ENOMEM);
1543*f7c14bbaSAndroid Build Coastguard Worker 			goto exit_free;
1544*f7c14bbaSAndroid Build Coastguard Worker 		}
1545*f7c14bbaSAndroid Build Coastguard Worker 		ptr = temp_ptr;
1546*f7c14bbaSAndroid Build Coastguard Worker 
1547*f7c14bbaSAndroid Build Coastguard Worker 		len = sizeof(btf_info);
1548*f7c14bbaSAndroid Build Coastguard Worker 		memset(&btf_info, 0, sizeof(btf_info));
1549*f7c14bbaSAndroid Build Coastguard Worker 		btf_info.btf = ptr_to_u64(ptr);
1550*f7c14bbaSAndroid Build Coastguard Worker 		btf_info.btf_size = last_size;
1551*f7c14bbaSAndroid Build Coastguard Worker 
1552*f7c14bbaSAndroid Build Coastguard Worker 		err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len);
1553*f7c14bbaSAndroid Build Coastguard Worker 	}
1554*f7c14bbaSAndroid Build Coastguard Worker 
1555*f7c14bbaSAndroid Build Coastguard Worker 	if (err || btf_info.btf_size > last_size) {
1556*f7c14bbaSAndroid Build Coastguard Worker 		btf = err ? ERR_PTR(-errno) : ERR_PTR(-E2BIG);
1557*f7c14bbaSAndroid Build Coastguard Worker 		goto exit_free;
1558*f7c14bbaSAndroid Build Coastguard Worker 	}
1559*f7c14bbaSAndroid Build Coastguard Worker 
1560*f7c14bbaSAndroid Build Coastguard Worker 	btf = btf_new(ptr, btf_info.btf_size, base_btf);
1561*f7c14bbaSAndroid Build Coastguard Worker 
1562*f7c14bbaSAndroid Build Coastguard Worker exit_free:
1563*f7c14bbaSAndroid Build Coastguard Worker 	free(ptr);
1564*f7c14bbaSAndroid Build Coastguard Worker 	return btf;
1565*f7c14bbaSAndroid Build Coastguard Worker }
1566*f7c14bbaSAndroid Build Coastguard Worker 
btf__load_from_kernel_by_id_split(__u32 id,struct btf * base_btf)1567*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf)
1568*f7c14bbaSAndroid Build Coastguard Worker {
1569*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf;
1570*f7c14bbaSAndroid Build Coastguard Worker 	int btf_fd;
1571*f7c14bbaSAndroid Build Coastguard Worker 
1572*f7c14bbaSAndroid Build Coastguard Worker 	btf_fd = bpf_btf_get_fd_by_id(id);
1573*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_fd < 0)
1574*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err_ptr(-errno);
1575*f7c14bbaSAndroid Build Coastguard Worker 
1576*f7c14bbaSAndroid Build Coastguard Worker 	btf = btf_get_from_fd(btf_fd, base_btf);
1577*f7c14bbaSAndroid Build Coastguard Worker 	close(btf_fd);
1578*f7c14bbaSAndroid Build Coastguard Worker 
1579*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_ptr(btf);
1580*f7c14bbaSAndroid Build Coastguard Worker }
1581*f7c14bbaSAndroid Build Coastguard Worker 
btf__load_from_kernel_by_id(__u32 id)1582*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__load_from_kernel_by_id(__u32 id)
1583*f7c14bbaSAndroid Build Coastguard Worker {
1584*f7c14bbaSAndroid Build Coastguard Worker 	return btf__load_from_kernel_by_id_split(id, NULL);
1585*f7c14bbaSAndroid Build Coastguard Worker }
1586*f7c14bbaSAndroid Build Coastguard Worker 
btf_invalidate_raw_data(struct btf * btf)1587*f7c14bbaSAndroid Build Coastguard Worker static void btf_invalidate_raw_data(struct btf *btf)
1588*f7c14bbaSAndroid Build Coastguard Worker {
1589*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->raw_data) {
1590*f7c14bbaSAndroid Build Coastguard Worker 		free(btf->raw_data);
1591*f7c14bbaSAndroid Build Coastguard Worker 		btf->raw_data = NULL;
1592*f7c14bbaSAndroid Build Coastguard Worker 	}
1593*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->raw_data_swapped) {
1594*f7c14bbaSAndroid Build Coastguard Worker 		free(btf->raw_data_swapped);
1595*f7c14bbaSAndroid Build Coastguard Worker 		btf->raw_data_swapped = NULL;
1596*f7c14bbaSAndroid Build Coastguard Worker 	}
1597*f7c14bbaSAndroid Build Coastguard Worker }
1598*f7c14bbaSAndroid Build Coastguard Worker 
1599*f7c14bbaSAndroid Build Coastguard Worker /* Ensure BTF is ready to be modified (by splitting into a three memory
1600*f7c14bbaSAndroid Build Coastguard Worker  * regions for header, types, and strings). Also invalidate cached
1601*f7c14bbaSAndroid Build Coastguard Worker  * raw_data, if any.
1602*f7c14bbaSAndroid Build Coastguard Worker  */
btf_ensure_modifiable(struct btf * btf)1603*f7c14bbaSAndroid Build Coastguard Worker static int btf_ensure_modifiable(struct btf *btf)
1604*f7c14bbaSAndroid Build Coastguard Worker {
1605*f7c14bbaSAndroid Build Coastguard Worker 	void *hdr, *types;
1606*f7c14bbaSAndroid Build Coastguard Worker 	struct strset *set = NULL;
1607*f7c14bbaSAndroid Build Coastguard Worker 	int err = -ENOMEM;
1608*f7c14bbaSAndroid Build Coastguard Worker 
1609*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_is_modifiable(btf)) {
1610*f7c14bbaSAndroid Build Coastguard Worker 		/* any BTF modification invalidates raw_data */
1611*f7c14bbaSAndroid Build Coastguard Worker 		btf_invalidate_raw_data(btf);
1612*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
1613*f7c14bbaSAndroid Build Coastguard Worker 	}
1614*f7c14bbaSAndroid Build Coastguard Worker 
1615*f7c14bbaSAndroid Build Coastguard Worker 	/* split raw data into three memory regions */
1616*f7c14bbaSAndroid Build Coastguard Worker 	hdr = malloc(btf->hdr->hdr_len);
1617*f7c14bbaSAndroid Build Coastguard Worker 	types = malloc(btf->hdr->type_len);
1618*f7c14bbaSAndroid Build Coastguard Worker 	if (!hdr || !types)
1619*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1620*f7c14bbaSAndroid Build Coastguard Worker 
1621*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(hdr, btf->hdr, btf->hdr->hdr_len);
1622*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(types, btf->types_data, btf->hdr->type_len);
1623*f7c14bbaSAndroid Build Coastguard Worker 
1624*f7c14bbaSAndroid Build Coastguard Worker 	/* build lookup index for all strings */
1625*f7c14bbaSAndroid Build Coastguard Worker 	set = strset__new(BTF_MAX_STR_OFFSET, btf->strs_data, btf->hdr->str_len);
1626*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR(set)) {
1627*f7c14bbaSAndroid Build Coastguard Worker 		err = PTR_ERR(set);
1628*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
1629*f7c14bbaSAndroid Build Coastguard Worker 	}
1630*f7c14bbaSAndroid Build Coastguard Worker 
1631*f7c14bbaSAndroid Build Coastguard Worker 	/* only when everything was successful, update internal state */
1632*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr = hdr;
1633*f7c14bbaSAndroid Build Coastguard Worker 	btf->types_data = types;
1634*f7c14bbaSAndroid Build Coastguard Worker 	btf->types_data_cap = btf->hdr->type_len;
1635*f7c14bbaSAndroid Build Coastguard Worker 	btf->strs_data = NULL;
1636*f7c14bbaSAndroid Build Coastguard Worker 	btf->strs_set = set;
1637*f7c14bbaSAndroid Build Coastguard Worker 	/* if BTF was created from scratch, all strings are guaranteed to be
1638*f7c14bbaSAndroid Build Coastguard Worker 	 * unique and deduplicated
1639*f7c14bbaSAndroid Build Coastguard Worker 	 */
1640*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->hdr->str_len == 0)
1641*f7c14bbaSAndroid Build Coastguard Worker 		btf->strs_deduped = true;
1642*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf->base_btf && btf->hdr->str_len == 1)
1643*f7c14bbaSAndroid Build Coastguard Worker 		btf->strs_deduped = true;
1644*f7c14bbaSAndroid Build Coastguard Worker 
1645*f7c14bbaSAndroid Build Coastguard Worker 	/* invalidate raw_data representation */
1646*f7c14bbaSAndroid Build Coastguard Worker 	btf_invalidate_raw_data(btf);
1647*f7c14bbaSAndroid Build Coastguard Worker 
1648*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
1649*f7c14bbaSAndroid Build Coastguard Worker 
1650*f7c14bbaSAndroid Build Coastguard Worker err_out:
1651*f7c14bbaSAndroid Build Coastguard Worker 	strset__free(set);
1652*f7c14bbaSAndroid Build Coastguard Worker 	free(hdr);
1653*f7c14bbaSAndroid Build Coastguard Worker 	free(types);
1654*f7c14bbaSAndroid Build Coastguard Worker 	return err;
1655*f7c14bbaSAndroid Build Coastguard Worker }
1656*f7c14bbaSAndroid Build Coastguard Worker 
1657*f7c14bbaSAndroid Build Coastguard Worker /* Find an offset in BTF string section that corresponds to a given string *s*.
1658*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
1659*f7c14bbaSAndroid Build Coastguard Worker  *   - >0 offset into string section, if string is found;
1660*f7c14bbaSAndroid Build Coastguard Worker  *   - -ENOENT, if string is not in the string section;
1661*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on any other error.
1662*f7c14bbaSAndroid Build Coastguard Worker  */
btf__find_str(struct btf * btf,const char * s)1663*f7c14bbaSAndroid Build Coastguard Worker int btf__find_str(struct btf *btf, const char *s)
1664*f7c14bbaSAndroid Build Coastguard Worker {
1665*f7c14bbaSAndroid Build Coastguard Worker 	int off;
1666*f7c14bbaSAndroid Build Coastguard Worker 
1667*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->base_btf) {
1668*f7c14bbaSAndroid Build Coastguard Worker 		off = btf__find_str(btf->base_btf, s);
1669*f7c14bbaSAndroid Build Coastguard Worker 		if (off != -ENOENT)
1670*f7c14bbaSAndroid Build Coastguard Worker 			return off;
1671*f7c14bbaSAndroid Build Coastguard Worker 	}
1672*f7c14bbaSAndroid Build Coastguard Worker 
1673*f7c14bbaSAndroid Build Coastguard Worker 	/* BTF needs to be in a modifiable state to build string lookup index */
1674*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
1675*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1676*f7c14bbaSAndroid Build Coastguard Worker 
1677*f7c14bbaSAndroid Build Coastguard Worker 	off = strset__find_str(btf->strs_set, s);
1678*f7c14bbaSAndroid Build Coastguard Worker 	if (off < 0)
1679*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(off);
1680*f7c14bbaSAndroid Build Coastguard Worker 
1681*f7c14bbaSAndroid Build Coastguard Worker 	return btf->start_str_off + off;
1682*f7c14bbaSAndroid Build Coastguard Worker }
1683*f7c14bbaSAndroid Build Coastguard Worker 
1684*f7c14bbaSAndroid Build Coastguard Worker /* Add a string s to the BTF string section.
1685*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
1686*f7c14bbaSAndroid Build Coastguard Worker  *   - > 0 offset into string section, on success;
1687*f7c14bbaSAndroid Build Coastguard Worker  *   - < 0, on error.
1688*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_str(struct btf * btf,const char * s)1689*f7c14bbaSAndroid Build Coastguard Worker int btf__add_str(struct btf *btf, const char *s)
1690*f7c14bbaSAndroid Build Coastguard Worker {
1691*f7c14bbaSAndroid Build Coastguard Worker 	int off;
1692*f7c14bbaSAndroid Build Coastguard Worker 
1693*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->base_btf) {
1694*f7c14bbaSAndroid Build Coastguard Worker 		off = btf__find_str(btf->base_btf, s);
1695*f7c14bbaSAndroid Build Coastguard Worker 		if (off != -ENOENT)
1696*f7c14bbaSAndroid Build Coastguard Worker 			return off;
1697*f7c14bbaSAndroid Build Coastguard Worker 	}
1698*f7c14bbaSAndroid Build Coastguard Worker 
1699*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
1700*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1701*f7c14bbaSAndroid Build Coastguard Worker 
1702*f7c14bbaSAndroid Build Coastguard Worker 	off = strset__add_str(btf->strs_set, s);
1703*f7c14bbaSAndroid Build Coastguard Worker 	if (off < 0)
1704*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(off);
1705*f7c14bbaSAndroid Build Coastguard Worker 
1706*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_len = strset__data_size(btf->strs_set);
1707*f7c14bbaSAndroid Build Coastguard Worker 
1708*f7c14bbaSAndroid Build Coastguard Worker 	return btf->start_str_off + off;
1709*f7c14bbaSAndroid Build Coastguard Worker }
1710*f7c14bbaSAndroid Build Coastguard Worker 
btf_add_type_mem(struct btf * btf,size_t add_sz)1711*f7c14bbaSAndroid Build Coastguard Worker static void *btf_add_type_mem(struct btf *btf, size_t add_sz)
1712*f7c14bbaSAndroid Build Coastguard Worker {
1713*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_add_mem(&btf->types_data, &btf->types_data_cap, 1,
1714*f7c14bbaSAndroid Build Coastguard Worker 			      btf->hdr->type_len, UINT_MAX, add_sz);
1715*f7c14bbaSAndroid Build Coastguard Worker }
1716*f7c14bbaSAndroid Build Coastguard Worker 
btf_type_inc_vlen(struct btf_type * t)1717*f7c14bbaSAndroid Build Coastguard Worker static void btf_type_inc_vlen(struct btf_type *t)
1718*f7c14bbaSAndroid Build Coastguard Worker {
1719*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, btf_kflag(t));
1720*f7c14bbaSAndroid Build Coastguard Worker }
1721*f7c14bbaSAndroid Build Coastguard Worker 
btf_commit_type(struct btf * btf,int data_sz)1722*f7c14bbaSAndroid Build Coastguard Worker static int btf_commit_type(struct btf *btf, int data_sz)
1723*f7c14bbaSAndroid Build Coastguard Worker {
1724*f7c14bbaSAndroid Build Coastguard Worker 	int err;
1725*f7c14bbaSAndroid Build Coastguard Worker 
1726*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_add_type_idx_entry(btf, btf->hdr->type_len);
1727*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
1728*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(err);
1729*f7c14bbaSAndroid Build Coastguard Worker 
1730*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->type_len += data_sz;
1731*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_off += data_sz;
1732*f7c14bbaSAndroid Build Coastguard Worker 	btf->nr_types++;
1733*f7c14bbaSAndroid Build Coastguard Worker 	return btf->start_id + btf->nr_types - 1;
1734*f7c14bbaSAndroid Build Coastguard Worker }
1735*f7c14bbaSAndroid Build Coastguard Worker 
1736*f7c14bbaSAndroid Build Coastguard Worker struct btf_pipe {
1737*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf *src;
1738*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *dst;
1739*f7c14bbaSAndroid Build Coastguard Worker 	struct hashmap *str_off_map; /* map string offsets from src to dst */
1740*f7c14bbaSAndroid Build Coastguard Worker };
1741*f7c14bbaSAndroid Build Coastguard Worker 
btf_rewrite_str(__u32 * str_off,void * ctx)1742*f7c14bbaSAndroid Build Coastguard Worker static int btf_rewrite_str(__u32 *str_off, void *ctx)
1743*f7c14bbaSAndroid Build Coastguard Worker {
1744*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_pipe *p = ctx;
1745*f7c14bbaSAndroid Build Coastguard Worker 	long mapped_off;
1746*f7c14bbaSAndroid Build Coastguard Worker 	int off, err;
1747*f7c14bbaSAndroid Build Coastguard Worker 
1748*f7c14bbaSAndroid Build Coastguard Worker 	if (!*str_off) /* nothing to do for empty strings */
1749*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
1750*f7c14bbaSAndroid Build Coastguard Worker 
1751*f7c14bbaSAndroid Build Coastguard Worker 	if (p->str_off_map &&
1752*f7c14bbaSAndroid Build Coastguard Worker 	    hashmap__find(p->str_off_map, *str_off, &mapped_off)) {
1753*f7c14bbaSAndroid Build Coastguard Worker 		*str_off = mapped_off;
1754*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
1755*f7c14bbaSAndroid Build Coastguard Worker 	}
1756*f7c14bbaSAndroid Build Coastguard Worker 
1757*f7c14bbaSAndroid Build Coastguard Worker 	off = btf__add_str(p->dst, btf__str_by_offset(p->src, *str_off));
1758*f7c14bbaSAndroid Build Coastguard Worker 	if (off < 0)
1759*f7c14bbaSAndroid Build Coastguard Worker 		return off;
1760*f7c14bbaSAndroid Build Coastguard Worker 
1761*f7c14bbaSAndroid Build Coastguard Worker 	/* Remember string mapping from src to dst.  It avoids
1762*f7c14bbaSAndroid Build Coastguard Worker 	 * performing expensive string comparisons.
1763*f7c14bbaSAndroid Build Coastguard Worker 	 */
1764*f7c14bbaSAndroid Build Coastguard Worker 	if (p->str_off_map) {
1765*f7c14bbaSAndroid Build Coastguard Worker 		err = hashmap__append(p->str_off_map, *str_off, off);
1766*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
1767*f7c14bbaSAndroid Build Coastguard Worker 			return err;
1768*f7c14bbaSAndroid Build Coastguard Worker 	}
1769*f7c14bbaSAndroid Build Coastguard Worker 
1770*f7c14bbaSAndroid Build Coastguard Worker 	*str_off = off;
1771*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
1772*f7c14bbaSAndroid Build Coastguard Worker }
1773*f7c14bbaSAndroid Build Coastguard Worker 
btf__add_type(struct btf * btf,const struct btf * src_btf,const struct btf_type * src_type)1774*f7c14bbaSAndroid Build Coastguard Worker int btf__add_type(struct btf *btf, const struct btf *src_btf, const struct btf_type *src_type)
1775*f7c14bbaSAndroid Build Coastguard Worker {
1776*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_pipe p = { .src = src_btf, .dst = btf };
1777*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
1778*f7c14bbaSAndroid Build Coastguard Worker 	int sz, err;
1779*f7c14bbaSAndroid Build Coastguard Worker 
1780*f7c14bbaSAndroid Build Coastguard Worker 	sz = btf_type_size(src_type);
1781*f7c14bbaSAndroid Build Coastguard Worker 	if (sz < 0)
1782*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(sz);
1783*f7c14bbaSAndroid Build Coastguard Worker 
1784*f7c14bbaSAndroid Build Coastguard Worker 	/* deconstruct BTF, if necessary, and invalidate raw_data */
1785*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
1786*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1787*f7c14bbaSAndroid Build Coastguard Worker 
1788*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
1789*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
1790*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1791*f7c14bbaSAndroid Build Coastguard Worker 
1792*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(t, src_type, sz);
1793*f7c14bbaSAndroid Build Coastguard Worker 
1794*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_type_visit_str_offs(t, btf_rewrite_str, &p);
1795*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
1796*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(err);
1797*f7c14bbaSAndroid Build Coastguard Worker 
1798*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
1799*f7c14bbaSAndroid Build Coastguard Worker }
1800*f7c14bbaSAndroid Build Coastguard Worker 
btf_rewrite_type_ids(__u32 * type_id,void * ctx)1801*f7c14bbaSAndroid Build Coastguard Worker static int btf_rewrite_type_ids(__u32 *type_id, void *ctx)
1802*f7c14bbaSAndroid Build Coastguard Worker {
1803*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf = ctx;
1804*f7c14bbaSAndroid Build Coastguard Worker 
1805*f7c14bbaSAndroid Build Coastguard Worker 	if (!*type_id) /* nothing to do for VOID references */
1806*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
1807*f7c14bbaSAndroid Build Coastguard Worker 
1808*f7c14bbaSAndroid Build Coastguard Worker 	/* we haven't updated btf's type count yet, so
1809*f7c14bbaSAndroid Build Coastguard Worker 	 * btf->start_id + btf->nr_types - 1 is the type ID offset we should
1810*f7c14bbaSAndroid Build Coastguard Worker 	 * add to all newly added BTF types
1811*f7c14bbaSAndroid Build Coastguard Worker 	 */
1812*f7c14bbaSAndroid Build Coastguard Worker 	*type_id += btf->start_id + btf->nr_types - 1;
1813*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
1814*f7c14bbaSAndroid Build Coastguard Worker }
1815*f7c14bbaSAndroid Build Coastguard Worker 
1816*f7c14bbaSAndroid Build Coastguard Worker static size_t btf_dedup_identity_hash_fn(long key, void *ctx);
1817*f7c14bbaSAndroid Build Coastguard Worker static bool btf_dedup_equal_fn(long k1, long k2, void *ctx);
1818*f7c14bbaSAndroid Build Coastguard Worker 
btf__add_btf(struct btf * btf,const struct btf * src_btf)1819*f7c14bbaSAndroid Build Coastguard Worker int btf__add_btf(struct btf *btf, const struct btf *src_btf)
1820*f7c14bbaSAndroid Build Coastguard Worker {
1821*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_pipe p = { .src = src_btf, .dst = btf };
1822*f7c14bbaSAndroid Build Coastguard Worker 	int data_sz, sz, cnt, i, err, old_strs_len;
1823*f7c14bbaSAndroid Build Coastguard Worker 	__u32 *off;
1824*f7c14bbaSAndroid Build Coastguard Worker 	void *t;
1825*f7c14bbaSAndroid Build Coastguard Worker 
1826*f7c14bbaSAndroid Build Coastguard Worker 	/* appending split BTF isn't supported yet */
1827*f7c14bbaSAndroid Build Coastguard Worker 	if (src_btf->base_btf)
1828*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOTSUP);
1829*f7c14bbaSAndroid Build Coastguard Worker 
1830*f7c14bbaSAndroid Build Coastguard Worker 	/* deconstruct BTF, if necessary, and invalidate raw_data */
1831*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
1832*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1833*f7c14bbaSAndroid Build Coastguard Worker 
1834*f7c14bbaSAndroid Build Coastguard Worker 	/* remember original strings section size if we have to roll back
1835*f7c14bbaSAndroid Build Coastguard Worker 	 * partial strings section changes
1836*f7c14bbaSAndroid Build Coastguard Worker 	 */
1837*f7c14bbaSAndroid Build Coastguard Worker 	old_strs_len = btf->hdr->str_len;
1838*f7c14bbaSAndroid Build Coastguard Worker 
1839*f7c14bbaSAndroid Build Coastguard Worker 	data_sz = src_btf->hdr->type_len;
1840*f7c14bbaSAndroid Build Coastguard Worker 	cnt = btf__type_cnt(src_btf) - 1;
1841*f7c14bbaSAndroid Build Coastguard Worker 
1842*f7c14bbaSAndroid Build Coastguard Worker 	/* pre-allocate enough memory for new types */
1843*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, data_sz);
1844*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
1845*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1846*f7c14bbaSAndroid Build Coastguard Worker 
1847*f7c14bbaSAndroid Build Coastguard Worker 	/* pre-allocate enough memory for type offset index for new types */
1848*f7c14bbaSAndroid Build Coastguard Worker 	off = btf_add_type_offs_mem(btf, cnt);
1849*f7c14bbaSAndroid Build Coastguard Worker 	if (!off)
1850*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1851*f7c14bbaSAndroid Build Coastguard Worker 
1852*f7c14bbaSAndroid Build Coastguard Worker 	/* Map the string offsets from src_btf to the offsets from btf to improve performance */
1853*f7c14bbaSAndroid Build Coastguard Worker 	p.str_off_map = hashmap__new(btf_dedup_identity_hash_fn, btf_dedup_equal_fn, NULL);
1854*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR(p.str_off_map))
1855*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1856*f7c14bbaSAndroid Build Coastguard Worker 
1857*f7c14bbaSAndroid Build Coastguard Worker 	/* bulk copy types data for all types from src_btf */
1858*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(t, src_btf->types_data, data_sz);
1859*f7c14bbaSAndroid Build Coastguard Worker 
1860*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < cnt; i++) {
1861*f7c14bbaSAndroid Build Coastguard Worker 		sz = btf_type_size(t);
1862*f7c14bbaSAndroid Build Coastguard Worker 		if (sz < 0) {
1863*f7c14bbaSAndroid Build Coastguard Worker 			/* unlikely, has to be corrupted src_btf */
1864*f7c14bbaSAndroid Build Coastguard Worker 			err = sz;
1865*f7c14bbaSAndroid Build Coastguard Worker 			goto err_out;
1866*f7c14bbaSAndroid Build Coastguard Worker 		}
1867*f7c14bbaSAndroid Build Coastguard Worker 
1868*f7c14bbaSAndroid Build Coastguard Worker 		/* fill out type ID to type offset mapping for lookups by type ID */
1869*f7c14bbaSAndroid Build Coastguard Worker 		*off = t - btf->types_data;
1870*f7c14bbaSAndroid Build Coastguard Worker 
1871*f7c14bbaSAndroid Build Coastguard Worker 		/* add, dedup, and remap strings referenced by this BTF type */
1872*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_type_visit_str_offs(t, btf_rewrite_str, &p);
1873*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
1874*f7c14bbaSAndroid Build Coastguard Worker 			goto err_out;
1875*f7c14bbaSAndroid Build Coastguard Worker 
1876*f7c14bbaSAndroid Build Coastguard Worker 		/* remap all type IDs referenced from this BTF type */
1877*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_type_visit_type_ids(t, btf_rewrite_type_ids, btf);
1878*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
1879*f7c14bbaSAndroid Build Coastguard Worker 			goto err_out;
1880*f7c14bbaSAndroid Build Coastguard Worker 
1881*f7c14bbaSAndroid Build Coastguard Worker 		/* go to next type data and type offset index entry */
1882*f7c14bbaSAndroid Build Coastguard Worker 		t += sz;
1883*f7c14bbaSAndroid Build Coastguard Worker 		off++;
1884*f7c14bbaSAndroid Build Coastguard Worker 	}
1885*f7c14bbaSAndroid Build Coastguard Worker 
1886*f7c14bbaSAndroid Build Coastguard Worker 	/* Up until now any of the copied type data was effectively invisible,
1887*f7c14bbaSAndroid Build Coastguard Worker 	 * so if we exited early before this point due to error, BTF would be
1888*f7c14bbaSAndroid Build Coastguard Worker 	 * effectively unmodified. There would be extra internal memory
1889*f7c14bbaSAndroid Build Coastguard Worker 	 * pre-allocated, but it would not be available for querying.  But now
1890*f7c14bbaSAndroid Build Coastguard Worker 	 * that we've copied and rewritten all the data successfully, we can
1891*f7c14bbaSAndroid Build Coastguard Worker 	 * update type count and various internal offsets and sizes to
1892*f7c14bbaSAndroid Build Coastguard Worker 	 * "commit" the changes and made them visible to the outside world.
1893*f7c14bbaSAndroid Build Coastguard Worker 	 */
1894*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->type_len += data_sz;
1895*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_off += data_sz;
1896*f7c14bbaSAndroid Build Coastguard Worker 	btf->nr_types += cnt;
1897*f7c14bbaSAndroid Build Coastguard Worker 
1898*f7c14bbaSAndroid Build Coastguard Worker 	hashmap__free(p.str_off_map);
1899*f7c14bbaSAndroid Build Coastguard Worker 
1900*f7c14bbaSAndroid Build Coastguard Worker 	/* return type ID of the first added BTF type */
1901*f7c14bbaSAndroid Build Coastguard Worker 	return btf->start_id + btf->nr_types - cnt;
1902*f7c14bbaSAndroid Build Coastguard Worker err_out:
1903*f7c14bbaSAndroid Build Coastguard Worker 	/* zero out preallocated memory as if it was just allocated with
1904*f7c14bbaSAndroid Build Coastguard Worker 	 * libbpf_add_mem()
1905*f7c14bbaSAndroid Build Coastguard Worker 	 */
1906*f7c14bbaSAndroid Build Coastguard Worker 	memset(btf->types_data + btf->hdr->type_len, 0, data_sz);
1907*f7c14bbaSAndroid Build Coastguard Worker 	memset(btf->strs_data + old_strs_len, 0, btf->hdr->str_len - old_strs_len);
1908*f7c14bbaSAndroid Build Coastguard Worker 
1909*f7c14bbaSAndroid Build Coastguard Worker 	/* and now restore original strings section size; types data size
1910*f7c14bbaSAndroid Build Coastguard Worker 	 * wasn't modified, so doesn't need restoring, see big comment above
1911*f7c14bbaSAndroid Build Coastguard Worker 	 */
1912*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_len = old_strs_len;
1913*f7c14bbaSAndroid Build Coastguard Worker 
1914*f7c14bbaSAndroid Build Coastguard Worker 	hashmap__free(p.str_off_map);
1915*f7c14bbaSAndroid Build Coastguard Worker 
1916*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_err(err);
1917*f7c14bbaSAndroid Build Coastguard Worker }
1918*f7c14bbaSAndroid Build Coastguard Worker 
1919*f7c14bbaSAndroid Build Coastguard Worker /*
1920*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_INT type with:
1921*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - non-empty, non-NULL type name;
1922*f7c14bbaSAndroid Build Coastguard Worker  *   - *sz* - power-of-2 (1, 2, 4, ..) size of the type, in bytes;
1923*f7c14bbaSAndroid Build Coastguard Worker  *   - encoding is a combination of BTF_INT_SIGNED, BTF_INT_CHAR, BTF_INT_BOOL.
1924*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
1925*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
1926*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
1927*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_int(struct btf * btf,const char * name,size_t byte_sz,int encoding)1928*f7c14bbaSAndroid Build Coastguard Worker int btf__add_int(struct btf *btf, const char *name, size_t byte_sz, int encoding)
1929*f7c14bbaSAndroid Build Coastguard Worker {
1930*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
1931*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off;
1932*f7c14bbaSAndroid Build Coastguard Worker 
1933*f7c14bbaSAndroid Build Coastguard Worker 	/* non-empty name */
1934*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
1935*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
1936*f7c14bbaSAndroid Build Coastguard Worker 	/* byte_sz must be power of 2 */
1937*f7c14bbaSAndroid Build Coastguard Worker 	if (!byte_sz || (byte_sz & (byte_sz - 1)) || byte_sz > 16)
1938*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
1939*f7c14bbaSAndroid Build Coastguard Worker 	if (encoding & ~(BTF_INT_SIGNED | BTF_INT_CHAR | BTF_INT_BOOL))
1940*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
1941*f7c14bbaSAndroid Build Coastguard Worker 
1942*f7c14bbaSAndroid Build Coastguard Worker 	/* deconstruct BTF, if necessary, and invalidate raw_data */
1943*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
1944*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1945*f7c14bbaSAndroid Build Coastguard Worker 
1946*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type) + sizeof(int);
1947*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
1948*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
1949*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1950*f7c14bbaSAndroid Build Coastguard Worker 
1951*f7c14bbaSAndroid Build Coastguard Worker 	/* if something goes wrong later, we might end up with an extra string,
1952*f7c14bbaSAndroid Build Coastguard Worker 	 * but that shouldn't be a problem, because BTF can't be constructed
1953*f7c14bbaSAndroid Build Coastguard Worker 	 * completely anyway and will most probably be just discarded
1954*f7c14bbaSAndroid Build Coastguard Worker 	 */
1955*f7c14bbaSAndroid Build Coastguard Worker 	name_off = btf__add_str(btf, name);
1956*f7c14bbaSAndroid Build Coastguard Worker 	if (name_off < 0)
1957*f7c14bbaSAndroid Build Coastguard Worker 		return name_off;
1958*f7c14bbaSAndroid Build Coastguard Worker 
1959*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = name_off;
1960*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(BTF_KIND_INT, 0, 0);
1961*f7c14bbaSAndroid Build Coastguard Worker 	t->size = byte_sz;
1962*f7c14bbaSAndroid Build Coastguard Worker 	/* set INT info, we don't allow setting legacy bit offset/size */
1963*f7c14bbaSAndroid Build Coastguard Worker 	*(__u32 *)(t + 1) = (encoding << 24) | (byte_sz * 8);
1964*f7c14bbaSAndroid Build Coastguard Worker 
1965*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
1966*f7c14bbaSAndroid Build Coastguard Worker }
1967*f7c14bbaSAndroid Build Coastguard Worker 
1968*f7c14bbaSAndroid Build Coastguard Worker /*
1969*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_FLOAT type with:
1970*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - non-empty, non-NULL type name;
1971*f7c14bbaSAndroid Build Coastguard Worker  *   - *sz* - size of the type, in bytes;
1972*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
1973*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
1974*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
1975*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_float(struct btf * btf,const char * name,size_t byte_sz)1976*f7c14bbaSAndroid Build Coastguard Worker int btf__add_float(struct btf *btf, const char *name, size_t byte_sz)
1977*f7c14bbaSAndroid Build Coastguard Worker {
1978*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
1979*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off;
1980*f7c14bbaSAndroid Build Coastguard Worker 
1981*f7c14bbaSAndroid Build Coastguard Worker 	/* non-empty name */
1982*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
1983*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
1984*f7c14bbaSAndroid Build Coastguard Worker 
1985*f7c14bbaSAndroid Build Coastguard Worker 	/* byte_sz must be one of the explicitly allowed values */
1986*f7c14bbaSAndroid Build Coastguard Worker 	if (byte_sz != 2 && byte_sz != 4 && byte_sz != 8 && byte_sz != 12 &&
1987*f7c14bbaSAndroid Build Coastguard Worker 	    byte_sz != 16)
1988*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
1989*f7c14bbaSAndroid Build Coastguard Worker 
1990*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
1991*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1992*f7c14bbaSAndroid Build Coastguard Worker 
1993*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type);
1994*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
1995*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
1996*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
1997*f7c14bbaSAndroid Build Coastguard Worker 
1998*f7c14bbaSAndroid Build Coastguard Worker 	name_off = btf__add_str(btf, name);
1999*f7c14bbaSAndroid Build Coastguard Worker 	if (name_off < 0)
2000*f7c14bbaSAndroid Build Coastguard Worker 		return name_off;
2001*f7c14bbaSAndroid Build Coastguard Worker 
2002*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = name_off;
2003*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(BTF_KIND_FLOAT, 0, 0);
2004*f7c14bbaSAndroid Build Coastguard Worker 	t->size = byte_sz;
2005*f7c14bbaSAndroid Build Coastguard Worker 
2006*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2007*f7c14bbaSAndroid Build Coastguard Worker }
2008*f7c14bbaSAndroid Build Coastguard Worker 
2009*f7c14bbaSAndroid Build Coastguard Worker /* it's completely legal to append BTF types with type IDs pointing forward to
2010*f7c14bbaSAndroid Build Coastguard Worker  * types that haven't been appended yet, so we only make sure that id looks
2011*f7c14bbaSAndroid Build Coastguard Worker  * sane, we can't guarantee that ID will always be valid
2012*f7c14bbaSAndroid Build Coastguard Worker  */
validate_type_id(int id)2013*f7c14bbaSAndroid Build Coastguard Worker static int validate_type_id(int id)
2014*f7c14bbaSAndroid Build Coastguard Worker {
2015*f7c14bbaSAndroid Build Coastguard Worker 	if (id < 0 || id > BTF_MAX_NR_TYPES)
2016*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2017*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2018*f7c14bbaSAndroid Build Coastguard Worker }
2019*f7c14bbaSAndroid Build Coastguard Worker 
2020*f7c14bbaSAndroid Build Coastguard Worker /* generic append function for PTR, TYPEDEF, CONST/VOLATILE/RESTRICT */
btf_add_ref_kind(struct btf * btf,int kind,const char * name,int ref_type_id)2021*f7c14bbaSAndroid Build Coastguard Worker static int btf_add_ref_kind(struct btf *btf, int kind, const char *name, int ref_type_id)
2022*f7c14bbaSAndroid Build Coastguard Worker {
2023*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2024*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off = 0;
2025*f7c14bbaSAndroid Build Coastguard Worker 
2026*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(ref_type_id))
2027*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2028*f7c14bbaSAndroid Build Coastguard Worker 
2029*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2030*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2031*f7c14bbaSAndroid Build Coastguard Worker 
2032*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type);
2033*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2034*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2035*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2036*f7c14bbaSAndroid Build Coastguard Worker 
2037*f7c14bbaSAndroid Build Coastguard Worker 	if (name && name[0]) {
2038*f7c14bbaSAndroid Build Coastguard Worker 		name_off = btf__add_str(btf, name);
2039*f7c14bbaSAndroid Build Coastguard Worker 		if (name_off < 0)
2040*f7c14bbaSAndroid Build Coastguard Worker 			return name_off;
2041*f7c14bbaSAndroid Build Coastguard Worker 	}
2042*f7c14bbaSAndroid Build Coastguard Worker 
2043*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = name_off;
2044*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(kind, 0, 0);
2045*f7c14bbaSAndroid Build Coastguard Worker 	t->type = ref_type_id;
2046*f7c14bbaSAndroid Build Coastguard Worker 
2047*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2048*f7c14bbaSAndroid Build Coastguard Worker }
2049*f7c14bbaSAndroid Build Coastguard Worker 
2050*f7c14bbaSAndroid Build Coastguard Worker /*
2051*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_PTR type with:
2052*f7c14bbaSAndroid Build Coastguard Worker  *   - *ref_type_id* - referenced type ID, it might not exist yet;
2053*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2054*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2055*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2056*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_ptr(struct btf * btf,int ref_type_id)2057*f7c14bbaSAndroid Build Coastguard Worker int btf__add_ptr(struct btf *btf, int ref_type_id)
2058*f7c14bbaSAndroid Build Coastguard Worker {
2059*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_ref_kind(btf, BTF_KIND_PTR, NULL, ref_type_id);
2060*f7c14bbaSAndroid Build Coastguard Worker }
2061*f7c14bbaSAndroid Build Coastguard Worker 
2062*f7c14bbaSAndroid Build Coastguard Worker /*
2063*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_ARRAY type with:
2064*f7c14bbaSAndroid Build Coastguard Worker  *   - *index_type_id* - type ID of the type describing array index;
2065*f7c14bbaSAndroid Build Coastguard Worker  *   - *elem_type_id* - type ID of the type describing array element;
2066*f7c14bbaSAndroid Build Coastguard Worker  *   - *nr_elems* - the size of the array;
2067*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2068*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2069*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2070*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_array(struct btf * btf,int index_type_id,int elem_type_id,__u32 nr_elems)2071*f7c14bbaSAndroid Build Coastguard Worker int btf__add_array(struct btf *btf, int index_type_id, int elem_type_id, __u32 nr_elems)
2072*f7c14bbaSAndroid Build Coastguard Worker {
2073*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2074*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_array *a;
2075*f7c14bbaSAndroid Build Coastguard Worker 	int sz;
2076*f7c14bbaSAndroid Build Coastguard Worker 
2077*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(index_type_id) || validate_type_id(elem_type_id))
2078*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2079*f7c14bbaSAndroid Build Coastguard Worker 
2080*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2081*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2082*f7c14bbaSAndroid Build Coastguard Worker 
2083*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type) + sizeof(struct btf_array);
2084*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2085*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2086*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2087*f7c14bbaSAndroid Build Coastguard Worker 
2088*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = 0;
2089*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(BTF_KIND_ARRAY, 0, 0);
2090*f7c14bbaSAndroid Build Coastguard Worker 	t->size = 0;
2091*f7c14bbaSAndroid Build Coastguard Worker 
2092*f7c14bbaSAndroid Build Coastguard Worker 	a = btf_array(t);
2093*f7c14bbaSAndroid Build Coastguard Worker 	a->type = elem_type_id;
2094*f7c14bbaSAndroid Build Coastguard Worker 	a->index_type = index_type_id;
2095*f7c14bbaSAndroid Build Coastguard Worker 	a->nelems = nr_elems;
2096*f7c14bbaSAndroid Build Coastguard Worker 
2097*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2098*f7c14bbaSAndroid Build Coastguard Worker }
2099*f7c14bbaSAndroid Build Coastguard Worker 
2100*f7c14bbaSAndroid Build Coastguard Worker /* generic STRUCT/UNION append function */
btf_add_composite(struct btf * btf,int kind,const char * name,__u32 bytes_sz)2101*f7c14bbaSAndroid Build Coastguard Worker static int btf_add_composite(struct btf *btf, int kind, const char *name, __u32 bytes_sz)
2102*f7c14bbaSAndroid Build Coastguard Worker {
2103*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2104*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off = 0;
2105*f7c14bbaSAndroid Build Coastguard Worker 
2106*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2107*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2108*f7c14bbaSAndroid Build Coastguard Worker 
2109*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type);
2110*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2111*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2112*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2113*f7c14bbaSAndroid Build Coastguard Worker 
2114*f7c14bbaSAndroid Build Coastguard Worker 	if (name && name[0]) {
2115*f7c14bbaSAndroid Build Coastguard Worker 		name_off = btf__add_str(btf, name);
2116*f7c14bbaSAndroid Build Coastguard Worker 		if (name_off < 0)
2117*f7c14bbaSAndroid Build Coastguard Worker 			return name_off;
2118*f7c14bbaSAndroid Build Coastguard Worker 	}
2119*f7c14bbaSAndroid Build Coastguard Worker 
2120*f7c14bbaSAndroid Build Coastguard Worker 	/* start out with vlen=0 and no kflag; this will be adjusted when
2121*f7c14bbaSAndroid Build Coastguard Worker 	 * adding each member
2122*f7c14bbaSAndroid Build Coastguard Worker 	 */
2123*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = name_off;
2124*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(kind, 0, 0);
2125*f7c14bbaSAndroid Build Coastguard Worker 	t->size = bytes_sz;
2126*f7c14bbaSAndroid Build Coastguard Worker 
2127*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2128*f7c14bbaSAndroid Build Coastguard Worker }
2129*f7c14bbaSAndroid Build Coastguard Worker 
2130*f7c14bbaSAndroid Build Coastguard Worker /*
2131*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_STRUCT type with:
2132*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - name of the struct, can be NULL or empty for anonymous structs;
2133*f7c14bbaSAndroid Build Coastguard Worker  *   - *byte_sz* - size of the struct, in bytes;
2134*f7c14bbaSAndroid Build Coastguard Worker  *
2135*f7c14bbaSAndroid Build Coastguard Worker  * Struct initially has no fields in it. Fields can be added by
2136*f7c14bbaSAndroid Build Coastguard Worker  * btf__add_field() right after btf__add_struct() succeeds.
2137*f7c14bbaSAndroid Build Coastguard Worker  *
2138*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2139*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2140*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2141*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_struct(struct btf * btf,const char * name,__u32 byte_sz)2142*f7c14bbaSAndroid Build Coastguard Worker int btf__add_struct(struct btf *btf, const char *name, __u32 byte_sz)
2143*f7c14bbaSAndroid Build Coastguard Worker {
2144*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_composite(btf, BTF_KIND_STRUCT, name, byte_sz);
2145*f7c14bbaSAndroid Build Coastguard Worker }
2146*f7c14bbaSAndroid Build Coastguard Worker 
2147*f7c14bbaSAndroid Build Coastguard Worker /*
2148*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_UNION type with:
2149*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - name of the union, can be NULL or empty for anonymous union;
2150*f7c14bbaSAndroid Build Coastguard Worker  *   - *byte_sz* - size of the union, in bytes;
2151*f7c14bbaSAndroid Build Coastguard Worker  *
2152*f7c14bbaSAndroid Build Coastguard Worker  * Union initially has no fields in it. Fields can be added by
2153*f7c14bbaSAndroid Build Coastguard Worker  * btf__add_field() right after btf__add_union() succeeds. All fields
2154*f7c14bbaSAndroid Build Coastguard Worker  * should have *bit_offset* of 0.
2155*f7c14bbaSAndroid Build Coastguard Worker  *
2156*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2157*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2158*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2159*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_union(struct btf * btf,const char * name,__u32 byte_sz)2160*f7c14bbaSAndroid Build Coastguard Worker int btf__add_union(struct btf *btf, const char *name, __u32 byte_sz)
2161*f7c14bbaSAndroid Build Coastguard Worker {
2162*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_composite(btf, BTF_KIND_UNION, name, byte_sz);
2163*f7c14bbaSAndroid Build Coastguard Worker }
2164*f7c14bbaSAndroid Build Coastguard Worker 
btf_last_type(struct btf * btf)2165*f7c14bbaSAndroid Build Coastguard Worker static struct btf_type *btf_last_type(struct btf *btf)
2166*f7c14bbaSAndroid Build Coastguard Worker {
2167*f7c14bbaSAndroid Build Coastguard Worker 	return btf_type_by_id(btf, btf__type_cnt(btf) - 1);
2168*f7c14bbaSAndroid Build Coastguard Worker }
2169*f7c14bbaSAndroid Build Coastguard Worker 
2170*f7c14bbaSAndroid Build Coastguard Worker /*
2171*f7c14bbaSAndroid Build Coastguard Worker  * Append new field for the current STRUCT/UNION type with:
2172*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - name of the field, can be NULL or empty for anonymous field;
2173*f7c14bbaSAndroid Build Coastguard Worker  *   - *type_id* - type ID for the type describing field type;
2174*f7c14bbaSAndroid Build Coastguard Worker  *   - *bit_offset* - bit offset of the start of the field within struct/union;
2175*f7c14bbaSAndroid Build Coastguard Worker  *   - *bit_size* - bit size of a bitfield, 0 for non-bitfield fields;
2176*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2177*f7c14bbaSAndroid Build Coastguard Worker  *   -  0, on success;
2178*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2179*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_field(struct btf * btf,const char * name,int type_id,__u32 bit_offset,__u32 bit_size)2180*f7c14bbaSAndroid Build Coastguard Worker int btf__add_field(struct btf *btf, const char *name, int type_id,
2181*f7c14bbaSAndroid Build Coastguard Worker 		   __u32 bit_offset, __u32 bit_size)
2182*f7c14bbaSAndroid Build Coastguard Worker {
2183*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2184*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_member *m;
2185*f7c14bbaSAndroid Build Coastguard Worker 	bool is_bitfield;
2186*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off = 0;
2187*f7c14bbaSAndroid Build Coastguard Worker 
2188*f7c14bbaSAndroid Build Coastguard Worker 	/* last type should be union/struct */
2189*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->nr_types == 0)
2190*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2191*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2192*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_composite(t))
2193*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2194*f7c14bbaSAndroid Build Coastguard Worker 
2195*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(type_id))
2196*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2197*f7c14bbaSAndroid Build Coastguard Worker 	/* best-effort bit field offset/size enforcement */
2198*f7c14bbaSAndroid Build Coastguard Worker 	is_bitfield = bit_size || (bit_offset % 8 != 0);
2199*f7c14bbaSAndroid Build Coastguard Worker 	if (is_bitfield && (bit_size == 0 || bit_size > 255 || bit_offset > 0xffffff))
2200*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2201*f7c14bbaSAndroid Build Coastguard Worker 
2202*f7c14bbaSAndroid Build Coastguard Worker 	/* only offset 0 is allowed for unions */
2203*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_is_union(t) && bit_offset)
2204*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2205*f7c14bbaSAndroid Build Coastguard Worker 
2206*f7c14bbaSAndroid Build Coastguard Worker 	/* decompose and invalidate raw data */
2207*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2208*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2209*f7c14bbaSAndroid Build Coastguard Worker 
2210*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_member);
2211*f7c14bbaSAndroid Build Coastguard Worker 	m = btf_add_type_mem(btf, sz);
2212*f7c14bbaSAndroid Build Coastguard Worker 	if (!m)
2213*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2214*f7c14bbaSAndroid Build Coastguard Worker 
2215*f7c14bbaSAndroid Build Coastguard Worker 	if (name && name[0]) {
2216*f7c14bbaSAndroid Build Coastguard Worker 		name_off = btf__add_str(btf, name);
2217*f7c14bbaSAndroid Build Coastguard Worker 		if (name_off < 0)
2218*f7c14bbaSAndroid Build Coastguard Worker 			return name_off;
2219*f7c14bbaSAndroid Build Coastguard Worker 	}
2220*f7c14bbaSAndroid Build Coastguard Worker 
2221*f7c14bbaSAndroid Build Coastguard Worker 	m->name_off = name_off;
2222*f7c14bbaSAndroid Build Coastguard Worker 	m->type = type_id;
2223*f7c14bbaSAndroid Build Coastguard Worker 	m->offset = bit_offset | (bit_size << 24);
2224*f7c14bbaSAndroid Build Coastguard Worker 
2225*f7c14bbaSAndroid Build Coastguard Worker 	/* btf_add_type_mem can invalidate t pointer */
2226*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2227*f7c14bbaSAndroid Build Coastguard Worker 	/* update parent type's vlen and kflag */
2228*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, is_bitfield || btf_kflag(t));
2229*f7c14bbaSAndroid Build Coastguard Worker 
2230*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->type_len += sz;
2231*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_off += sz;
2232*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2233*f7c14bbaSAndroid Build Coastguard Worker }
2234*f7c14bbaSAndroid Build Coastguard Worker 
btf_add_enum_common(struct btf * btf,const char * name,__u32 byte_sz,bool is_signed,__u8 kind)2235*f7c14bbaSAndroid Build Coastguard Worker static int btf_add_enum_common(struct btf *btf, const char *name, __u32 byte_sz,
2236*f7c14bbaSAndroid Build Coastguard Worker 			       bool is_signed, __u8 kind)
2237*f7c14bbaSAndroid Build Coastguard Worker {
2238*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2239*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off = 0;
2240*f7c14bbaSAndroid Build Coastguard Worker 
2241*f7c14bbaSAndroid Build Coastguard Worker 	/* byte_sz must be power of 2 */
2242*f7c14bbaSAndroid Build Coastguard Worker 	if (!byte_sz || (byte_sz & (byte_sz - 1)) || byte_sz > 8)
2243*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2244*f7c14bbaSAndroid Build Coastguard Worker 
2245*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2246*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2247*f7c14bbaSAndroid Build Coastguard Worker 
2248*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type);
2249*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2250*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2251*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2252*f7c14bbaSAndroid Build Coastguard Worker 
2253*f7c14bbaSAndroid Build Coastguard Worker 	if (name && name[0]) {
2254*f7c14bbaSAndroid Build Coastguard Worker 		name_off = btf__add_str(btf, name);
2255*f7c14bbaSAndroid Build Coastguard Worker 		if (name_off < 0)
2256*f7c14bbaSAndroid Build Coastguard Worker 			return name_off;
2257*f7c14bbaSAndroid Build Coastguard Worker 	}
2258*f7c14bbaSAndroid Build Coastguard Worker 
2259*f7c14bbaSAndroid Build Coastguard Worker 	/* start out with vlen=0; it will be adjusted when adding enum values */
2260*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = name_off;
2261*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(kind, 0, is_signed);
2262*f7c14bbaSAndroid Build Coastguard Worker 	t->size = byte_sz;
2263*f7c14bbaSAndroid Build Coastguard Worker 
2264*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2265*f7c14bbaSAndroid Build Coastguard Worker }
2266*f7c14bbaSAndroid Build Coastguard Worker 
2267*f7c14bbaSAndroid Build Coastguard Worker /*
2268*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_ENUM type with:
2269*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - name of the enum, can be NULL or empty for anonymous enums;
2270*f7c14bbaSAndroid Build Coastguard Worker  *   - *byte_sz* - size of the enum, in bytes.
2271*f7c14bbaSAndroid Build Coastguard Worker  *
2272*f7c14bbaSAndroid Build Coastguard Worker  * Enum initially has no enum values in it (and corresponds to enum forward
2273*f7c14bbaSAndroid Build Coastguard Worker  * declaration). Enumerator values can be added by btf__add_enum_value()
2274*f7c14bbaSAndroid Build Coastguard Worker  * immediately after btf__add_enum() succeeds.
2275*f7c14bbaSAndroid Build Coastguard Worker  *
2276*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2277*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2278*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2279*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_enum(struct btf * btf,const char * name,__u32 byte_sz)2280*f7c14bbaSAndroid Build Coastguard Worker int btf__add_enum(struct btf *btf, const char *name, __u32 byte_sz)
2281*f7c14bbaSAndroid Build Coastguard Worker {
2282*f7c14bbaSAndroid Build Coastguard Worker 	/*
2283*f7c14bbaSAndroid Build Coastguard Worker 	 * set the signedness to be unsigned, it will change to signed
2284*f7c14bbaSAndroid Build Coastguard Worker 	 * if any later enumerator is negative.
2285*f7c14bbaSAndroid Build Coastguard Worker 	 */
2286*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_enum_common(btf, name, byte_sz, false, BTF_KIND_ENUM);
2287*f7c14bbaSAndroid Build Coastguard Worker }
2288*f7c14bbaSAndroid Build Coastguard Worker 
2289*f7c14bbaSAndroid Build Coastguard Worker /*
2290*f7c14bbaSAndroid Build Coastguard Worker  * Append new enum value for the current ENUM type with:
2291*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - name of the enumerator value, can't be NULL or empty;
2292*f7c14bbaSAndroid Build Coastguard Worker  *   - *value* - integer value corresponding to enum value *name*;
2293*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2294*f7c14bbaSAndroid Build Coastguard Worker  *   -  0, on success;
2295*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2296*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_enum_value(struct btf * btf,const char * name,__s64 value)2297*f7c14bbaSAndroid Build Coastguard Worker int btf__add_enum_value(struct btf *btf, const char *name, __s64 value)
2298*f7c14bbaSAndroid Build Coastguard Worker {
2299*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2300*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_enum *v;
2301*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off;
2302*f7c14bbaSAndroid Build Coastguard Worker 
2303*f7c14bbaSAndroid Build Coastguard Worker 	/* last type should be BTF_KIND_ENUM */
2304*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->nr_types == 0)
2305*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2306*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2307*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_enum(t))
2308*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2309*f7c14bbaSAndroid Build Coastguard Worker 
2310*f7c14bbaSAndroid Build Coastguard Worker 	/* non-empty name */
2311*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
2312*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2313*f7c14bbaSAndroid Build Coastguard Worker 	if (value < INT_MIN || value > UINT_MAX)
2314*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-E2BIG);
2315*f7c14bbaSAndroid Build Coastguard Worker 
2316*f7c14bbaSAndroid Build Coastguard Worker 	/* decompose and invalidate raw data */
2317*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2318*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2319*f7c14bbaSAndroid Build Coastguard Worker 
2320*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_enum);
2321*f7c14bbaSAndroid Build Coastguard Worker 	v = btf_add_type_mem(btf, sz);
2322*f7c14bbaSAndroid Build Coastguard Worker 	if (!v)
2323*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2324*f7c14bbaSAndroid Build Coastguard Worker 
2325*f7c14bbaSAndroid Build Coastguard Worker 	name_off = btf__add_str(btf, name);
2326*f7c14bbaSAndroid Build Coastguard Worker 	if (name_off < 0)
2327*f7c14bbaSAndroid Build Coastguard Worker 		return name_off;
2328*f7c14bbaSAndroid Build Coastguard Worker 
2329*f7c14bbaSAndroid Build Coastguard Worker 	v->name_off = name_off;
2330*f7c14bbaSAndroid Build Coastguard Worker 	v->val = value;
2331*f7c14bbaSAndroid Build Coastguard Worker 
2332*f7c14bbaSAndroid Build Coastguard Worker 	/* update parent type's vlen */
2333*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2334*f7c14bbaSAndroid Build Coastguard Worker 	btf_type_inc_vlen(t);
2335*f7c14bbaSAndroid Build Coastguard Worker 
2336*f7c14bbaSAndroid Build Coastguard Worker 	/* if negative value, set signedness to signed */
2337*f7c14bbaSAndroid Build Coastguard Worker 	if (value < 0)
2338*f7c14bbaSAndroid Build Coastguard Worker 		t->info = btf_type_info(btf_kind(t), btf_vlen(t), true);
2339*f7c14bbaSAndroid Build Coastguard Worker 
2340*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->type_len += sz;
2341*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_off += sz;
2342*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2343*f7c14bbaSAndroid Build Coastguard Worker }
2344*f7c14bbaSAndroid Build Coastguard Worker 
2345*f7c14bbaSAndroid Build Coastguard Worker /*
2346*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_ENUM64 type with:
2347*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - name of the enum, can be NULL or empty for anonymous enums;
2348*f7c14bbaSAndroid Build Coastguard Worker  *   - *byte_sz* - size of the enum, in bytes.
2349*f7c14bbaSAndroid Build Coastguard Worker  *   - *is_signed* - whether the enum values are signed or not;
2350*f7c14bbaSAndroid Build Coastguard Worker  *
2351*f7c14bbaSAndroid Build Coastguard Worker  * Enum initially has no enum values in it (and corresponds to enum forward
2352*f7c14bbaSAndroid Build Coastguard Worker  * declaration). Enumerator values can be added by btf__add_enum64_value()
2353*f7c14bbaSAndroid Build Coastguard Worker  * immediately after btf__add_enum64() succeeds.
2354*f7c14bbaSAndroid Build Coastguard Worker  *
2355*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2356*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2357*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2358*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_enum64(struct btf * btf,const char * name,__u32 byte_sz,bool is_signed)2359*f7c14bbaSAndroid Build Coastguard Worker int btf__add_enum64(struct btf *btf, const char *name, __u32 byte_sz,
2360*f7c14bbaSAndroid Build Coastguard Worker 		    bool is_signed)
2361*f7c14bbaSAndroid Build Coastguard Worker {
2362*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_enum_common(btf, name, byte_sz, is_signed,
2363*f7c14bbaSAndroid Build Coastguard Worker 				   BTF_KIND_ENUM64);
2364*f7c14bbaSAndroid Build Coastguard Worker }
2365*f7c14bbaSAndroid Build Coastguard Worker 
2366*f7c14bbaSAndroid Build Coastguard Worker /*
2367*f7c14bbaSAndroid Build Coastguard Worker  * Append new enum value for the current ENUM64 type with:
2368*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - name of the enumerator value, can't be NULL or empty;
2369*f7c14bbaSAndroid Build Coastguard Worker  *   - *value* - integer value corresponding to enum value *name*;
2370*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2371*f7c14bbaSAndroid Build Coastguard Worker  *   -  0, on success;
2372*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2373*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_enum64_value(struct btf * btf,const char * name,__u64 value)2374*f7c14bbaSAndroid Build Coastguard Worker int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value)
2375*f7c14bbaSAndroid Build Coastguard Worker {
2376*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_enum64 *v;
2377*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2378*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off;
2379*f7c14bbaSAndroid Build Coastguard Worker 
2380*f7c14bbaSAndroid Build Coastguard Worker 	/* last type should be BTF_KIND_ENUM64 */
2381*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->nr_types == 0)
2382*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2383*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2384*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_enum64(t))
2385*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2386*f7c14bbaSAndroid Build Coastguard Worker 
2387*f7c14bbaSAndroid Build Coastguard Worker 	/* non-empty name */
2388*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
2389*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2390*f7c14bbaSAndroid Build Coastguard Worker 
2391*f7c14bbaSAndroid Build Coastguard Worker 	/* decompose and invalidate raw data */
2392*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2393*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2394*f7c14bbaSAndroid Build Coastguard Worker 
2395*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_enum64);
2396*f7c14bbaSAndroid Build Coastguard Worker 	v = btf_add_type_mem(btf, sz);
2397*f7c14bbaSAndroid Build Coastguard Worker 	if (!v)
2398*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2399*f7c14bbaSAndroid Build Coastguard Worker 
2400*f7c14bbaSAndroid Build Coastguard Worker 	name_off = btf__add_str(btf, name);
2401*f7c14bbaSAndroid Build Coastguard Worker 	if (name_off < 0)
2402*f7c14bbaSAndroid Build Coastguard Worker 		return name_off;
2403*f7c14bbaSAndroid Build Coastguard Worker 
2404*f7c14bbaSAndroid Build Coastguard Worker 	v->name_off = name_off;
2405*f7c14bbaSAndroid Build Coastguard Worker 	v->val_lo32 = (__u32)value;
2406*f7c14bbaSAndroid Build Coastguard Worker 	v->val_hi32 = value >> 32;
2407*f7c14bbaSAndroid Build Coastguard Worker 
2408*f7c14bbaSAndroid Build Coastguard Worker 	/* update parent type's vlen */
2409*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2410*f7c14bbaSAndroid Build Coastguard Worker 	btf_type_inc_vlen(t);
2411*f7c14bbaSAndroid Build Coastguard Worker 
2412*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->type_len += sz;
2413*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_off += sz;
2414*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2415*f7c14bbaSAndroid Build Coastguard Worker }
2416*f7c14bbaSAndroid Build Coastguard Worker 
2417*f7c14bbaSAndroid Build Coastguard Worker /*
2418*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_FWD type with:
2419*f7c14bbaSAndroid Build Coastguard Worker  *   - *name*, non-empty/non-NULL name;
2420*f7c14bbaSAndroid Build Coastguard Worker  *   - *fwd_kind*, kind of forward declaration, one of BTF_FWD_STRUCT,
2421*f7c14bbaSAndroid Build Coastguard Worker  *     BTF_FWD_UNION, or BTF_FWD_ENUM;
2422*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2423*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2424*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2425*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_fwd(struct btf * btf,const char * name,enum btf_fwd_kind fwd_kind)2426*f7c14bbaSAndroid Build Coastguard Worker int btf__add_fwd(struct btf *btf, const char *name, enum btf_fwd_kind fwd_kind)
2427*f7c14bbaSAndroid Build Coastguard Worker {
2428*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
2429*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2430*f7c14bbaSAndroid Build Coastguard Worker 
2431*f7c14bbaSAndroid Build Coastguard Worker 	switch (fwd_kind) {
2432*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_FWD_STRUCT:
2433*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_FWD_UNION: {
2434*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_type *t;
2435*f7c14bbaSAndroid Build Coastguard Worker 		int id;
2436*f7c14bbaSAndroid Build Coastguard Worker 
2437*f7c14bbaSAndroid Build Coastguard Worker 		id = btf_add_ref_kind(btf, BTF_KIND_FWD, name, 0);
2438*f7c14bbaSAndroid Build Coastguard Worker 		if (id <= 0)
2439*f7c14bbaSAndroid Build Coastguard Worker 			return id;
2440*f7c14bbaSAndroid Build Coastguard Worker 		t = btf_type_by_id(btf, id);
2441*f7c14bbaSAndroid Build Coastguard Worker 		t->info = btf_type_info(BTF_KIND_FWD, 0, fwd_kind == BTF_FWD_UNION);
2442*f7c14bbaSAndroid Build Coastguard Worker 		return id;
2443*f7c14bbaSAndroid Build Coastguard Worker 	}
2444*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_FWD_ENUM:
2445*f7c14bbaSAndroid Build Coastguard Worker 		/* enum forward in BTF currently is just an enum with no enum
2446*f7c14bbaSAndroid Build Coastguard Worker 		 * values; we also assume a standard 4-byte size for it
2447*f7c14bbaSAndroid Build Coastguard Worker 		 */
2448*f7c14bbaSAndroid Build Coastguard Worker 		return btf__add_enum(btf, name, sizeof(int));
2449*f7c14bbaSAndroid Build Coastguard Worker 	default:
2450*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2451*f7c14bbaSAndroid Build Coastguard Worker 	}
2452*f7c14bbaSAndroid Build Coastguard Worker }
2453*f7c14bbaSAndroid Build Coastguard Worker 
2454*f7c14bbaSAndroid Build Coastguard Worker /*
2455*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KING_TYPEDEF type with:
2456*f7c14bbaSAndroid Build Coastguard Worker  *   - *name*, non-empty/non-NULL name;
2457*f7c14bbaSAndroid Build Coastguard Worker  *   - *ref_type_id* - referenced type ID, it might not exist yet;
2458*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2459*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2460*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2461*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_typedef(struct btf * btf,const char * name,int ref_type_id)2462*f7c14bbaSAndroid Build Coastguard Worker int btf__add_typedef(struct btf *btf, const char *name, int ref_type_id)
2463*f7c14bbaSAndroid Build Coastguard Worker {
2464*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
2465*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2466*f7c14bbaSAndroid Build Coastguard Worker 
2467*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_ref_kind(btf, BTF_KIND_TYPEDEF, name, ref_type_id);
2468*f7c14bbaSAndroid Build Coastguard Worker }
2469*f7c14bbaSAndroid Build Coastguard Worker 
2470*f7c14bbaSAndroid Build Coastguard Worker /*
2471*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_VOLATILE type with:
2472*f7c14bbaSAndroid Build Coastguard Worker  *   - *ref_type_id* - referenced type ID, it might not exist yet;
2473*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2474*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2475*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2476*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_volatile(struct btf * btf,int ref_type_id)2477*f7c14bbaSAndroid Build Coastguard Worker int btf__add_volatile(struct btf *btf, int ref_type_id)
2478*f7c14bbaSAndroid Build Coastguard Worker {
2479*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_ref_kind(btf, BTF_KIND_VOLATILE, NULL, ref_type_id);
2480*f7c14bbaSAndroid Build Coastguard Worker }
2481*f7c14bbaSAndroid Build Coastguard Worker 
2482*f7c14bbaSAndroid Build Coastguard Worker /*
2483*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_CONST type with:
2484*f7c14bbaSAndroid Build Coastguard Worker  *   - *ref_type_id* - referenced type ID, it might not exist yet;
2485*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2486*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2487*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2488*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_const(struct btf * btf,int ref_type_id)2489*f7c14bbaSAndroid Build Coastguard Worker int btf__add_const(struct btf *btf, int ref_type_id)
2490*f7c14bbaSAndroid Build Coastguard Worker {
2491*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_ref_kind(btf, BTF_KIND_CONST, NULL, ref_type_id);
2492*f7c14bbaSAndroid Build Coastguard Worker }
2493*f7c14bbaSAndroid Build Coastguard Worker 
2494*f7c14bbaSAndroid Build Coastguard Worker /*
2495*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_RESTRICT type with:
2496*f7c14bbaSAndroid Build Coastguard Worker  *   - *ref_type_id* - referenced type ID, it might not exist yet;
2497*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2498*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2499*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2500*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_restrict(struct btf * btf,int ref_type_id)2501*f7c14bbaSAndroid Build Coastguard Worker int btf__add_restrict(struct btf *btf, int ref_type_id)
2502*f7c14bbaSAndroid Build Coastguard Worker {
2503*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_ref_kind(btf, BTF_KIND_RESTRICT, NULL, ref_type_id);
2504*f7c14bbaSAndroid Build Coastguard Worker }
2505*f7c14bbaSAndroid Build Coastguard Worker 
2506*f7c14bbaSAndroid Build Coastguard Worker /*
2507*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_TYPE_TAG type with:
2508*f7c14bbaSAndroid Build Coastguard Worker  *   - *value*, non-empty/non-NULL tag value;
2509*f7c14bbaSAndroid Build Coastguard Worker  *   - *ref_type_id* - referenced type ID, it might not exist yet;
2510*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2511*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2512*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2513*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_type_tag(struct btf * btf,const char * value,int ref_type_id)2514*f7c14bbaSAndroid Build Coastguard Worker int btf__add_type_tag(struct btf *btf, const char *value, int ref_type_id)
2515*f7c14bbaSAndroid Build Coastguard Worker {
2516*f7c14bbaSAndroid Build Coastguard Worker 	if (!value || !value[0])
2517*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2518*f7c14bbaSAndroid Build Coastguard Worker 
2519*f7c14bbaSAndroid Build Coastguard Worker 	return btf_add_ref_kind(btf, BTF_KIND_TYPE_TAG, value, ref_type_id);
2520*f7c14bbaSAndroid Build Coastguard Worker }
2521*f7c14bbaSAndroid Build Coastguard Worker 
2522*f7c14bbaSAndroid Build Coastguard Worker /*
2523*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_FUNC type with:
2524*f7c14bbaSAndroid Build Coastguard Worker  *   - *name*, non-empty/non-NULL name;
2525*f7c14bbaSAndroid Build Coastguard Worker  *   - *proto_type_id* - FUNC_PROTO's type ID, it might not exist yet;
2526*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2527*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2528*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2529*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_func(struct btf * btf,const char * name,enum btf_func_linkage linkage,int proto_type_id)2530*f7c14bbaSAndroid Build Coastguard Worker int btf__add_func(struct btf *btf, const char *name,
2531*f7c14bbaSAndroid Build Coastguard Worker 		  enum btf_func_linkage linkage, int proto_type_id)
2532*f7c14bbaSAndroid Build Coastguard Worker {
2533*f7c14bbaSAndroid Build Coastguard Worker 	int id;
2534*f7c14bbaSAndroid Build Coastguard Worker 
2535*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
2536*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2537*f7c14bbaSAndroid Build Coastguard Worker 	if (linkage != BTF_FUNC_STATIC && linkage != BTF_FUNC_GLOBAL &&
2538*f7c14bbaSAndroid Build Coastguard Worker 	    linkage != BTF_FUNC_EXTERN)
2539*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2540*f7c14bbaSAndroid Build Coastguard Worker 
2541*f7c14bbaSAndroid Build Coastguard Worker 	id = btf_add_ref_kind(btf, BTF_KIND_FUNC, name, proto_type_id);
2542*f7c14bbaSAndroid Build Coastguard Worker 	if (id > 0) {
2543*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_type *t = btf_type_by_id(btf, id);
2544*f7c14bbaSAndroid Build Coastguard Worker 
2545*f7c14bbaSAndroid Build Coastguard Worker 		t->info = btf_type_info(BTF_KIND_FUNC, linkage, 0);
2546*f7c14bbaSAndroid Build Coastguard Worker 	}
2547*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_err(id);
2548*f7c14bbaSAndroid Build Coastguard Worker }
2549*f7c14bbaSAndroid Build Coastguard Worker 
2550*f7c14bbaSAndroid Build Coastguard Worker /*
2551*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_FUNC_PROTO with:
2552*f7c14bbaSAndroid Build Coastguard Worker  *   - *ret_type_id* - type ID for return result of a function.
2553*f7c14bbaSAndroid Build Coastguard Worker  *
2554*f7c14bbaSAndroid Build Coastguard Worker  * Function prototype initially has no arguments, but they can be added by
2555*f7c14bbaSAndroid Build Coastguard Worker  * btf__add_func_param() one by one, immediately after
2556*f7c14bbaSAndroid Build Coastguard Worker  * btf__add_func_proto() succeeded.
2557*f7c14bbaSAndroid Build Coastguard Worker  *
2558*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2559*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2560*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2561*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_func_proto(struct btf * btf,int ret_type_id)2562*f7c14bbaSAndroid Build Coastguard Worker int btf__add_func_proto(struct btf *btf, int ret_type_id)
2563*f7c14bbaSAndroid Build Coastguard Worker {
2564*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2565*f7c14bbaSAndroid Build Coastguard Worker 	int sz;
2566*f7c14bbaSAndroid Build Coastguard Worker 
2567*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(ret_type_id))
2568*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2569*f7c14bbaSAndroid Build Coastguard Worker 
2570*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2571*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2572*f7c14bbaSAndroid Build Coastguard Worker 
2573*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type);
2574*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2575*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2576*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2577*f7c14bbaSAndroid Build Coastguard Worker 
2578*f7c14bbaSAndroid Build Coastguard Worker 	/* start out with vlen=0; this will be adjusted when adding enum
2579*f7c14bbaSAndroid Build Coastguard Worker 	 * values, if necessary
2580*f7c14bbaSAndroid Build Coastguard Worker 	 */
2581*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = 0;
2582*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(BTF_KIND_FUNC_PROTO, 0, 0);
2583*f7c14bbaSAndroid Build Coastguard Worker 	t->type = ret_type_id;
2584*f7c14bbaSAndroid Build Coastguard Worker 
2585*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2586*f7c14bbaSAndroid Build Coastguard Worker }
2587*f7c14bbaSAndroid Build Coastguard Worker 
2588*f7c14bbaSAndroid Build Coastguard Worker /*
2589*f7c14bbaSAndroid Build Coastguard Worker  * Append new function parameter for current FUNC_PROTO type with:
2590*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - parameter name, can be NULL or empty;
2591*f7c14bbaSAndroid Build Coastguard Worker  *   - *type_id* - type ID describing the type of the parameter.
2592*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2593*f7c14bbaSAndroid Build Coastguard Worker  *   -  0, on success;
2594*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2595*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_func_param(struct btf * btf,const char * name,int type_id)2596*f7c14bbaSAndroid Build Coastguard Worker int btf__add_func_param(struct btf *btf, const char *name, int type_id)
2597*f7c14bbaSAndroid Build Coastguard Worker {
2598*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2599*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_param *p;
2600*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off = 0;
2601*f7c14bbaSAndroid Build Coastguard Worker 
2602*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(type_id))
2603*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2604*f7c14bbaSAndroid Build Coastguard Worker 
2605*f7c14bbaSAndroid Build Coastguard Worker 	/* last type should be BTF_KIND_FUNC_PROTO */
2606*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->nr_types == 0)
2607*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2608*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2609*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_func_proto(t))
2610*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2611*f7c14bbaSAndroid Build Coastguard Worker 
2612*f7c14bbaSAndroid Build Coastguard Worker 	/* decompose and invalidate raw data */
2613*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2614*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2615*f7c14bbaSAndroid Build Coastguard Worker 
2616*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_param);
2617*f7c14bbaSAndroid Build Coastguard Worker 	p = btf_add_type_mem(btf, sz);
2618*f7c14bbaSAndroid Build Coastguard Worker 	if (!p)
2619*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2620*f7c14bbaSAndroid Build Coastguard Worker 
2621*f7c14bbaSAndroid Build Coastguard Worker 	if (name && name[0]) {
2622*f7c14bbaSAndroid Build Coastguard Worker 		name_off = btf__add_str(btf, name);
2623*f7c14bbaSAndroid Build Coastguard Worker 		if (name_off < 0)
2624*f7c14bbaSAndroid Build Coastguard Worker 			return name_off;
2625*f7c14bbaSAndroid Build Coastguard Worker 	}
2626*f7c14bbaSAndroid Build Coastguard Worker 
2627*f7c14bbaSAndroid Build Coastguard Worker 	p->name_off = name_off;
2628*f7c14bbaSAndroid Build Coastguard Worker 	p->type = type_id;
2629*f7c14bbaSAndroid Build Coastguard Worker 
2630*f7c14bbaSAndroid Build Coastguard Worker 	/* update parent type's vlen */
2631*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2632*f7c14bbaSAndroid Build Coastguard Worker 	btf_type_inc_vlen(t);
2633*f7c14bbaSAndroid Build Coastguard Worker 
2634*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->type_len += sz;
2635*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_off += sz;
2636*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2637*f7c14bbaSAndroid Build Coastguard Worker }
2638*f7c14bbaSAndroid Build Coastguard Worker 
2639*f7c14bbaSAndroid Build Coastguard Worker /*
2640*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_VAR type with:
2641*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - non-empty/non-NULL name;
2642*f7c14bbaSAndroid Build Coastguard Worker  *   - *linkage* - variable linkage, one of BTF_VAR_STATIC,
2643*f7c14bbaSAndroid Build Coastguard Worker  *     BTF_VAR_GLOBAL_ALLOCATED, or BTF_VAR_GLOBAL_EXTERN;
2644*f7c14bbaSAndroid Build Coastguard Worker  *   - *type_id* - type ID of the type describing the type of the variable.
2645*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2646*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2647*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2648*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_var(struct btf * btf,const char * name,int linkage,int type_id)2649*f7c14bbaSAndroid Build Coastguard Worker int btf__add_var(struct btf *btf, const char *name, int linkage, int type_id)
2650*f7c14bbaSAndroid Build Coastguard Worker {
2651*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2652*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_var *v;
2653*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off;
2654*f7c14bbaSAndroid Build Coastguard Worker 
2655*f7c14bbaSAndroid Build Coastguard Worker 	/* non-empty name */
2656*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
2657*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2658*f7c14bbaSAndroid Build Coastguard Worker 	if (linkage != BTF_VAR_STATIC && linkage != BTF_VAR_GLOBAL_ALLOCATED &&
2659*f7c14bbaSAndroid Build Coastguard Worker 	    linkage != BTF_VAR_GLOBAL_EXTERN)
2660*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2661*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(type_id))
2662*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2663*f7c14bbaSAndroid Build Coastguard Worker 
2664*f7c14bbaSAndroid Build Coastguard Worker 	/* deconstruct BTF, if necessary, and invalidate raw_data */
2665*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2666*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2667*f7c14bbaSAndroid Build Coastguard Worker 
2668*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type) + sizeof(struct btf_var);
2669*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2670*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2671*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2672*f7c14bbaSAndroid Build Coastguard Worker 
2673*f7c14bbaSAndroid Build Coastguard Worker 	name_off = btf__add_str(btf, name);
2674*f7c14bbaSAndroid Build Coastguard Worker 	if (name_off < 0)
2675*f7c14bbaSAndroid Build Coastguard Worker 		return name_off;
2676*f7c14bbaSAndroid Build Coastguard Worker 
2677*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = name_off;
2678*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(BTF_KIND_VAR, 0, 0);
2679*f7c14bbaSAndroid Build Coastguard Worker 	t->type = type_id;
2680*f7c14bbaSAndroid Build Coastguard Worker 
2681*f7c14bbaSAndroid Build Coastguard Worker 	v = btf_var(t);
2682*f7c14bbaSAndroid Build Coastguard Worker 	v->linkage = linkage;
2683*f7c14bbaSAndroid Build Coastguard Worker 
2684*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2685*f7c14bbaSAndroid Build Coastguard Worker }
2686*f7c14bbaSAndroid Build Coastguard Worker 
2687*f7c14bbaSAndroid Build Coastguard Worker /*
2688*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_DATASEC type with:
2689*f7c14bbaSAndroid Build Coastguard Worker  *   - *name* - non-empty/non-NULL name;
2690*f7c14bbaSAndroid Build Coastguard Worker  *   - *byte_sz* - data section size, in bytes.
2691*f7c14bbaSAndroid Build Coastguard Worker  *
2692*f7c14bbaSAndroid Build Coastguard Worker  * Data section is initially empty. Variables info can be added with
2693*f7c14bbaSAndroid Build Coastguard Worker  * btf__add_datasec_var_info() calls, after btf__add_datasec() succeeds.
2694*f7c14bbaSAndroid Build Coastguard Worker  *
2695*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2696*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2697*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2698*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_datasec(struct btf * btf,const char * name,__u32 byte_sz)2699*f7c14bbaSAndroid Build Coastguard Worker int btf__add_datasec(struct btf *btf, const char *name, __u32 byte_sz)
2700*f7c14bbaSAndroid Build Coastguard Worker {
2701*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2702*f7c14bbaSAndroid Build Coastguard Worker 	int sz, name_off;
2703*f7c14bbaSAndroid Build Coastguard Worker 
2704*f7c14bbaSAndroid Build Coastguard Worker 	/* non-empty name */
2705*f7c14bbaSAndroid Build Coastguard Worker 	if (!name || !name[0])
2706*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2707*f7c14bbaSAndroid Build Coastguard Worker 
2708*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2709*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2710*f7c14bbaSAndroid Build Coastguard Worker 
2711*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type);
2712*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2713*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2714*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2715*f7c14bbaSAndroid Build Coastguard Worker 
2716*f7c14bbaSAndroid Build Coastguard Worker 	name_off = btf__add_str(btf, name);
2717*f7c14bbaSAndroid Build Coastguard Worker 	if (name_off < 0)
2718*f7c14bbaSAndroid Build Coastguard Worker 		return name_off;
2719*f7c14bbaSAndroid Build Coastguard Worker 
2720*f7c14bbaSAndroid Build Coastguard Worker 	/* start with vlen=0, which will be update as var_secinfos are added */
2721*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = name_off;
2722*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(BTF_KIND_DATASEC, 0, 0);
2723*f7c14bbaSAndroid Build Coastguard Worker 	t->size = byte_sz;
2724*f7c14bbaSAndroid Build Coastguard Worker 
2725*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2726*f7c14bbaSAndroid Build Coastguard Worker }
2727*f7c14bbaSAndroid Build Coastguard Worker 
2728*f7c14bbaSAndroid Build Coastguard Worker /*
2729*f7c14bbaSAndroid Build Coastguard Worker  * Append new data section variable information entry for current DATASEC type:
2730*f7c14bbaSAndroid Build Coastguard Worker  *   - *var_type_id* - type ID, describing type of the variable;
2731*f7c14bbaSAndroid Build Coastguard Worker  *   - *offset* - variable offset within data section, in bytes;
2732*f7c14bbaSAndroid Build Coastguard Worker  *   - *byte_sz* - variable size, in bytes.
2733*f7c14bbaSAndroid Build Coastguard Worker  *
2734*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2735*f7c14bbaSAndroid Build Coastguard Worker  *   -  0, on success;
2736*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2737*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_datasec_var_info(struct btf * btf,int var_type_id,__u32 offset,__u32 byte_sz)2738*f7c14bbaSAndroid Build Coastguard Worker int btf__add_datasec_var_info(struct btf *btf, int var_type_id, __u32 offset, __u32 byte_sz)
2739*f7c14bbaSAndroid Build Coastguard Worker {
2740*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2741*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_var_secinfo *v;
2742*f7c14bbaSAndroid Build Coastguard Worker 	int sz;
2743*f7c14bbaSAndroid Build Coastguard Worker 
2744*f7c14bbaSAndroid Build Coastguard Worker 	/* last type should be BTF_KIND_DATASEC */
2745*f7c14bbaSAndroid Build Coastguard Worker 	if (btf->nr_types == 0)
2746*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2747*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2748*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_datasec(t))
2749*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2750*f7c14bbaSAndroid Build Coastguard Worker 
2751*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(var_type_id))
2752*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2753*f7c14bbaSAndroid Build Coastguard Worker 
2754*f7c14bbaSAndroid Build Coastguard Worker 	/* decompose and invalidate raw data */
2755*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2756*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2757*f7c14bbaSAndroid Build Coastguard Worker 
2758*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_var_secinfo);
2759*f7c14bbaSAndroid Build Coastguard Worker 	v = btf_add_type_mem(btf, sz);
2760*f7c14bbaSAndroid Build Coastguard Worker 	if (!v)
2761*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2762*f7c14bbaSAndroid Build Coastguard Worker 
2763*f7c14bbaSAndroid Build Coastguard Worker 	v->type = var_type_id;
2764*f7c14bbaSAndroid Build Coastguard Worker 	v->offset = offset;
2765*f7c14bbaSAndroid Build Coastguard Worker 	v->size = byte_sz;
2766*f7c14bbaSAndroid Build Coastguard Worker 
2767*f7c14bbaSAndroid Build Coastguard Worker 	/* update parent type's vlen */
2768*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_last_type(btf);
2769*f7c14bbaSAndroid Build Coastguard Worker 	btf_type_inc_vlen(t);
2770*f7c14bbaSAndroid Build Coastguard Worker 
2771*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->type_len += sz;
2772*f7c14bbaSAndroid Build Coastguard Worker 	btf->hdr->str_off += sz;
2773*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2774*f7c14bbaSAndroid Build Coastguard Worker }
2775*f7c14bbaSAndroid Build Coastguard Worker 
2776*f7c14bbaSAndroid Build Coastguard Worker /*
2777*f7c14bbaSAndroid Build Coastguard Worker  * Append new BTF_KIND_DECL_TAG type with:
2778*f7c14bbaSAndroid Build Coastguard Worker  *   - *value* - non-empty/non-NULL string;
2779*f7c14bbaSAndroid Build Coastguard Worker  *   - *ref_type_id* - referenced type ID, it might not exist yet;
2780*f7c14bbaSAndroid Build Coastguard Worker  *   - *component_idx* - -1 for tagging reference type, otherwise struct/union
2781*f7c14bbaSAndroid Build Coastguard Worker  *     member or function argument index;
2782*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
2783*f7c14bbaSAndroid Build Coastguard Worker  *   - >0, type ID of newly added BTF type;
2784*f7c14bbaSAndroid Build Coastguard Worker  *   - <0, on error.
2785*f7c14bbaSAndroid Build Coastguard Worker  */
btf__add_decl_tag(struct btf * btf,const char * value,int ref_type_id,int component_idx)2786*f7c14bbaSAndroid Build Coastguard Worker int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id,
2787*f7c14bbaSAndroid Build Coastguard Worker 		 int component_idx)
2788*f7c14bbaSAndroid Build Coastguard Worker {
2789*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
2790*f7c14bbaSAndroid Build Coastguard Worker 	int sz, value_off;
2791*f7c14bbaSAndroid Build Coastguard Worker 
2792*f7c14bbaSAndroid Build Coastguard Worker 	if (!value || !value[0] || component_idx < -1)
2793*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2794*f7c14bbaSAndroid Build Coastguard Worker 
2795*f7c14bbaSAndroid Build Coastguard Worker 	if (validate_type_id(ref_type_id))
2796*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
2797*f7c14bbaSAndroid Build Coastguard Worker 
2798*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf))
2799*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2800*f7c14bbaSAndroid Build Coastguard Worker 
2801*f7c14bbaSAndroid Build Coastguard Worker 	sz = sizeof(struct btf_type) + sizeof(struct btf_decl_tag);
2802*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_add_type_mem(btf, sz);
2803*f7c14bbaSAndroid Build Coastguard Worker 	if (!t)
2804*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-ENOMEM);
2805*f7c14bbaSAndroid Build Coastguard Worker 
2806*f7c14bbaSAndroid Build Coastguard Worker 	value_off = btf__add_str(btf, value);
2807*f7c14bbaSAndroid Build Coastguard Worker 	if (value_off < 0)
2808*f7c14bbaSAndroid Build Coastguard Worker 		return value_off;
2809*f7c14bbaSAndroid Build Coastguard Worker 
2810*f7c14bbaSAndroid Build Coastguard Worker 	t->name_off = value_off;
2811*f7c14bbaSAndroid Build Coastguard Worker 	t->info = btf_type_info(BTF_KIND_DECL_TAG, 0, false);
2812*f7c14bbaSAndroid Build Coastguard Worker 	t->type = ref_type_id;
2813*f7c14bbaSAndroid Build Coastguard Worker 	btf_decl_tag(t)->component_idx = component_idx;
2814*f7c14bbaSAndroid Build Coastguard Worker 
2815*f7c14bbaSAndroid Build Coastguard Worker 	return btf_commit_type(btf, sz);
2816*f7c14bbaSAndroid Build Coastguard Worker }
2817*f7c14bbaSAndroid Build Coastguard Worker 
2818*f7c14bbaSAndroid Build Coastguard Worker struct btf_ext_sec_setup_param {
2819*f7c14bbaSAndroid Build Coastguard Worker 	__u32 off;
2820*f7c14bbaSAndroid Build Coastguard Worker 	__u32 len;
2821*f7c14bbaSAndroid Build Coastguard Worker 	__u32 min_rec_size;
2822*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext_info *ext_info;
2823*f7c14bbaSAndroid Build Coastguard Worker 	const char *desc;
2824*f7c14bbaSAndroid Build Coastguard Worker };
2825*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext_setup_info(struct btf_ext * btf_ext,struct btf_ext_sec_setup_param * ext_sec)2826*f7c14bbaSAndroid Build Coastguard Worker static int btf_ext_setup_info(struct btf_ext *btf_ext,
2827*f7c14bbaSAndroid Build Coastguard Worker 			      struct btf_ext_sec_setup_param *ext_sec)
2828*f7c14bbaSAndroid Build Coastguard Worker {
2829*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_ext_info_sec *sinfo;
2830*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext_info *ext_info;
2831*f7c14bbaSAndroid Build Coastguard Worker 	__u32 info_left, record_size;
2832*f7c14bbaSAndroid Build Coastguard Worker 	size_t sec_cnt = 0;
2833*f7c14bbaSAndroid Build Coastguard Worker 	/* The start of the info sec (including the __u32 record_size). */
2834*f7c14bbaSAndroid Build Coastguard Worker 	void *info;
2835*f7c14bbaSAndroid Build Coastguard Worker 
2836*f7c14bbaSAndroid Build Coastguard Worker 	if (ext_sec->len == 0)
2837*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
2838*f7c14bbaSAndroid Build Coastguard Worker 
2839*f7c14bbaSAndroid Build Coastguard Worker 	if (ext_sec->off & 0x03) {
2840*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n",
2841*f7c14bbaSAndroid Build Coastguard Worker 		     ext_sec->desc);
2842*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2843*f7c14bbaSAndroid Build Coastguard Worker 	}
2844*f7c14bbaSAndroid Build Coastguard Worker 
2845*f7c14bbaSAndroid Build Coastguard Worker 	info = btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off;
2846*f7c14bbaSAndroid Build Coastguard Worker 	info_left = ext_sec->len;
2847*f7c14bbaSAndroid Build Coastguard Worker 
2848*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ext->data + btf_ext->data_size < info + ext_sec->len) {
2849*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
2850*f7c14bbaSAndroid Build Coastguard Worker 			 ext_sec->desc, ext_sec->off, ext_sec->len);
2851*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2852*f7c14bbaSAndroid Build Coastguard Worker 	}
2853*f7c14bbaSAndroid Build Coastguard Worker 
2854*f7c14bbaSAndroid Build Coastguard Worker 	/* At least a record size */
2855*f7c14bbaSAndroid Build Coastguard Worker 	if (info_left < sizeof(__u32)) {
2856*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc);
2857*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2858*f7c14bbaSAndroid Build Coastguard Worker 	}
2859*f7c14bbaSAndroid Build Coastguard Worker 
2860*f7c14bbaSAndroid Build Coastguard Worker 	/* The record size needs to meet the minimum standard */
2861*f7c14bbaSAndroid Build Coastguard Worker 	record_size = *(__u32 *)info;
2862*f7c14bbaSAndroid Build Coastguard Worker 	if (record_size < ext_sec->min_rec_size ||
2863*f7c14bbaSAndroid Build Coastguard Worker 	    record_size & 0x03) {
2864*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("%s section in .BTF.ext has invalid record size %u\n",
2865*f7c14bbaSAndroid Build Coastguard Worker 			 ext_sec->desc, record_size);
2866*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2867*f7c14bbaSAndroid Build Coastguard Worker 	}
2868*f7c14bbaSAndroid Build Coastguard Worker 
2869*f7c14bbaSAndroid Build Coastguard Worker 	sinfo = info + sizeof(__u32);
2870*f7c14bbaSAndroid Build Coastguard Worker 	info_left -= sizeof(__u32);
2871*f7c14bbaSAndroid Build Coastguard Worker 
2872*f7c14bbaSAndroid Build Coastguard Worker 	/* If no records, return failure now so .BTF.ext won't be used. */
2873*f7c14bbaSAndroid Build Coastguard Worker 	if (!info_left) {
2874*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("%s section in .BTF.ext has no records", ext_sec->desc);
2875*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2876*f7c14bbaSAndroid Build Coastguard Worker 	}
2877*f7c14bbaSAndroid Build Coastguard Worker 
2878*f7c14bbaSAndroid Build Coastguard Worker 	while (info_left) {
2879*f7c14bbaSAndroid Build Coastguard Worker 		unsigned int sec_hdrlen = sizeof(struct btf_ext_info_sec);
2880*f7c14bbaSAndroid Build Coastguard Worker 		__u64 total_record_size;
2881*f7c14bbaSAndroid Build Coastguard Worker 		__u32 num_records;
2882*f7c14bbaSAndroid Build Coastguard Worker 
2883*f7c14bbaSAndroid Build Coastguard Worker 		if (info_left < sec_hdrlen) {
2884*f7c14bbaSAndroid Build Coastguard Worker 			pr_debug("%s section header is not found in .BTF.ext\n",
2885*f7c14bbaSAndroid Build Coastguard Worker 			     ext_sec->desc);
2886*f7c14bbaSAndroid Build Coastguard Worker 			return -EINVAL;
2887*f7c14bbaSAndroid Build Coastguard Worker 		}
2888*f7c14bbaSAndroid Build Coastguard Worker 
2889*f7c14bbaSAndroid Build Coastguard Worker 		num_records = sinfo->num_info;
2890*f7c14bbaSAndroid Build Coastguard Worker 		if (num_records == 0) {
2891*f7c14bbaSAndroid Build Coastguard Worker 			pr_debug("%s section has incorrect num_records in .BTF.ext\n",
2892*f7c14bbaSAndroid Build Coastguard Worker 			     ext_sec->desc);
2893*f7c14bbaSAndroid Build Coastguard Worker 			return -EINVAL;
2894*f7c14bbaSAndroid Build Coastguard Worker 		}
2895*f7c14bbaSAndroid Build Coastguard Worker 
2896*f7c14bbaSAndroid Build Coastguard Worker 		total_record_size = sec_hdrlen + (__u64)num_records * record_size;
2897*f7c14bbaSAndroid Build Coastguard Worker 		if (info_left < total_record_size) {
2898*f7c14bbaSAndroid Build Coastguard Worker 			pr_debug("%s section has incorrect num_records in .BTF.ext\n",
2899*f7c14bbaSAndroid Build Coastguard Worker 			     ext_sec->desc);
2900*f7c14bbaSAndroid Build Coastguard Worker 			return -EINVAL;
2901*f7c14bbaSAndroid Build Coastguard Worker 		}
2902*f7c14bbaSAndroid Build Coastguard Worker 
2903*f7c14bbaSAndroid Build Coastguard Worker 		info_left -= total_record_size;
2904*f7c14bbaSAndroid Build Coastguard Worker 		sinfo = (void *)sinfo + total_record_size;
2905*f7c14bbaSAndroid Build Coastguard Worker 		sec_cnt++;
2906*f7c14bbaSAndroid Build Coastguard Worker 	}
2907*f7c14bbaSAndroid Build Coastguard Worker 
2908*f7c14bbaSAndroid Build Coastguard Worker 	ext_info = ext_sec->ext_info;
2909*f7c14bbaSAndroid Build Coastguard Worker 	ext_info->len = ext_sec->len - sizeof(__u32);
2910*f7c14bbaSAndroid Build Coastguard Worker 	ext_info->rec_size = record_size;
2911*f7c14bbaSAndroid Build Coastguard Worker 	ext_info->info = info + sizeof(__u32);
2912*f7c14bbaSAndroid Build Coastguard Worker 	ext_info->sec_cnt = sec_cnt;
2913*f7c14bbaSAndroid Build Coastguard Worker 
2914*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2915*f7c14bbaSAndroid Build Coastguard Worker }
2916*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext_setup_func_info(struct btf_ext * btf_ext)2917*f7c14bbaSAndroid Build Coastguard Worker static int btf_ext_setup_func_info(struct btf_ext *btf_ext)
2918*f7c14bbaSAndroid Build Coastguard Worker {
2919*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext_sec_setup_param param = {
2920*f7c14bbaSAndroid Build Coastguard Worker 		.off = btf_ext->hdr->func_info_off,
2921*f7c14bbaSAndroid Build Coastguard Worker 		.len = btf_ext->hdr->func_info_len,
2922*f7c14bbaSAndroid Build Coastguard Worker 		.min_rec_size = sizeof(struct bpf_func_info_min),
2923*f7c14bbaSAndroid Build Coastguard Worker 		.ext_info = &btf_ext->func_info,
2924*f7c14bbaSAndroid Build Coastguard Worker 		.desc = "func_info"
2925*f7c14bbaSAndroid Build Coastguard Worker 	};
2926*f7c14bbaSAndroid Build Coastguard Worker 
2927*f7c14bbaSAndroid Build Coastguard Worker 	return btf_ext_setup_info(btf_ext, &param);
2928*f7c14bbaSAndroid Build Coastguard Worker }
2929*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext_setup_line_info(struct btf_ext * btf_ext)2930*f7c14bbaSAndroid Build Coastguard Worker static int btf_ext_setup_line_info(struct btf_ext *btf_ext)
2931*f7c14bbaSAndroid Build Coastguard Worker {
2932*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext_sec_setup_param param = {
2933*f7c14bbaSAndroid Build Coastguard Worker 		.off = btf_ext->hdr->line_info_off,
2934*f7c14bbaSAndroid Build Coastguard Worker 		.len = btf_ext->hdr->line_info_len,
2935*f7c14bbaSAndroid Build Coastguard Worker 		.min_rec_size = sizeof(struct bpf_line_info_min),
2936*f7c14bbaSAndroid Build Coastguard Worker 		.ext_info = &btf_ext->line_info,
2937*f7c14bbaSAndroid Build Coastguard Worker 		.desc = "line_info",
2938*f7c14bbaSAndroid Build Coastguard Worker 	};
2939*f7c14bbaSAndroid Build Coastguard Worker 
2940*f7c14bbaSAndroid Build Coastguard Worker 	return btf_ext_setup_info(btf_ext, &param);
2941*f7c14bbaSAndroid Build Coastguard Worker }
2942*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext_setup_core_relos(struct btf_ext * btf_ext)2943*f7c14bbaSAndroid Build Coastguard Worker static int btf_ext_setup_core_relos(struct btf_ext *btf_ext)
2944*f7c14bbaSAndroid Build Coastguard Worker {
2945*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext_sec_setup_param param = {
2946*f7c14bbaSAndroid Build Coastguard Worker 		.off = btf_ext->hdr->core_relo_off,
2947*f7c14bbaSAndroid Build Coastguard Worker 		.len = btf_ext->hdr->core_relo_len,
2948*f7c14bbaSAndroid Build Coastguard Worker 		.min_rec_size = sizeof(struct bpf_core_relo),
2949*f7c14bbaSAndroid Build Coastguard Worker 		.ext_info = &btf_ext->core_relo_info,
2950*f7c14bbaSAndroid Build Coastguard Worker 		.desc = "core_relo",
2951*f7c14bbaSAndroid Build Coastguard Worker 	};
2952*f7c14bbaSAndroid Build Coastguard Worker 
2953*f7c14bbaSAndroid Build Coastguard Worker 	return btf_ext_setup_info(btf_ext, &param);
2954*f7c14bbaSAndroid Build Coastguard Worker }
2955*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext_parse_hdr(__u8 * data,__u32 data_size)2956*f7c14bbaSAndroid Build Coastguard Worker static int btf_ext_parse_hdr(__u8 *data, __u32 data_size)
2957*f7c14bbaSAndroid Build Coastguard Worker {
2958*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
2959*f7c14bbaSAndroid Build Coastguard Worker 
2960*f7c14bbaSAndroid Build Coastguard Worker 	if (data_size < offsetofend(struct btf_ext_header, hdr_len) ||
2961*f7c14bbaSAndroid Build Coastguard Worker 	    data_size < hdr->hdr_len) {
2962*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("BTF.ext header not found");
2963*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2964*f7c14bbaSAndroid Build Coastguard Worker 	}
2965*f7c14bbaSAndroid Build Coastguard Worker 
2966*f7c14bbaSAndroid Build Coastguard Worker 	if (hdr->magic == bswap_16(BTF_MAGIC)) {
2967*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("BTF.ext in non-native endianness is not supported\n");
2968*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOTSUP;
2969*f7c14bbaSAndroid Build Coastguard Worker 	} else if (hdr->magic != BTF_MAGIC) {
2970*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Invalid BTF.ext magic:%x\n", hdr->magic);
2971*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2972*f7c14bbaSAndroid Build Coastguard Worker 	}
2973*f7c14bbaSAndroid Build Coastguard Worker 
2974*f7c14bbaSAndroid Build Coastguard Worker 	if (hdr->version != BTF_VERSION) {
2975*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Unsupported BTF.ext version:%u\n", hdr->version);
2976*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOTSUP;
2977*f7c14bbaSAndroid Build Coastguard Worker 	}
2978*f7c14bbaSAndroid Build Coastguard Worker 
2979*f7c14bbaSAndroid Build Coastguard Worker 	if (hdr->flags) {
2980*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("Unsupported BTF.ext flags:%x\n", hdr->flags);
2981*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOTSUP;
2982*f7c14bbaSAndroid Build Coastguard Worker 	}
2983*f7c14bbaSAndroid Build Coastguard Worker 
2984*f7c14bbaSAndroid Build Coastguard Worker 	if (data_size == hdr->hdr_len) {
2985*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("BTF.ext has no data\n");
2986*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
2987*f7c14bbaSAndroid Build Coastguard Worker 	}
2988*f7c14bbaSAndroid Build Coastguard Worker 
2989*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
2990*f7c14bbaSAndroid Build Coastguard Worker }
2991*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext__free(struct btf_ext * btf_ext)2992*f7c14bbaSAndroid Build Coastguard Worker void btf_ext__free(struct btf_ext *btf_ext)
2993*f7c14bbaSAndroid Build Coastguard Worker {
2994*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR_OR_NULL(btf_ext))
2995*f7c14bbaSAndroid Build Coastguard Worker 		return;
2996*f7c14bbaSAndroid Build Coastguard Worker 	free(btf_ext->func_info.sec_idxs);
2997*f7c14bbaSAndroid Build Coastguard Worker 	free(btf_ext->line_info.sec_idxs);
2998*f7c14bbaSAndroid Build Coastguard Worker 	free(btf_ext->core_relo_info.sec_idxs);
2999*f7c14bbaSAndroid Build Coastguard Worker 	free(btf_ext->data);
3000*f7c14bbaSAndroid Build Coastguard Worker 	free(btf_ext);
3001*f7c14bbaSAndroid Build Coastguard Worker }
3002*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext__new(const __u8 * data,__u32 size)3003*f7c14bbaSAndroid Build Coastguard Worker struct btf_ext *btf_ext__new(const __u8 *data, __u32 size)
3004*f7c14bbaSAndroid Build Coastguard Worker {
3005*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext *btf_ext;
3006*f7c14bbaSAndroid Build Coastguard Worker 	int err;
3007*f7c14bbaSAndroid Build Coastguard Worker 
3008*f7c14bbaSAndroid Build Coastguard Worker 	btf_ext = calloc(1, sizeof(struct btf_ext));
3009*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_ext)
3010*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err_ptr(-ENOMEM);
3011*f7c14bbaSAndroid Build Coastguard Worker 
3012*f7c14bbaSAndroid Build Coastguard Worker 	btf_ext->data_size = size;
3013*f7c14bbaSAndroid Build Coastguard Worker 	btf_ext->data = malloc(size);
3014*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_ext->data) {
3015*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENOMEM;
3016*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3017*f7c14bbaSAndroid Build Coastguard Worker 	}
3018*f7c14bbaSAndroid Build Coastguard Worker 	memcpy(btf_ext->data, data, size);
3019*f7c14bbaSAndroid Build Coastguard Worker 
3020*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_ext_parse_hdr(btf_ext->data, size);
3021*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
3022*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3023*f7c14bbaSAndroid Build Coastguard Worker 
3024*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ext->hdr->hdr_len < offsetofend(struct btf_ext_header, line_info_len)) {
3025*f7c14bbaSAndroid Build Coastguard Worker 		err = -EINVAL;
3026*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3027*f7c14bbaSAndroid Build Coastguard Worker 	}
3028*f7c14bbaSAndroid Build Coastguard Worker 
3029*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_ext_setup_func_info(btf_ext);
3030*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
3031*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3032*f7c14bbaSAndroid Build Coastguard Worker 
3033*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_ext_setup_line_info(btf_ext);
3034*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
3035*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3036*f7c14bbaSAndroid Build Coastguard Worker 
3037*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ext->hdr->hdr_len < offsetofend(struct btf_ext_header, core_relo_len))
3038*f7c14bbaSAndroid Build Coastguard Worker 		goto done; /* skip core relos parsing */
3039*f7c14bbaSAndroid Build Coastguard Worker 
3040*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_ext_setup_core_relos(btf_ext);
3041*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
3042*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3043*f7c14bbaSAndroid Build Coastguard Worker 
3044*f7c14bbaSAndroid Build Coastguard Worker done:
3045*f7c14bbaSAndroid Build Coastguard Worker 	if (err) {
3046*f7c14bbaSAndroid Build Coastguard Worker 		btf_ext__free(btf_ext);
3047*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err_ptr(err);
3048*f7c14bbaSAndroid Build Coastguard Worker 	}
3049*f7c14bbaSAndroid Build Coastguard Worker 
3050*f7c14bbaSAndroid Build Coastguard Worker 	return btf_ext;
3051*f7c14bbaSAndroid Build Coastguard Worker }
3052*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext__raw_data(const struct btf_ext * btf_ext,__u32 * size)3053*f7c14bbaSAndroid Build Coastguard Worker const void *btf_ext__raw_data(const struct btf_ext *btf_ext, __u32 *size)
3054*f7c14bbaSAndroid Build Coastguard Worker {
3055*f7c14bbaSAndroid Build Coastguard Worker 	*size = btf_ext->data_size;
3056*f7c14bbaSAndroid Build Coastguard Worker 	return btf_ext->data;
3057*f7c14bbaSAndroid Build Coastguard Worker }
3058*f7c14bbaSAndroid Build Coastguard Worker 
3059*f7c14bbaSAndroid Build Coastguard Worker __attribute__((alias("btf_ext__raw_data")))
3060*f7c14bbaSAndroid Build Coastguard Worker const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, __u32 *size);
3061*f7c14bbaSAndroid Build Coastguard Worker 
3062*f7c14bbaSAndroid Build Coastguard Worker 
3063*f7c14bbaSAndroid Build Coastguard Worker struct btf_dedup;
3064*f7c14bbaSAndroid Build Coastguard Worker 
3065*f7c14bbaSAndroid Build Coastguard Worker static struct btf_dedup *btf_dedup_new(struct btf *btf, const struct btf_dedup_opts *opts);
3066*f7c14bbaSAndroid Build Coastguard Worker static void btf_dedup_free(struct btf_dedup *d);
3067*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_prep(struct btf_dedup *d);
3068*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_strings(struct btf_dedup *d);
3069*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_prim_types(struct btf_dedup *d);
3070*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_struct_types(struct btf_dedup *d);
3071*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_ref_types(struct btf_dedup *d);
3072*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_resolve_fwds(struct btf_dedup *d);
3073*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_compact_types(struct btf_dedup *d);
3074*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_remap_types(struct btf_dedup *d);
3075*f7c14bbaSAndroid Build Coastguard Worker 
3076*f7c14bbaSAndroid Build Coastguard Worker /*
3077*f7c14bbaSAndroid Build Coastguard Worker  * Deduplicate BTF types and strings.
3078*f7c14bbaSAndroid Build Coastguard Worker  *
3079*f7c14bbaSAndroid Build Coastguard Worker  * BTF dedup algorithm takes as an input `struct btf` representing `.BTF` ELF
3080*f7c14bbaSAndroid Build Coastguard Worker  * section with all BTF type descriptors and string data. It overwrites that
3081*f7c14bbaSAndroid Build Coastguard Worker  * memory in-place with deduplicated types and strings without any loss of
3082*f7c14bbaSAndroid Build Coastguard Worker  * information. If optional `struct btf_ext` representing '.BTF.ext' ELF section
3083*f7c14bbaSAndroid Build Coastguard Worker  * is provided, all the strings referenced from .BTF.ext section are honored
3084*f7c14bbaSAndroid Build Coastguard Worker  * and updated to point to the right offsets after deduplication.
3085*f7c14bbaSAndroid Build Coastguard Worker  *
3086*f7c14bbaSAndroid Build Coastguard Worker  * If function returns with error, type/string data might be garbled and should
3087*f7c14bbaSAndroid Build Coastguard Worker  * be discarded.
3088*f7c14bbaSAndroid Build Coastguard Worker  *
3089*f7c14bbaSAndroid Build Coastguard Worker  * More verbose and detailed description of both problem btf_dedup is solving,
3090*f7c14bbaSAndroid Build Coastguard Worker  * as well as solution could be found at:
3091*f7c14bbaSAndroid Build Coastguard Worker  * https://facebookmicrosites.github.io/bpf/blog/2018/11/14/btf-enhancement.html
3092*f7c14bbaSAndroid Build Coastguard Worker  *
3093*f7c14bbaSAndroid Build Coastguard Worker  * Problem description and justification
3094*f7c14bbaSAndroid Build Coastguard Worker  * =====================================
3095*f7c14bbaSAndroid Build Coastguard Worker  *
3096*f7c14bbaSAndroid Build Coastguard Worker  * BTF type information is typically emitted either as a result of conversion
3097*f7c14bbaSAndroid Build Coastguard Worker  * from DWARF to BTF or directly by compiler. In both cases, each compilation
3098*f7c14bbaSAndroid Build Coastguard Worker  * unit contains information about a subset of all the types that are used
3099*f7c14bbaSAndroid Build Coastguard Worker  * in an application. These subsets are frequently overlapping and contain a lot
3100*f7c14bbaSAndroid Build Coastguard Worker  * of duplicated information when later concatenated together into a single
3101*f7c14bbaSAndroid Build Coastguard Worker  * binary. This algorithm ensures that each unique type is represented by single
3102*f7c14bbaSAndroid Build Coastguard Worker  * BTF type descriptor, greatly reducing resulting size of BTF data.
3103*f7c14bbaSAndroid Build Coastguard Worker  *
3104*f7c14bbaSAndroid Build Coastguard Worker  * Compilation unit isolation and subsequent duplication of data is not the only
3105*f7c14bbaSAndroid Build Coastguard Worker  * problem. The same type hierarchy (e.g., struct and all the type that struct
3106*f7c14bbaSAndroid Build Coastguard Worker  * references) in different compilation units can be represented in BTF to
3107*f7c14bbaSAndroid Build Coastguard Worker  * various degrees of completeness (or, rather, incompleteness) due to
3108*f7c14bbaSAndroid Build Coastguard Worker  * struct/union forward declarations.
3109*f7c14bbaSAndroid Build Coastguard Worker  *
3110*f7c14bbaSAndroid Build Coastguard Worker  * Let's take a look at an example, that we'll use to better understand the
3111*f7c14bbaSAndroid Build Coastguard Worker  * problem (and solution). Suppose we have two compilation units, each using
3112*f7c14bbaSAndroid Build Coastguard Worker  * same `struct S`, but each of them having incomplete type information about
3113*f7c14bbaSAndroid Build Coastguard Worker  * struct's fields:
3114*f7c14bbaSAndroid Build Coastguard Worker  *
3115*f7c14bbaSAndroid Build Coastguard Worker  * // CU #1:
3116*f7c14bbaSAndroid Build Coastguard Worker  * struct S;
3117*f7c14bbaSAndroid Build Coastguard Worker  * struct A {
3118*f7c14bbaSAndroid Build Coastguard Worker  *	int a;
3119*f7c14bbaSAndroid Build Coastguard Worker  *	struct A* self;
3120*f7c14bbaSAndroid Build Coastguard Worker  *	struct S* parent;
3121*f7c14bbaSAndroid Build Coastguard Worker  * };
3122*f7c14bbaSAndroid Build Coastguard Worker  * struct B;
3123*f7c14bbaSAndroid Build Coastguard Worker  * struct S {
3124*f7c14bbaSAndroid Build Coastguard Worker  *	struct A* a_ptr;
3125*f7c14bbaSAndroid Build Coastguard Worker  *	struct B* b_ptr;
3126*f7c14bbaSAndroid Build Coastguard Worker  * };
3127*f7c14bbaSAndroid Build Coastguard Worker  *
3128*f7c14bbaSAndroid Build Coastguard Worker  * // CU #2:
3129*f7c14bbaSAndroid Build Coastguard Worker  * struct S;
3130*f7c14bbaSAndroid Build Coastguard Worker  * struct A;
3131*f7c14bbaSAndroid Build Coastguard Worker  * struct B {
3132*f7c14bbaSAndroid Build Coastguard Worker  *	int b;
3133*f7c14bbaSAndroid Build Coastguard Worker  *	struct B* self;
3134*f7c14bbaSAndroid Build Coastguard Worker  *	struct S* parent;
3135*f7c14bbaSAndroid Build Coastguard Worker  * };
3136*f7c14bbaSAndroid Build Coastguard Worker  * struct S {
3137*f7c14bbaSAndroid Build Coastguard Worker  *	struct A* a_ptr;
3138*f7c14bbaSAndroid Build Coastguard Worker  *	struct B* b_ptr;
3139*f7c14bbaSAndroid Build Coastguard Worker  * };
3140*f7c14bbaSAndroid Build Coastguard Worker  *
3141*f7c14bbaSAndroid Build Coastguard Worker  * In case of CU #1, BTF data will know only that `struct B` exist (but no
3142*f7c14bbaSAndroid Build Coastguard Worker  * more), but will know the complete type information about `struct A`. While
3143*f7c14bbaSAndroid Build Coastguard Worker  * for CU #2, it will know full type information about `struct B`, but will
3144*f7c14bbaSAndroid Build Coastguard Worker  * only know about forward declaration of `struct A` (in BTF terms, it will
3145*f7c14bbaSAndroid Build Coastguard Worker  * have `BTF_KIND_FWD` type descriptor with name `B`).
3146*f7c14bbaSAndroid Build Coastguard Worker  *
3147*f7c14bbaSAndroid Build Coastguard Worker  * This compilation unit isolation means that it's possible that there is no
3148*f7c14bbaSAndroid Build Coastguard Worker  * single CU with complete type information describing structs `S`, `A`, and
3149*f7c14bbaSAndroid Build Coastguard Worker  * `B`. Also, we might get tons of duplicated and redundant type information.
3150*f7c14bbaSAndroid Build Coastguard Worker  *
3151*f7c14bbaSAndroid Build Coastguard Worker  * Additional complication we need to keep in mind comes from the fact that
3152*f7c14bbaSAndroid Build Coastguard Worker  * types, in general, can form graphs containing cycles, not just DAGs.
3153*f7c14bbaSAndroid Build Coastguard Worker  *
3154*f7c14bbaSAndroid Build Coastguard Worker  * While algorithm does deduplication, it also merges and resolves type
3155*f7c14bbaSAndroid Build Coastguard Worker  * information (unless disabled throught `struct btf_opts`), whenever possible.
3156*f7c14bbaSAndroid Build Coastguard Worker  * E.g., in the example above with two compilation units having partial type
3157*f7c14bbaSAndroid Build Coastguard Worker  * information for structs `A` and `B`, the output of algorithm will emit
3158*f7c14bbaSAndroid Build Coastguard Worker  * a single copy of each BTF type that describes structs `A`, `B`, and `S`
3159*f7c14bbaSAndroid Build Coastguard Worker  * (as well as type information for `int` and pointers), as if they were defined
3160*f7c14bbaSAndroid Build Coastguard Worker  * in a single compilation unit as:
3161*f7c14bbaSAndroid Build Coastguard Worker  *
3162*f7c14bbaSAndroid Build Coastguard Worker  * struct A {
3163*f7c14bbaSAndroid Build Coastguard Worker  *	int a;
3164*f7c14bbaSAndroid Build Coastguard Worker  *	struct A* self;
3165*f7c14bbaSAndroid Build Coastguard Worker  *	struct S* parent;
3166*f7c14bbaSAndroid Build Coastguard Worker  * };
3167*f7c14bbaSAndroid Build Coastguard Worker  * struct B {
3168*f7c14bbaSAndroid Build Coastguard Worker  *	int b;
3169*f7c14bbaSAndroid Build Coastguard Worker  *	struct B* self;
3170*f7c14bbaSAndroid Build Coastguard Worker  *	struct S* parent;
3171*f7c14bbaSAndroid Build Coastguard Worker  * };
3172*f7c14bbaSAndroid Build Coastguard Worker  * struct S {
3173*f7c14bbaSAndroid Build Coastguard Worker  *	struct A* a_ptr;
3174*f7c14bbaSAndroid Build Coastguard Worker  *	struct B* b_ptr;
3175*f7c14bbaSAndroid Build Coastguard Worker  * };
3176*f7c14bbaSAndroid Build Coastguard Worker  *
3177*f7c14bbaSAndroid Build Coastguard Worker  * Algorithm summary
3178*f7c14bbaSAndroid Build Coastguard Worker  * =================
3179*f7c14bbaSAndroid Build Coastguard Worker  *
3180*f7c14bbaSAndroid Build Coastguard Worker  * Algorithm completes its work in 7 separate passes:
3181*f7c14bbaSAndroid Build Coastguard Worker  *
3182*f7c14bbaSAndroid Build Coastguard Worker  * 1. Strings deduplication.
3183*f7c14bbaSAndroid Build Coastguard Worker  * 2. Primitive types deduplication (int, enum, fwd).
3184*f7c14bbaSAndroid Build Coastguard Worker  * 3. Struct/union types deduplication.
3185*f7c14bbaSAndroid Build Coastguard Worker  * 4. Resolve unambiguous forward declarations.
3186*f7c14bbaSAndroid Build Coastguard Worker  * 5. Reference types deduplication (pointers, typedefs, arrays, funcs, func
3187*f7c14bbaSAndroid Build Coastguard Worker  *    protos, and const/volatile/restrict modifiers).
3188*f7c14bbaSAndroid Build Coastguard Worker  * 6. Types compaction.
3189*f7c14bbaSAndroid Build Coastguard Worker  * 7. Types remapping.
3190*f7c14bbaSAndroid Build Coastguard Worker  *
3191*f7c14bbaSAndroid Build Coastguard Worker  * Algorithm determines canonical type descriptor, which is a single
3192*f7c14bbaSAndroid Build Coastguard Worker  * representative type for each truly unique type. This canonical type is the
3193*f7c14bbaSAndroid Build Coastguard Worker  * one that will go into final deduplicated BTF type information. For
3194*f7c14bbaSAndroid Build Coastguard Worker  * struct/unions, it is also the type that algorithm will merge additional type
3195*f7c14bbaSAndroid Build Coastguard Worker  * information into (while resolving FWDs), as it discovers it from data in
3196*f7c14bbaSAndroid Build Coastguard Worker  * other CUs. Each input BTF type eventually gets either mapped to itself, if
3197*f7c14bbaSAndroid Build Coastguard Worker  * that type is canonical, or to some other type, if that type is equivalent
3198*f7c14bbaSAndroid Build Coastguard Worker  * and was chosen as canonical representative. This mapping is stored in
3199*f7c14bbaSAndroid Build Coastguard Worker  * `btf_dedup->map` array. This map is also used to record STRUCT/UNION that
3200*f7c14bbaSAndroid Build Coastguard Worker  * FWD type got resolved to.
3201*f7c14bbaSAndroid Build Coastguard Worker  *
3202*f7c14bbaSAndroid Build Coastguard Worker  * To facilitate fast discovery of canonical types, we also maintain canonical
3203*f7c14bbaSAndroid Build Coastguard Worker  * index (`btf_dedup->dedup_table`), which maps type descriptor's signature hash
3204*f7c14bbaSAndroid Build Coastguard Worker  * (i.e., hashed kind, name, size, fields, etc) into a list of canonical types
3205*f7c14bbaSAndroid Build Coastguard Worker  * that match that signature. With sufficiently good choice of type signature
3206*f7c14bbaSAndroid Build Coastguard Worker  * hashing function, we can limit number of canonical types for each unique type
3207*f7c14bbaSAndroid Build Coastguard Worker  * signature to a very small number, allowing to find canonical type for any
3208*f7c14bbaSAndroid Build Coastguard Worker  * duplicated type very quickly.
3209*f7c14bbaSAndroid Build Coastguard Worker  *
3210*f7c14bbaSAndroid Build Coastguard Worker  * Struct/union deduplication is the most critical part and algorithm for
3211*f7c14bbaSAndroid Build Coastguard Worker  * deduplicating structs/unions is described in greater details in comments for
3212*f7c14bbaSAndroid Build Coastguard Worker  * `btf_dedup_is_equiv` function.
3213*f7c14bbaSAndroid Build Coastguard Worker  */
btf__dedup(struct btf * btf,const struct btf_dedup_opts * opts)3214*f7c14bbaSAndroid Build Coastguard Worker int btf__dedup(struct btf *btf, const struct btf_dedup_opts *opts)
3215*f7c14bbaSAndroid Build Coastguard Worker {
3216*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_dedup *d;
3217*f7c14bbaSAndroid Build Coastguard Worker 	int err;
3218*f7c14bbaSAndroid Build Coastguard Worker 
3219*f7c14bbaSAndroid Build Coastguard Worker 	if (!OPTS_VALID(opts, btf_dedup_opts))
3220*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
3221*f7c14bbaSAndroid Build Coastguard Worker 
3222*f7c14bbaSAndroid Build Coastguard Worker 	d = btf_dedup_new(btf, opts);
3223*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR(d)) {
3224*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_new failed: %ld", PTR_ERR(d));
3225*f7c14bbaSAndroid Build Coastguard Worker 		return libbpf_err(-EINVAL);
3226*f7c14bbaSAndroid Build Coastguard Worker 	}
3227*f7c14bbaSAndroid Build Coastguard Worker 
3228*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_ensure_modifiable(btf)) {
3229*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENOMEM;
3230*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3231*f7c14bbaSAndroid Build Coastguard Worker 	}
3232*f7c14bbaSAndroid Build Coastguard Worker 
3233*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_prep(d);
3234*f7c14bbaSAndroid Build Coastguard Worker 	if (err) {
3235*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_prep failed:%d\n", err);
3236*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3237*f7c14bbaSAndroid Build Coastguard Worker 	}
3238*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_strings(d);
3239*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0) {
3240*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_strings failed:%d\n", err);
3241*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3242*f7c14bbaSAndroid Build Coastguard Worker 	}
3243*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_prim_types(d);
3244*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0) {
3245*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_prim_types failed:%d\n", err);
3246*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3247*f7c14bbaSAndroid Build Coastguard Worker 	}
3248*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_struct_types(d);
3249*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0) {
3250*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_struct_types failed:%d\n", err);
3251*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3252*f7c14bbaSAndroid Build Coastguard Worker 	}
3253*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_resolve_fwds(d);
3254*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0) {
3255*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_resolve_fwds failed:%d\n", err);
3256*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3257*f7c14bbaSAndroid Build Coastguard Worker 	}
3258*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_ref_types(d);
3259*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0) {
3260*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_ref_types failed:%d\n", err);
3261*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3262*f7c14bbaSAndroid Build Coastguard Worker 	}
3263*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_compact_types(d);
3264*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0) {
3265*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_compact_types failed:%d\n", err);
3266*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3267*f7c14bbaSAndroid Build Coastguard Worker 	}
3268*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_remap_types(d);
3269*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0) {
3270*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("btf_dedup_remap_types failed:%d\n", err);
3271*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3272*f7c14bbaSAndroid Build Coastguard Worker 	}
3273*f7c14bbaSAndroid Build Coastguard Worker 
3274*f7c14bbaSAndroid Build Coastguard Worker done:
3275*f7c14bbaSAndroid Build Coastguard Worker 	btf_dedup_free(d);
3276*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_err(err);
3277*f7c14bbaSAndroid Build Coastguard Worker }
3278*f7c14bbaSAndroid Build Coastguard Worker 
3279*f7c14bbaSAndroid Build Coastguard Worker #define BTF_UNPROCESSED_ID ((__u32)-1)
3280*f7c14bbaSAndroid Build Coastguard Worker #define BTF_IN_PROGRESS_ID ((__u32)-2)
3281*f7c14bbaSAndroid Build Coastguard Worker 
3282*f7c14bbaSAndroid Build Coastguard Worker struct btf_dedup {
3283*f7c14bbaSAndroid Build Coastguard Worker 	/* .BTF section to be deduped in-place */
3284*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf;
3285*f7c14bbaSAndroid Build Coastguard Worker 	/*
3286*f7c14bbaSAndroid Build Coastguard Worker 	 * Optional .BTF.ext section. When provided, any strings referenced
3287*f7c14bbaSAndroid Build Coastguard Worker 	 * from it will be taken into account when deduping strings
3288*f7c14bbaSAndroid Build Coastguard Worker 	 */
3289*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext *btf_ext;
3290*f7c14bbaSAndroid Build Coastguard Worker 	/*
3291*f7c14bbaSAndroid Build Coastguard Worker 	 * This is a map from any type's signature hash to a list of possible
3292*f7c14bbaSAndroid Build Coastguard Worker 	 * canonical representative type candidates. Hash collisions are
3293*f7c14bbaSAndroid Build Coastguard Worker 	 * ignored, so even types of various kinds can share same list of
3294*f7c14bbaSAndroid Build Coastguard Worker 	 * candidates, which is fine because we rely on subsequent
3295*f7c14bbaSAndroid Build Coastguard Worker 	 * btf_xxx_equal() checks to authoritatively verify type equality.
3296*f7c14bbaSAndroid Build Coastguard Worker 	 */
3297*f7c14bbaSAndroid Build Coastguard Worker 	struct hashmap *dedup_table;
3298*f7c14bbaSAndroid Build Coastguard Worker 	/* Canonical types map */
3299*f7c14bbaSAndroid Build Coastguard Worker 	__u32 *map;
3300*f7c14bbaSAndroid Build Coastguard Worker 	/* Hypothetical mapping, used during type graph equivalence checks */
3301*f7c14bbaSAndroid Build Coastguard Worker 	__u32 *hypot_map;
3302*f7c14bbaSAndroid Build Coastguard Worker 	__u32 *hypot_list;
3303*f7c14bbaSAndroid Build Coastguard Worker 	size_t hypot_cnt;
3304*f7c14bbaSAndroid Build Coastguard Worker 	size_t hypot_cap;
3305*f7c14bbaSAndroid Build Coastguard Worker 	/* Whether hypothetical mapping, if successful, would need to adjust
3306*f7c14bbaSAndroid Build Coastguard Worker 	 * already canonicalized types (due to a new forward declaration to
3307*f7c14bbaSAndroid Build Coastguard Worker 	 * concrete type resolution). In such case, during split BTF dedup
3308*f7c14bbaSAndroid Build Coastguard Worker 	 * candidate type would still be considered as different, because base
3309*f7c14bbaSAndroid Build Coastguard Worker 	 * BTF is considered to be immutable.
3310*f7c14bbaSAndroid Build Coastguard Worker 	 */
3311*f7c14bbaSAndroid Build Coastguard Worker 	bool hypot_adjust_canon;
3312*f7c14bbaSAndroid Build Coastguard Worker 	/* Various option modifying behavior of algorithm */
3313*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_dedup_opts opts;
3314*f7c14bbaSAndroid Build Coastguard Worker 	/* temporary strings deduplication state */
3315*f7c14bbaSAndroid Build Coastguard Worker 	struct strset *strs_set;
3316*f7c14bbaSAndroid Build Coastguard Worker };
3317*f7c14bbaSAndroid Build Coastguard Worker 
hash_combine(long h,long value)3318*f7c14bbaSAndroid Build Coastguard Worker static long hash_combine(long h, long value)
3319*f7c14bbaSAndroid Build Coastguard Worker {
3320*f7c14bbaSAndroid Build Coastguard Worker 	return h * 31 + value;
3321*f7c14bbaSAndroid Build Coastguard Worker }
3322*f7c14bbaSAndroid Build Coastguard Worker 
3323*f7c14bbaSAndroid Build Coastguard Worker #define for_each_dedup_cand(d, node, hash) \
3324*f7c14bbaSAndroid Build Coastguard Worker 	hashmap__for_each_key_entry(d->dedup_table, node, hash)
3325*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_table_add(struct btf_dedup * d,long hash,__u32 type_id)3326*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_table_add(struct btf_dedup *d, long hash, __u32 type_id)
3327*f7c14bbaSAndroid Build Coastguard Worker {
3328*f7c14bbaSAndroid Build Coastguard Worker 	return hashmap__append(d->dedup_table, hash, type_id);
3329*f7c14bbaSAndroid Build Coastguard Worker }
3330*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_hypot_map_add(struct btf_dedup * d,__u32 from_id,__u32 to_id)3331*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_hypot_map_add(struct btf_dedup *d,
3332*f7c14bbaSAndroid Build Coastguard Worker 				   __u32 from_id, __u32 to_id)
3333*f7c14bbaSAndroid Build Coastguard Worker {
3334*f7c14bbaSAndroid Build Coastguard Worker 	if (d->hypot_cnt == d->hypot_cap) {
3335*f7c14bbaSAndroid Build Coastguard Worker 		__u32 *new_list;
3336*f7c14bbaSAndroid Build Coastguard Worker 
3337*f7c14bbaSAndroid Build Coastguard Worker 		d->hypot_cap += max((size_t)16, d->hypot_cap / 2);
3338*f7c14bbaSAndroid Build Coastguard Worker 		new_list = libbpf_reallocarray(d->hypot_list, d->hypot_cap, sizeof(__u32));
3339*f7c14bbaSAndroid Build Coastguard Worker 		if (!new_list)
3340*f7c14bbaSAndroid Build Coastguard Worker 			return -ENOMEM;
3341*f7c14bbaSAndroid Build Coastguard Worker 		d->hypot_list = new_list;
3342*f7c14bbaSAndroid Build Coastguard Worker 	}
3343*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_list[d->hypot_cnt++] = from_id;
3344*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_map[from_id] = to_id;
3345*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
3346*f7c14bbaSAndroid Build Coastguard Worker }
3347*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_clear_hypot_map(struct btf_dedup * d)3348*f7c14bbaSAndroid Build Coastguard Worker static void btf_dedup_clear_hypot_map(struct btf_dedup *d)
3349*f7c14bbaSAndroid Build Coastguard Worker {
3350*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3351*f7c14bbaSAndroid Build Coastguard Worker 
3352*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->hypot_cnt; i++)
3353*f7c14bbaSAndroid Build Coastguard Worker 		d->hypot_map[d->hypot_list[i]] = BTF_UNPROCESSED_ID;
3354*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_cnt = 0;
3355*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_adjust_canon = false;
3356*f7c14bbaSAndroid Build Coastguard Worker }
3357*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_free(struct btf_dedup * d)3358*f7c14bbaSAndroid Build Coastguard Worker static void btf_dedup_free(struct btf_dedup *d)
3359*f7c14bbaSAndroid Build Coastguard Worker {
3360*f7c14bbaSAndroid Build Coastguard Worker 	hashmap__free(d->dedup_table);
3361*f7c14bbaSAndroid Build Coastguard Worker 	d->dedup_table = NULL;
3362*f7c14bbaSAndroid Build Coastguard Worker 
3363*f7c14bbaSAndroid Build Coastguard Worker 	free(d->map);
3364*f7c14bbaSAndroid Build Coastguard Worker 	d->map = NULL;
3365*f7c14bbaSAndroid Build Coastguard Worker 
3366*f7c14bbaSAndroid Build Coastguard Worker 	free(d->hypot_map);
3367*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_map = NULL;
3368*f7c14bbaSAndroid Build Coastguard Worker 
3369*f7c14bbaSAndroid Build Coastguard Worker 	free(d->hypot_list);
3370*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_list = NULL;
3371*f7c14bbaSAndroid Build Coastguard Worker 
3372*f7c14bbaSAndroid Build Coastguard Worker 	free(d);
3373*f7c14bbaSAndroid Build Coastguard Worker }
3374*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_identity_hash_fn(long key,void * ctx)3375*f7c14bbaSAndroid Build Coastguard Worker static size_t btf_dedup_identity_hash_fn(long key, void *ctx)
3376*f7c14bbaSAndroid Build Coastguard Worker {
3377*f7c14bbaSAndroid Build Coastguard Worker 	return key;
3378*f7c14bbaSAndroid Build Coastguard Worker }
3379*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_collision_hash_fn(long key,void * ctx)3380*f7c14bbaSAndroid Build Coastguard Worker static size_t btf_dedup_collision_hash_fn(long key, void *ctx)
3381*f7c14bbaSAndroid Build Coastguard Worker {
3382*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
3383*f7c14bbaSAndroid Build Coastguard Worker }
3384*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_equal_fn(long k1,long k2,void * ctx)3385*f7c14bbaSAndroid Build Coastguard Worker static bool btf_dedup_equal_fn(long k1, long k2, void *ctx)
3386*f7c14bbaSAndroid Build Coastguard Worker {
3387*f7c14bbaSAndroid Build Coastguard Worker 	return k1 == k2;
3388*f7c14bbaSAndroid Build Coastguard Worker }
3389*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_new(struct btf * btf,const struct btf_dedup_opts * opts)3390*f7c14bbaSAndroid Build Coastguard Worker static struct btf_dedup *btf_dedup_new(struct btf *btf, const struct btf_dedup_opts *opts)
3391*f7c14bbaSAndroid Build Coastguard Worker {
3392*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_dedup *d = calloc(1, sizeof(struct btf_dedup));
3393*f7c14bbaSAndroid Build Coastguard Worker 	hashmap_hash_fn hash_fn = btf_dedup_identity_hash_fn;
3394*f7c14bbaSAndroid Build Coastguard Worker 	int i, err = 0, type_cnt;
3395*f7c14bbaSAndroid Build Coastguard Worker 
3396*f7c14bbaSAndroid Build Coastguard Worker 	if (!d)
3397*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(-ENOMEM);
3398*f7c14bbaSAndroid Build Coastguard Worker 
3399*f7c14bbaSAndroid Build Coastguard Worker 	if (OPTS_GET(opts, force_collisions, false))
3400*f7c14bbaSAndroid Build Coastguard Worker 		hash_fn = btf_dedup_collision_hash_fn;
3401*f7c14bbaSAndroid Build Coastguard Worker 
3402*f7c14bbaSAndroid Build Coastguard Worker 	d->btf = btf;
3403*f7c14bbaSAndroid Build Coastguard Worker 	d->btf_ext = OPTS_GET(opts, btf_ext, NULL);
3404*f7c14bbaSAndroid Build Coastguard Worker 
3405*f7c14bbaSAndroid Build Coastguard Worker 	d->dedup_table = hashmap__new(hash_fn, btf_dedup_equal_fn, NULL);
3406*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR(d->dedup_table)) {
3407*f7c14bbaSAndroid Build Coastguard Worker 		err = PTR_ERR(d->dedup_table);
3408*f7c14bbaSAndroid Build Coastguard Worker 		d->dedup_table = NULL;
3409*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3410*f7c14bbaSAndroid Build Coastguard Worker 	}
3411*f7c14bbaSAndroid Build Coastguard Worker 
3412*f7c14bbaSAndroid Build Coastguard Worker 	type_cnt = btf__type_cnt(btf);
3413*f7c14bbaSAndroid Build Coastguard Worker 	d->map = malloc(sizeof(__u32) * type_cnt);
3414*f7c14bbaSAndroid Build Coastguard Worker 	if (!d->map) {
3415*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENOMEM;
3416*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3417*f7c14bbaSAndroid Build Coastguard Worker 	}
3418*f7c14bbaSAndroid Build Coastguard Worker 	/* special BTF "void" type is made canonical immediately */
3419*f7c14bbaSAndroid Build Coastguard Worker 	d->map[0] = 0;
3420*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 1; i < type_cnt; i++) {
3421*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_type *t = btf_type_by_id(d->btf, i);
3422*f7c14bbaSAndroid Build Coastguard Worker 
3423*f7c14bbaSAndroid Build Coastguard Worker 		/* VAR and DATASEC are never deduped and are self-canonical */
3424*f7c14bbaSAndroid Build Coastguard Worker 		if (btf_is_var(t) || btf_is_datasec(t))
3425*f7c14bbaSAndroid Build Coastguard Worker 			d->map[i] = i;
3426*f7c14bbaSAndroid Build Coastguard Worker 		else
3427*f7c14bbaSAndroid Build Coastguard Worker 			d->map[i] = BTF_UNPROCESSED_ID;
3428*f7c14bbaSAndroid Build Coastguard Worker 	}
3429*f7c14bbaSAndroid Build Coastguard Worker 
3430*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_map = malloc(sizeof(__u32) * type_cnt);
3431*f7c14bbaSAndroid Build Coastguard Worker 	if (!d->hypot_map) {
3432*f7c14bbaSAndroid Build Coastguard Worker 		err = -ENOMEM;
3433*f7c14bbaSAndroid Build Coastguard Worker 		goto done;
3434*f7c14bbaSAndroid Build Coastguard Worker 	}
3435*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < type_cnt; i++)
3436*f7c14bbaSAndroid Build Coastguard Worker 		d->hypot_map[i] = BTF_UNPROCESSED_ID;
3437*f7c14bbaSAndroid Build Coastguard Worker 
3438*f7c14bbaSAndroid Build Coastguard Worker done:
3439*f7c14bbaSAndroid Build Coastguard Worker 	if (err) {
3440*f7c14bbaSAndroid Build Coastguard Worker 		btf_dedup_free(d);
3441*f7c14bbaSAndroid Build Coastguard Worker 		return ERR_PTR(err);
3442*f7c14bbaSAndroid Build Coastguard Worker 	}
3443*f7c14bbaSAndroid Build Coastguard Worker 
3444*f7c14bbaSAndroid Build Coastguard Worker 	return d;
3445*f7c14bbaSAndroid Build Coastguard Worker }
3446*f7c14bbaSAndroid Build Coastguard Worker 
3447*f7c14bbaSAndroid Build Coastguard Worker /*
3448*f7c14bbaSAndroid Build Coastguard Worker  * Iterate over all possible places in .BTF and .BTF.ext that can reference
3449*f7c14bbaSAndroid Build Coastguard Worker  * string and pass pointer to it to a provided callback `fn`.
3450*f7c14bbaSAndroid Build Coastguard Worker  */
btf_for_each_str_off(struct btf_dedup * d,str_off_visit_fn fn,void * ctx)3451*f7c14bbaSAndroid Build Coastguard Worker static int btf_for_each_str_off(struct btf_dedup *d, str_off_visit_fn fn, void *ctx)
3452*f7c14bbaSAndroid Build Coastguard Worker {
3453*f7c14bbaSAndroid Build Coastguard Worker 	int i, r;
3454*f7c14bbaSAndroid Build Coastguard Worker 
3455*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->btf->nr_types; i++) {
3456*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_type *t = btf_type_by_id(d->btf, d->btf->start_id + i);
3457*f7c14bbaSAndroid Build Coastguard Worker 
3458*f7c14bbaSAndroid Build Coastguard Worker 		r = btf_type_visit_str_offs(t, fn, ctx);
3459*f7c14bbaSAndroid Build Coastguard Worker 		if (r)
3460*f7c14bbaSAndroid Build Coastguard Worker 			return r;
3461*f7c14bbaSAndroid Build Coastguard Worker 	}
3462*f7c14bbaSAndroid Build Coastguard Worker 
3463*f7c14bbaSAndroid Build Coastguard Worker 	if (!d->btf_ext)
3464*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
3465*f7c14bbaSAndroid Build Coastguard Worker 
3466*f7c14bbaSAndroid Build Coastguard Worker 	r = btf_ext_visit_str_offs(d->btf_ext, fn, ctx);
3467*f7c14bbaSAndroid Build Coastguard Worker 	if (r)
3468*f7c14bbaSAndroid Build Coastguard Worker 		return r;
3469*f7c14bbaSAndroid Build Coastguard Worker 
3470*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
3471*f7c14bbaSAndroid Build Coastguard Worker }
3472*f7c14bbaSAndroid Build Coastguard Worker 
strs_dedup_remap_str_off(__u32 * str_off_ptr,void * ctx)3473*f7c14bbaSAndroid Build Coastguard Worker static int strs_dedup_remap_str_off(__u32 *str_off_ptr, void *ctx)
3474*f7c14bbaSAndroid Build Coastguard Worker {
3475*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_dedup *d = ctx;
3476*f7c14bbaSAndroid Build Coastguard Worker 	__u32 str_off = *str_off_ptr;
3477*f7c14bbaSAndroid Build Coastguard Worker 	const char *s;
3478*f7c14bbaSAndroid Build Coastguard Worker 	int off, err;
3479*f7c14bbaSAndroid Build Coastguard Worker 
3480*f7c14bbaSAndroid Build Coastguard Worker 	/* don't touch empty string or string in main BTF */
3481*f7c14bbaSAndroid Build Coastguard Worker 	if (str_off == 0 || str_off < d->btf->start_str_off)
3482*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
3483*f7c14bbaSAndroid Build Coastguard Worker 
3484*f7c14bbaSAndroid Build Coastguard Worker 	s = btf__str_by_offset(d->btf, str_off);
3485*f7c14bbaSAndroid Build Coastguard Worker 	if (d->btf->base_btf) {
3486*f7c14bbaSAndroid Build Coastguard Worker 		err = btf__find_str(d->btf->base_btf, s);
3487*f7c14bbaSAndroid Build Coastguard Worker 		if (err >= 0) {
3488*f7c14bbaSAndroid Build Coastguard Worker 			*str_off_ptr = err;
3489*f7c14bbaSAndroid Build Coastguard Worker 			return 0;
3490*f7c14bbaSAndroid Build Coastguard Worker 		}
3491*f7c14bbaSAndroid Build Coastguard Worker 		if (err != -ENOENT)
3492*f7c14bbaSAndroid Build Coastguard Worker 			return err;
3493*f7c14bbaSAndroid Build Coastguard Worker 	}
3494*f7c14bbaSAndroid Build Coastguard Worker 
3495*f7c14bbaSAndroid Build Coastguard Worker 	off = strset__add_str(d->strs_set, s);
3496*f7c14bbaSAndroid Build Coastguard Worker 	if (off < 0)
3497*f7c14bbaSAndroid Build Coastguard Worker 		return off;
3498*f7c14bbaSAndroid Build Coastguard Worker 
3499*f7c14bbaSAndroid Build Coastguard Worker 	*str_off_ptr = d->btf->start_str_off + off;
3500*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
3501*f7c14bbaSAndroid Build Coastguard Worker }
3502*f7c14bbaSAndroid Build Coastguard Worker 
3503*f7c14bbaSAndroid Build Coastguard Worker /*
3504*f7c14bbaSAndroid Build Coastguard Worker  * Dedup string and filter out those that are not referenced from either .BTF
3505*f7c14bbaSAndroid Build Coastguard Worker  * or .BTF.ext (if provided) sections.
3506*f7c14bbaSAndroid Build Coastguard Worker  *
3507*f7c14bbaSAndroid Build Coastguard Worker  * This is done by building index of all strings in BTF's string section,
3508*f7c14bbaSAndroid Build Coastguard Worker  * then iterating over all entities that can reference strings (e.g., type
3509*f7c14bbaSAndroid Build Coastguard Worker  * names, struct field names, .BTF.ext line info, etc) and marking corresponding
3510*f7c14bbaSAndroid Build Coastguard Worker  * strings as used. After that all used strings are deduped and compacted into
3511*f7c14bbaSAndroid Build Coastguard Worker  * sequential blob of memory and new offsets are calculated. Then all the string
3512*f7c14bbaSAndroid Build Coastguard Worker  * references are iterated again and rewritten using new offsets.
3513*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_strings(struct btf_dedup * d)3514*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_strings(struct btf_dedup *d)
3515*f7c14bbaSAndroid Build Coastguard Worker {
3516*f7c14bbaSAndroid Build Coastguard Worker 	int err;
3517*f7c14bbaSAndroid Build Coastguard Worker 
3518*f7c14bbaSAndroid Build Coastguard Worker 	if (d->btf->strs_deduped)
3519*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
3520*f7c14bbaSAndroid Build Coastguard Worker 
3521*f7c14bbaSAndroid Build Coastguard Worker 	d->strs_set = strset__new(BTF_MAX_STR_OFFSET, NULL, 0);
3522*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR(d->strs_set)) {
3523*f7c14bbaSAndroid Build Coastguard Worker 		err = PTR_ERR(d->strs_set);
3524*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
3525*f7c14bbaSAndroid Build Coastguard Worker 	}
3526*f7c14bbaSAndroid Build Coastguard Worker 
3527*f7c14bbaSAndroid Build Coastguard Worker 	if (!d->btf->base_btf) {
3528*f7c14bbaSAndroid Build Coastguard Worker 		/* insert empty string; we won't be looking it up during strings
3529*f7c14bbaSAndroid Build Coastguard Worker 		 * dedup, but it's good to have it for generic BTF string lookups
3530*f7c14bbaSAndroid Build Coastguard Worker 		 */
3531*f7c14bbaSAndroid Build Coastguard Worker 		err = strset__add_str(d->strs_set, "");
3532*f7c14bbaSAndroid Build Coastguard Worker 		if (err < 0)
3533*f7c14bbaSAndroid Build Coastguard Worker 			goto err_out;
3534*f7c14bbaSAndroid Build Coastguard Worker 	}
3535*f7c14bbaSAndroid Build Coastguard Worker 
3536*f7c14bbaSAndroid Build Coastguard Worker 	/* remap string offsets */
3537*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_for_each_str_off(d, strs_dedup_remap_str_off, d);
3538*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
3539*f7c14bbaSAndroid Build Coastguard Worker 		goto err_out;
3540*f7c14bbaSAndroid Build Coastguard Worker 
3541*f7c14bbaSAndroid Build Coastguard Worker 	/* replace BTF string data and hash with deduped ones */
3542*f7c14bbaSAndroid Build Coastguard Worker 	strset__free(d->btf->strs_set);
3543*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->hdr->str_len = strset__data_size(d->strs_set);
3544*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->strs_set = d->strs_set;
3545*f7c14bbaSAndroid Build Coastguard Worker 	d->strs_set = NULL;
3546*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->strs_deduped = true;
3547*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
3548*f7c14bbaSAndroid Build Coastguard Worker 
3549*f7c14bbaSAndroid Build Coastguard Worker err_out:
3550*f7c14bbaSAndroid Build Coastguard Worker 	strset__free(d->strs_set);
3551*f7c14bbaSAndroid Build Coastguard Worker 	d->strs_set = NULL;
3552*f7c14bbaSAndroid Build Coastguard Worker 
3553*f7c14bbaSAndroid Build Coastguard Worker 	return err;
3554*f7c14bbaSAndroid Build Coastguard Worker }
3555*f7c14bbaSAndroid Build Coastguard Worker 
btf_hash_common(struct btf_type * t)3556*f7c14bbaSAndroid Build Coastguard Worker static long btf_hash_common(struct btf_type *t)
3557*f7c14bbaSAndroid Build Coastguard Worker {
3558*f7c14bbaSAndroid Build Coastguard Worker 	long h;
3559*f7c14bbaSAndroid Build Coastguard Worker 
3560*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(0, t->name_off);
3561*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(h, t->info);
3562*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(h, t->size);
3563*f7c14bbaSAndroid Build Coastguard Worker 	return h;
3564*f7c14bbaSAndroid Build Coastguard Worker }
3565*f7c14bbaSAndroid Build Coastguard Worker 
btf_equal_common(struct btf_type * t1,struct btf_type * t2)3566*f7c14bbaSAndroid Build Coastguard Worker static bool btf_equal_common(struct btf_type *t1, struct btf_type *t2)
3567*f7c14bbaSAndroid Build Coastguard Worker {
3568*f7c14bbaSAndroid Build Coastguard Worker 	return t1->name_off == t2->name_off &&
3569*f7c14bbaSAndroid Build Coastguard Worker 	       t1->info == t2->info &&
3570*f7c14bbaSAndroid Build Coastguard Worker 	       t1->size == t2->size;
3571*f7c14bbaSAndroid Build Coastguard Worker }
3572*f7c14bbaSAndroid Build Coastguard Worker 
3573*f7c14bbaSAndroid Build Coastguard Worker /* Calculate type signature hash of INT or TAG. */
btf_hash_int_decl_tag(struct btf_type * t)3574*f7c14bbaSAndroid Build Coastguard Worker static long btf_hash_int_decl_tag(struct btf_type *t)
3575*f7c14bbaSAndroid Build Coastguard Worker {
3576*f7c14bbaSAndroid Build Coastguard Worker 	__u32 info = *(__u32 *)(t + 1);
3577*f7c14bbaSAndroid Build Coastguard Worker 	long h;
3578*f7c14bbaSAndroid Build Coastguard Worker 
3579*f7c14bbaSAndroid Build Coastguard Worker 	h = btf_hash_common(t);
3580*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(h, info);
3581*f7c14bbaSAndroid Build Coastguard Worker 	return h;
3582*f7c14bbaSAndroid Build Coastguard Worker }
3583*f7c14bbaSAndroid Build Coastguard Worker 
3584*f7c14bbaSAndroid Build Coastguard Worker /* Check structural equality of two INTs or TAGs. */
btf_equal_int_tag(struct btf_type * t1,struct btf_type * t2)3585*f7c14bbaSAndroid Build Coastguard Worker static bool btf_equal_int_tag(struct btf_type *t1, struct btf_type *t2)
3586*f7c14bbaSAndroid Build Coastguard Worker {
3587*f7c14bbaSAndroid Build Coastguard Worker 	__u32 info1, info2;
3588*f7c14bbaSAndroid Build Coastguard Worker 
3589*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_equal_common(t1, t2))
3590*f7c14bbaSAndroid Build Coastguard Worker 		return false;
3591*f7c14bbaSAndroid Build Coastguard Worker 	info1 = *(__u32 *)(t1 + 1);
3592*f7c14bbaSAndroid Build Coastguard Worker 	info2 = *(__u32 *)(t2 + 1);
3593*f7c14bbaSAndroid Build Coastguard Worker 	return info1 == info2;
3594*f7c14bbaSAndroid Build Coastguard Worker }
3595*f7c14bbaSAndroid Build Coastguard Worker 
3596*f7c14bbaSAndroid Build Coastguard Worker /* Calculate type signature hash of ENUM/ENUM64. */
btf_hash_enum(struct btf_type * t)3597*f7c14bbaSAndroid Build Coastguard Worker static long btf_hash_enum(struct btf_type *t)
3598*f7c14bbaSAndroid Build Coastguard Worker {
3599*f7c14bbaSAndroid Build Coastguard Worker 	long h;
3600*f7c14bbaSAndroid Build Coastguard Worker 
3601*f7c14bbaSAndroid Build Coastguard Worker 	/* don't hash vlen, enum members and size to support enum fwd resolving */
3602*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(0, t->name_off);
3603*f7c14bbaSAndroid Build Coastguard Worker 	return h;
3604*f7c14bbaSAndroid Build Coastguard Worker }
3605*f7c14bbaSAndroid Build Coastguard Worker 
btf_equal_enum_members(struct btf_type * t1,struct btf_type * t2)3606*f7c14bbaSAndroid Build Coastguard Worker static bool btf_equal_enum_members(struct btf_type *t1, struct btf_type *t2)
3607*f7c14bbaSAndroid Build Coastguard Worker {
3608*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_enum *m1, *m2;
3609*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen;
3610*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3611*f7c14bbaSAndroid Build Coastguard Worker 
3612*f7c14bbaSAndroid Build Coastguard Worker 	vlen = btf_vlen(t1);
3613*f7c14bbaSAndroid Build Coastguard Worker 	m1 = btf_enum(t1);
3614*f7c14bbaSAndroid Build Coastguard Worker 	m2 = btf_enum(t2);
3615*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < vlen; i++) {
3616*f7c14bbaSAndroid Build Coastguard Worker 		if (m1->name_off != m2->name_off || m1->val != m2->val)
3617*f7c14bbaSAndroid Build Coastguard Worker 			return false;
3618*f7c14bbaSAndroid Build Coastguard Worker 		m1++;
3619*f7c14bbaSAndroid Build Coastguard Worker 		m2++;
3620*f7c14bbaSAndroid Build Coastguard Worker 	}
3621*f7c14bbaSAndroid Build Coastguard Worker 	return true;
3622*f7c14bbaSAndroid Build Coastguard Worker }
3623*f7c14bbaSAndroid Build Coastguard Worker 
btf_equal_enum64_members(struct btf_type * t1,struct btf_type * t2)3624*f7c14bbaSAndroid Build Coastguard Worker static bool btf_equal_enum64_members(struct btf_type *t1, struct btf_type *t2)
3625*f7c14bbaSAndroid Build Coastguard Worker {
3626*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_enum64 *m1, *m2;
3627*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen;
3628*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3629*f7c14bbaSAndroid Build Coastguard Worker 
3630*f7c14bbaSAndroid Build Coastguard Worker 	vlen = btf_vlen(t1);
3631*f7c14bbaSAndroid Build Coastguard Worker 	m1 = btf_enum64(t1);
3632*f7c14bbaSAndroid Build Coastguard Worker 	m2 = btf_enum64(t2);
3633*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < vlen; i++) {
3634*f7c14bbaSAndroid Build Coastguard Worker 		if (m1->name_off != m2->name_off || m1->val_lo32 != m2->val_lo32 ||
3635*f7c14bbaSAndroid Build Coastguard Worker 		    m1->val_hi32 != m2->val_hi32)
3636*f7c14bbaSAndroid Build Coastguard Worker 			return false;
3637*f7c14bbaSAndroid Build Coastguard Worker 		m1++;
3638*f7c14bbaSAndroid Build Coastguard Worker 		m2++;
3639*f7c14bbaSAndroid Build Coastguard Worker 	}
3640*f7c14bbaSAndroid Build Coastguard Worker 	return true;
3641*f7c14bbaSAndroid Build Coastguard Worker }
3642*f7c14bbaSAndroid Build Coastguard Worker 
3643*f7c14bbaSAndroid Build Coastguard Worker /* Check structural equality of two ENUMs or ENUM64s. */
btf_equal_enum(struct btf_type * t1,struct btf_type * t2)3644*f7c14bbaSAndroid Build Coastguard Worker static bool btf_equal_enum(struct btf_type *t1, struct btf_type *t2)
3645*f7c14bbaSAndroid Build Coastguard Worker {
3646*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_equal_common(t1, t2))
3647*f7c14bbaSAndroid Build Coastguard Worker 		return false;
3648*f7c14bbaSAndroid Build Coastguard Worker 
3649*f7c14bbaSAndroid Build Coastguard Worker 	/* t1 & t2 kinds are identical because of btf_equal_common */
3650*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_kind(t1) == BTF_KIND_ENUM)
3651*f7c14bbaSAndroid Build Coastguard Worker 		return btf_equal_enum_members(t1, t2);
3652*f7c14bbaSAndroid Build Coastguard Worker 	else
3653*f7c14bbaSAndroid Build Coastguard Worker 		return btf_equal_enum64_members(t1, t2);
3654*f7c14bbaSAndroid Build Coastguard Worker }
3655*f7c14bbaSAndroid Build Coastguard Worker 
btf_is_enum_fwd(struct btf_type * t)3656*f7c14bbaSAndroid Build Coastguard Worker static inline bool btf_is_enum_fwd(struct btf_type *t)
3657*f7c14bbaSAndroid Build Coastguard Worker {
3658*f7c14bbaSAndroid Build Coastguard Worker 	return btf_is_any_enum(t) && btf_vlen(t) == 0;
3659*f7c14bbaSAndroid Build Coastguard Worker }
3660*f7c14bbaSAndroid Build Coastguard Worker 
btf_compat_enum(struct btf_type * t1,struct btf_type * t2)3661*f7c14bbaSAndroid Build Coastguard Worker static bool btf_compat_enum(struct btf_type *t1, struct btf_type *t2)
3662*f7c14bbaSAndroid Build Coastguard Worker {
3663*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_enum_fwd(t1) && !btf_is_enum_fwd(t2))
3664*f7c14bbaSAndroid Build Coastguard Worker 		return btf_equal_enum(t1, t2);
3665*f7c14bbaSAndroid Build Coastguard Worker 	/* At this point either t1 or t2 or both are forward declarations, thus:
3666*f7c14bbaSAndroid Build Coastguard Worker 	 * - skip comparing vlen because it is zero for forward declarations;
3667*f7c14bbaSAndroid Build Coastguard Worker 	 * - skip comparing size to allow enum forward declarations
3668*f7c14bbaSAndroid Build Coastguard Worker 	 *   to be compatible with enum64 full declarations;
3669*f7c14bbaSAndroid Build Coastguard Worker 	 * - skip comparing kind for the same reason.
3670*f7c14bbaSAndroid Build Coastguard Worker 	 */
3671*f7c14bbaSAndroid Build Coastguard Worker 	return t1->name_off == t2->name_off &&
3672*f7c14bbaSAndroid Build Coastguard Worker 	       btf_is_any_enum(t1) && btf_is_any_enum(t2);
3673*f7c14bbaSAndroid Build Coastguard Worker }
3674*f7c14bbaSAndroid Build Coastguard Worker 
3675*f7c14bbaSAndroid Build Coastguard Worker /*
3676*f7c14bbaSAndroid Build Coastguard Worker  * Calculate type signature hash of STRUCT/UNION, ignoring referenced type IDs,
3677*f7c14bbaSAndroid Build Coastguard Worker  * as referenced type IDs equivalence is established separately during type
3678*f7c14bbaSAndroid Build Coastguard Worker  * graph equivalence check algorithm.
3679*f7c14bbaSAndroid Build Coastguard Worker  */
btf_hash_struct(struct btf_type * t)3680*f7c14bbaSAndroid Build Coastguard Worker static long btf_hash_struct(struct btf_type *t)
3681*f7c14bbaSAndroid Build Coastguard Worker {
3682*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_member *member = btf_members(t);
3683*f7c14bbaSAndroid Build Coastguard Worker 	__u32 vlen = btf_vlen(t);
3684*f7c14bbaSAndroid Build Coastguard Worker 	long h = btf_hash_common(t);
3685*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3686*f7c14bbaSAndroid Build Coastguard Worker 
3687*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < vlen; i++) {
3688*f7c14bbaSAndroid Build Coastguard Worker 		h = hash_combine(h, member->name_off);
3689*f7c14bbaSAndroid Build Coastguard Worker 		h = hash_combine(h, member->offset);
3690*f7c14bbaSAndroid Build Coastguard Worker 		/* no hashing of referenced type ID, it can be unresolved yet */
3691*f7c14bbaSAndroid Build Coastguard Worker 		member++;
3692*f7c14bbaSAndroid Build Coastguard Worker 	}
3693*f7c14bbaSAndroid Build Coastguard Worker 	return h;
3694*f7c14bbaSAndroid Build Coastguard Worker }
3695*f7c14bbaSAndroid Build Coastguard Worker 
3696*f7c14bbaSAndroid Build Coastguard Worker /*
3697*f7c14bbaSAndroid Build Coastguard Worker  * Check structural compatibility of two STRUCTs/UNIONs, ignoring referenced
3698*f7c14bbaSAndroid Build Coastguard Worker  * type IDs. This check is performed during type graph equivalence check and
3699*f7c14bbaSAndroid Build Coastguard Worker  * referenced types equivalence is checked separately.
3700*f7c14bbaSAndroid Build Coastguard Worker  */
btf_shallow_equal_struct(struct btf_type * t1,struct btf_type * t2)3701*f7c14bbaSAndroid Build Coastguard Worker static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2)
3702*f7c14bbaSAndroid Build Coastguard Worker {
3703*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_member *m1, *m2;
3704*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen;
3705*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3706*f7c14bbaSAndroid Build Coastguard Worker 
3707*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_equal_common(t1, t2))
3708*f7c14bbaSAndroid Build Coastguard Worker 		return false;
3709*f7c14bbaSAndroid Build Coastguard Worker 
3710*f7c14bbaSAndroid Build Coastguard Worker 	vlen = btf_vlen(t1);
3711*f7c14bbaSAndroid Build Coastguard Worker 	m1 = btf_members(t1);
3712*f7c14bbaSAndroid Build Coastguard Worker 	m2 = btf_members(t2);
3713*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < vlen; i++) {
3714*f7c14bbaSAndroid Build Coastguard Worker 		if (m1->name_off != m2->name_off || m1->offset != m2->offset)
3715*f7c14bbaSAndroid Build Coastguard Worker 			return false;
3716*f7c14bbaSAndroid Build Coastguard Worker 		m1++;
3717*f7c14bbaSAndroid Build Coastguard Worker 		m2++;
3718*f7c14bbaSAndroid Build Coastguard Worker 	}
3719*f7c14bbaSAndroid Build Coastguard Worker 	return true;
3720*f7c14bbaSAndroid Build Coastguard Worker }
3721*f7c14bbaSAndroid Build Coastguard Worker 
3722*f7c14bbaSAndroid Build Coastguard Worker /*
3723*f7c14bbaSAndroid Build Coastguard Worker  * Calculate type signature hash of ARRAY, including referenced type IDs,
3724*f7c14bbaSAndroid Build Coastguard Worker  * under assumption that they were already resolved to canonical type IDs and
3725*f7c14bbaSAndroid Build Coastguard Worker  * are not going to change.
3726*f7c14bbaSAndroid Build Coastguard Worker  */
btf_hash_array(struct btf_type * t)3727*f7c14bbaSAndroid Build Coastguard Worker static long btf_hash_array(struct btf_type *t)
3728*f7c14bbaSAndroid Build Coastguard Worker {
3729*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_array *info = btf_array(t);
3730*f7c14bbaSAndroid Build Coastguard Worker 	long h = btf_hash_common(t);
3731*f7c14bbaSAndroid Build Coastguard Worker 
3732*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(h, info->type);
3733*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(h, info->index_type);
3734*f7c14bbaSAndroid Build Coastguard Worker 	h = hash_combine(h, info->nelems);
3735*f7c14bbaSAndroid Build Coastguard Worker 	return h;
3736*f7c14bbaSAndroid Build Coastguard Worker }
3737*f7c14bbaSAndroid Build Coastguard Worker 
3738*f7c14bbaSAndroid Build Coastguard Worker /*
3739*f7c14bbaSAndroid Build Coastguard Worker  * Check exact equality of two ARRAYs, taking into account referenced
3740*f7c14bbaSAndroid Build Coastguard Worker  * type IDs, under assumption that they were already resolved to canonical
3741*f7c14bbaSAndroid Build Coastguard Worker  * type IDs and are not going to change.
3742*f7c14bbaSAndroid Build Coastguard Worker  * This function is called during reference types deduplication to compare
3743*f7c14bbaSAndroid Build Coastguard Worker  * ARRAY to potential canonical representative.
3744*f7c14bbaSAndroid Build Coastguard Worker  */
btf_equal_array(struct btf_type * t1,struct btf_type * t2)3745*f7c14bbaSAndroid Build Coastguard Worker static bool btf_equal_array(struct btf_type *t1, struct btf_type *t2)
3746*f7c14bbaSAndroid Build Coastguard Worker {
3747*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_array *info1, *info2;
3748*f7c14bbaSAndroid Build Coastguard Worker 
3749*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_equal_common(t1, t2))
3750*f7c14bbaSAndroid Build Coastguard Worker 		return false;
3751*f7c14bbaSAndroid Build Coastguard Worker 
3752*f7c14bbaSAndroid Build Coastguard Worker 	info1 = btf_array(t1);
3753*f7c14bbaSAndroid Build Coastguard Worker 	info2 = btf_array(t2);
3754*f7c14bbaSAndroid Build Coastguard Worker 	return info1->type == info2->type &&
3755*f7c14bbaSAndroid Build Coastguard Worker 	       info1->index_type == info2->index_type &&
3756*f7c14bbaSAndroid Build Coastguard Worker 	       info1->nelems == info2->nelems;
3757*f7c14bbaSAndroid Build Coastguard Worker }
3758*f7c14bbaSAndroid Build Coastguard Worker 
3759*f7c14bbaSAndroid Build Coastguard Worker /*
3760*f7c14bbaSAndroid Build Coastguard Worker  * Check structural compatibility of two ARRAYs, ignoring referenced type
3761*f7c14bbaSAndroid Build Coastguard Worker  * IDs. This check is performed during type graph equivalence check and
3762*f7c14bbaSAndroid Build Coastguard Worker  * referenced types equivalence is checked separately.
3763*f7c14bbaSAndroid Build Coastguard Worker  */
btf_compat_array(struct btf_type * t1,struct btf_type * t2)3764*f7c14bbaSAndroid Build Coastguard Worker static bool btf_compat_array(struct btf_type *t1, struct btf_type *t2)
3765*f7c14bbaSAndroid Build Coastguard Worker {
3766*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_equal_common(t1, t2))
3767*f7c14bbaSAndroid Build Coastguard Worker 		return false;
3768*f7c14bbaSAndroid Build Coastguard Worker 
3769*f7c14bbaSAndroid Build Coastguard Worker 	return btf_array(t1)->nelems == btf_array(t2)->nelems;
3770*f7c14bbaSAndroid Build Coastguard Worker }
3771*f7c14bbaSAndroid Build Coastguard Worker 
3772*f7c14bbaSAndroid Build Coastguard Worker /*
3773*f7c14bbaSAndroid Build Coastguard Worker  * Calculate type signature hash of FUNC_PROTO, including referenced type IDs,
3774*f7c14bbaSAndroid Build Coastguard Worker  * under assumption that they were already resolved to canonical type IDs and
3775*f7c14bbaSAndroid Build Coastguard Worker  * are not going to change.
3776*f7c14bbaSAndroid Build Coastguard Worker  */
btf_hash_fnproto(struct btf_type * t)3777*f7c14bbaSAndroid Build Coastguard Worker static long btf_hash_fnproto(struct btf_type *t)
3778*f7c14bbaSAndroid Build Coastguard Worker {
3779*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_param *member = btf_params(t);
3780*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen = btf_vlen(t);
3781*f7c14bbaSAndroid Build Coastguard Worker 	long h = btf_hash_common(t);
3782*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3783*f7c14bbaSAndroid Build Coastguard Worker 
3784*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < vlen; i++) {
3785*f7c14bbaSAndroid Build Coastguard Worker 		h = hash_combine(h, member->name_off);
3786*f7c14bbaSAndroid Build Coastguard Worker 		h = hash_combine(h, member->type);
3787*f7c14bbaSAndroid Build Coastguard Worker 		member++;
3788*f7c14bbaSAndroid Build Coastguard Worker 	}
3789*f7c14bbaSAndroid Build Coastguard Worker 	return h;
3790*f7c14bbaSAndroid Build Coastguard Worker }
3791*f7c14bbaSAndroid Build Coastguard Worker 
3792*f7c14bbaSAndroid Build Coastguard Worker /*
3793*f7c14bbaSAndroid Build Coastguard Worker  * Check exact equality of two FUNC_PROTOs, taking into account referenced
3794*f7c14bbaSAndroid Build Coastguard Worker  * type IDs, under assumption that they were already resolved to canonical
3795*f7c14bbaSAndroid Build Coastguard Worker  * type IDs and are not going to change.
3796*f7c14bbaSAndroid Build Coastguard Worker  * This function is called during reference types deduplication to compare
3797*f7c14bbaSAndroid Build Coastguard Worker  * FUNC_PROTO to potential canonical representative.
3798*f7c14bbaSAndroid Build Coastguard Worker  */
btf_equal_fnproto(struct btf_type * t1,struct btf_type * t2)3799*f7c14bbaSAndroid Build Coastguard Worker static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2)
3800*f7c14bbaSAndroid Build Coastguard Worker {
3801*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_param *m1, *m2;
3802*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen;
3803*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3804*f7c14bbaSAndroid Build Coastguard Worker 
3805*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_equal_common(t1, t2))
3806*f7c14bbaSAndroid Build Coastguard Worker 		return false;
3807*f7c14bbaSAndroid Build Coastguard Worker 
3808*f7c14bbaSAndroid Build Coastguard Worker 	vlen = btf_vlen(t1);
3809*f7c14bbaSAndroid Build Coastguard Worker 	m1 = btf_params(t1);
3810*f7c14bbaSAndroid Build Coastguard Worker 	m2 = btf_params(t2);
3811*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < vlen; i++) {
3812*f7c14bbaSAndroid Build Coastguard Worker 		if (m1->name_off != m2->name_off || m1->type != m2->type)
3813*f7c14bbaSAndroid Build Coastguard Worker 			return false;
3814*f7c14bbaSAndroid Build Coastguard Worker 		m1++;
3815*f7c14bbaSAndroid Build Coastguard Worker 		m2++;
3816*f7c14bbaSAndroid Build Coastguard Worker 	}
3817*f7c14bbaSAndroid Build Coastguard Worker 	return true;
3818*f7c14bbaSAndroid Build Coastguard Worker }
3819*f7c14bbaSAndroid Build Coastguard Worker 
3820*f7c14bbaSAndroid Build Coastguard Worker /*
3821*f7c14bbaSAndroid Build Coastguard Worker  * Check structural compatibility of two FUNC_PROTOs, ignoring referenced type
3822*f7c14bbaSAndroid Build Coastguard Worker  * IDs. This check is performed during type graph equivalence check and
3823*f7c14bbaSAndroid Build Coastguard Worker  * referenced types equivalence is checked separately.
3824*f7c14bbaSAndroid Build Coastguard Worker  */
btf_compat_fnproto(struct btf_type * t1,struct btf_type * t2)3825*f7c14bbaSAndroid Build Coastguard Worker static bool btf_compat_fnproto(struct btf_type *t1, struct btf_type *t2)
3826*f7c14bbaSAndroid Build Coastguard Worker {
3827*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_param *m1, *m2;
3828*f7c14bbaSAndroid Build Coastguard Worker 	__u16 vlen;
3829*f7c14bbaSAndroid Build Coastguard Worker 	int i;
3830*f7c14bbaSAndroid Build Coastguard Worker 
3831*f7c14bbaSAndroid Build Coastguard Worker 	/* skip return type ID */
3832*f7c14bbaSAndroid Build Coastguard Worker 	if (t1->name_off != t2->name_off || t1->info != t2->info)
3833*f7c14bbaSAndroid Build Coastguard Worker 		return false;
3834*f7c14bbaSAndroid Build Coastguard Worker 
3835*f7c14bbaSAndroid Build Coastguard Worker 	vlen = btf_vlen(t1);
3836*f7c14bbaSAndroid Build Coastguard Worker 	m1 = btf_params(t1);
3837*f7c14bbaSAndroid Build Coastguard Worker 	m2 = btf_params(t2);
3838*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < vlen; i++) {
3839*f7c14bbaSAndroid Build Coastguard Worker 		if (m1->name_off != m2->name_off)
3840*f7c14bbaSAndroid Build Coastguard Worker 			return false;
3841*f7c14bbaSAndroid Build Coastguard Worker 		m1++;
3842*f7c14bbaSAndroid Build Coastguard Worker 		m2++;
3843*f7c14bbaSAndroid Build Coastguard Worker 	}
3844*f7c14bbaSAndroid Build Coastguard Worker 	return true;
3845*f7c14bbaSAndroid Build Coastguard Worker }
3846*f7c14bbaSAndroid Build Coastguard Worker 
3847*f7c14bbaSAndroid Build Coastguard Worker /* Prepare split BTF for deduplication by calculating hashes of base BTF's
3848*f7c14bbaSAndroid Build Coastguard Worker  * types and initializing the rest of the state (canonical type mapping) for
3849*f7c14bbaSAndroid Build Coastguard Worker  * the fixed base BTF part.
3850*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_prep(struct btf_dedup * d)3851*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_prep(struct btf_dedup *d)
3852*f7c14bbaSAndroid Build Coastguard Worker {
3853*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
3854*f7c14bbaSAndroid Build Coastguard Worker 	int type_id;
3855*f7c14bbaSAndroid Build Coastguard Worker 	long h;
3856*f7c14bbaSAndroid Build Coastguard Worker 
3857*f7c14bbaSAndroid Build Coastguard Worker 	if (!d->btf->base_btf)
3858*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
3859*f7c14bbaSAndroid Build Coastguard Worker 
3860*f7c14bbaSAndroid Build Coastguard Worker 	for (type_id = 1; type_id < d->btf->start_id; type_id++) {
3861*f7c14bbaSAndroid Build Coastguard Worker 		t = btf_type_by_id(d->btf, type_id);
3862*f7c14bbaSAndroid Build Coastguard Worker 
3863*f7c14bbaSAndroid Build Coastguard Worker 		/* all base BTF types are self-canonical by definition */
3864*f7c14bbaSAndroid Build Coastguard Worker 		d->map[type_id] = type_id;
3865*f7c14bbaSAndroid Build Coastguard Worker 
3866*f7c14bbaSAndroid Build Coastguard Worker 		switch (btf_kind(t)) {
3867*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_VAR:
3868*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_DATASEC:
3869*f7c14bbaSAndroid Build Coastguard Worker 			/* VAR and DATASEC are never hash/deduplicated */
3870*f7c14bbaSAndroid Build Coastguard Worker 			continue;
3871*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_CONST:
3872*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_VOLATILE:
3873*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_RESTRICT:
3874*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_PTR:
3875*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_FWD:
3876*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_TYPEDEF:
3877*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_FUNC:
3878*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_FLOAT:
3879*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_TYPE_TAG:
3880*f7c14bbaSAndroid Build Coastguard Worker 			h = btf_hash_common(t);
3881*f7c14bbaSAndroid Build Coastguard Worker 			break;
3882*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_INT:
3883*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_DECL_TAG:
3884*f7c14bbaSAndroid Build Coastguard Worker 			h = btf_hash_int_decl_tag(t);
3885*f7c14bbaSAndroid Build Coastguard Worker 			break;
3886*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_ENUM:
3887*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_ENUM64:
3888*f7c14bbaSAndroid Build Coastguard Worker 			h = btf_hash_enum(t);
3889*f7c14bbaSAndroid Build Coastguard Worker 			break;
3890*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_STRUCT:
3891*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_UNION:
3892*f7c14bbaSAndroid Build Coastguard Worker 			h = btf_hash_struct(t);
3893*f7c14bbaSAndroid Build Coastguard Worker 			break;
3894*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_ARRAY:
3895*f7c14bbaSAndroid Build Coastguard Worker 			h = btf_hash_array(t);
3896*f7c14bbaSAndroid Build Coastguard Worker 			break;
3897*f7c14bbaSAndroid Build Coastguard Worker 		case BTF_KIND_FUNC_PROTO:
3898*f7c14bbaSAndroid Build Coastguard Worker 			h = btf_hash_fnproto(t);
3899*f7c14bbaSAndroid Build Coastguard Worker 			break;
3900*f7c14bbaSAndroid Build Coastguard Worker 		default:
3901*f7c14bbaSAndroid Build Coastguard Worker 			pr_debug("unknown kind %d for type [%d]\n", btf_kind(t), type_id);
3902*f7c14bbaSAndroid Build Coastguard Worker 			return -EINVAL;
3903*f7c14bbaSAndroid Build Coastguard Worker 		}
3904*f7c14bbaSAndroid Build Coastguard Worker 		if (btf_dedup_table_add(d, h, type_id))
3905*f7c14bbaSAndroid Build Coastguard Worker 			return -ENOMEM;
3906*f7c14bbaSAndroid Build Coastguard Worker 	}
3907*f7c14bbaSAndroid Build Coastguard Worker 
3908*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
3909*f7c14bbaSAndroid Build Coastguard Worker }
3910*f7c14bbaSAndroid Build Coastguard Worker 
3911*f7c14bbaSAndroid Build Coastguard Worker /*
3912*f7c14bbaSAndroid Build Coastguard Worker  * Deduplicate primitive types, that can't reference other types, by calculating
3913*f7c14bbaSAndroid Build Coastguard Worker  * their type signature hash and comparing them with any possible canonical
3914*f7c14bbaSAndroid Build Coastguard Worker  * candidate. If no canonical candidate matches, type itself is marked as
3915*f7c14bbaSAndroid Build Coastguard Worker  * canonical and is added into `btf_dedup->dedup_table` as another candidate.
3916*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_prim_type(struct btf_dedup * d,__u32 type_id)3917*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
3918*f7c14bbaSAndroid Build Coastguard Worker {
3919*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t = btf_type_by_id(d->btf, type_id);
3920*f7c14bbaSAndroid Build Coastguard Worker 	struct hashmap_entry *hash_entry;
3921*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *cand;
3922*f7c14bbaSAndroid Build Coastguard Worker 	/* if we don't find equivalent type, then we are canonical */
3923*f7c14bbaSAndroid Build Coastguard Worker 	__u32 new_id = type_id;
3924*f7c14bbaSAndroid Build Coastguard Worker 	__u32 cand_id;
3925*f7c14bbaSAndroid Build Coastguard Worker 	long h;
3926*f7c14bbaSAndroid Build Coastguard Worker 
3927*f7c14bbaSAndroid Build Coastguard Worker 	switch (btf_kind(t)) {
3928*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
3929*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
3930*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
3931*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
3932*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
3933*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY:
3934*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
3935*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION:
3936*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC:
3937*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO:
3938*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VAR:
3939*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DATASEC:
3940*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DECL_TAG:
3941*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
3942*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
3943*f7c14bbaSAndroid Build Coastguard Worker 
3944*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_INT:
3945*f7c14bbaSAndroid Build Coastguard Worker 		h = btf_hash_int_decl_tag(t);
3946*f7c14bbaSAndroid Build Coastguard Worker 		for_each_dedup_cand(d, hash_entry, h) {
3947*f7c14bbaSAndroid Build Coastguard Worker 			cand_id = hash_entry->value;
3948*f7c14bbaSAndroid Build Coastguard Worker 			cand = btf_type_by_id(d->btf, cand_id);
3949*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_equal_int_tag(t, cand)) {
3950*f7c14bbaSAndroid Build Coastguard Worker 				new_id = cand_id;
3951*f7c14bbaSAndroid Build Coastguard Worker 				break;
3952*f7c14bbaSAndroid Build Coastguard Worker 			}
3953*f7c14bbaSAndroid Build Coastguard Worker 		}
3954*f7c14bbaSAndroid Build Coastguard Worker 		break;
3955*f7c14bbaSAndroid Build Coastguard Worker 
3956*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM:
3957*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64:
3958*f7c14bbaSAndroid Build Coastguard Worker 		h = btf_hash_enum(t);
3959*f7c14bbaSAndroid Build Coastguard Worker 		for_each_dedup_cand(d, hash_entry, h) {
3960*f7c14bbaSAndroid Build Coastguard Worker 			cand_id = hash_entry->value;
3961*f7c14bbaSAndroid Build Coastguard Worker 			cand = btf_type_by_id(d->btf, cand_id);
3962*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_equal_enum(t, cand)) {
3963*f7c14bbaSAndroid Build Coastguard Worker 				new_id = cand_id;
3964*f7c14bbaSAndroid Build Coastguard Worker 				break;
3965*f7c14bbaSAndroid Build Coastguard Worker 			}
3966*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_compat_enum(t, cand)) {
3967*f7c14bbaSAndroid Build Coastguard Worker 				if (btf_is_enum_fwd(t)) {
3968*f7c14bbaSAndroid Build Coastguard Worker 					/* resolve fwd to full enum */
3969*f7c14bbaSAndroid Build Coastguard Worker 					new_id = cand_id;
3970*f7c14bbaSAndroid Build Coastguard Worker 					break;
3971*f7c14bbaSAndroid Build Coastguard Worker 				}
3972*f7c14bbaSAndroid Build Coastguard Worker 				/* resolve canonical enum fwd to full enum */
3973*f7c14bbaSAndroid Build Coastguard Worker 				d->map[cand_id] = type_id;
3974*f7c14bbaSAndroid Build Coastguard Worker 			}
3975*f7c14bbaSAndroid Build Coastguard Worker 		}
3976*f7c14bbaSAndroid Build Coastguard Worker 		break;
3977*f7c14bbaSAndroid Build Coastguard Worker 
3978*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FWD:
3979*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FLOAT:
3980*f7c14bbaSAndroid Build Coastguard Worker 		h = btf_hash_common(t);
3981*f7c14bbaSAndroid Build Coastguard Worker 		for_each_dedup_cand(d, hash_entry, h) {
3982*f7c14bbaSAndroid Build Coastguard Worker 			cand_id = hash_entry->value;
3983*f7c14bbaSAndroid Build Coastguard Worker 			cand = btf_type_by_id(d->btf, cand_id);
3984*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_equal_common(t, cand)) {
3985*f7c14bbaSAndroid Build Coastguard Worker 				new_id = cand_id;
3986*f7c14bbaSAndroid Build Coastguard Worker 				break;
3987*f7c14bbaSAndroid Build Coastguard Worker 			}
3988*f7c14bbaSAndroid Build Coastguard Worker 		}
3989*f7c14bbaSAndroid Build Coastguard Worker 		break;
3990*f7c14bbaSAndroid Build Coastguard Worker 
3991*f7c14bbaSAndroid Build Coastguard Worker 	default:
3992*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
3993*f7c14bbaSAndroid Build Coastguard Worker 	}
3994*f7c14bbaSAndroid Build Coastguard Worker 
3995*f7c14bbaSAndroid Build Coastguard Worker 	d->map[type_id] = new_id;
3996*f7c14bbaSAndroid Build Coastguard Worker 	if (type_id == new_id && btf_dedup_table_add(d, h, type_id))
3997*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOMEM;
3998*f7c14bbaSAndroid Build Coastguard Worker 
3999*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4000*f7c14bbaSAndroid Build Coastguard Worker }
4001*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_prim_types(struct btf_dedup * d)4002*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_prim_types(struct btf_dedup *d)
4003*f7c14bbaSAndroid Build Coastguard Worker {
4004*f7c14bbaSAndroid Build Coastguard Worker 	int i, err;
4005*f7c14bbaSAndroid Build Coastguard Worker 
4006*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->btf->nr_types; i++) {
4007*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_dedup_prim_type(d, d->btf->start_id + i);
4008*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
4009*f7c14bbaSAndroid Build Coastguard Worker 			return err;
4010*f7c14bbaSAndroid Build Coastguard Worker 	}
4011*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4012*f7c14bbaSAndroid Build Coastguard Worker }
4013*f7c14bbaSAndroid Build Coastguard Worker 
4014*f7c14bbaSAndroid Build Coastguard Worker /*
4015*f7c14bbaSAndroid Build Coastguard Worker  * Check whether type is already mapped into canonical one (could be to itself).
4016*f7c14bbaSAndroid Build Coastguard Worker  */
is_type_mapped(struct btf_dedup * d,uint32_t type_id)4017*f7c14bbaSAndroid Build Coastguard Worker static inline bool is_type_mapped(struct btf_dedup *d, uint32_t type_id)
4018*f7c14bbaSAndroid Build Coastguard Worker {
4019*f7c14bbaSAndroid Build Coastguard Worker 	return d->map[type_id] <= BTF_MAX_NR_TYPES;
4020*f7c14bbaSAndroid Build Coastguard Worker }
4021*f7c14bbaSAndroid Build Coastguard Worker 
4022*f7c14bbaSAndroid Build Coastguard Worker /*
4023*f7c14bbaSAndroid Build Coastguard Worker  * Resolve type ID into its canonical type ID, if any; otherwise return original
4024*f7c14bbaSAndroid Build Coastguard Worker  * type ID. If type is FWD and is resolved into STRUCT/UNION already, follow
4025*f7c14bbaSAndroid Build Coastguard Worker  * STRUCT/UNION link and resolve it into canonical type ID as well.
4026*f7c14bbaSAndroid Build Coastguard Worker  */
resolve_type_id(struct btf_dedup * d,__u32 type_id)4027*f7c14bbaSAndroid Build Coastguard Worker static inline __u32 resolve_type_id(struct btf_dedup *d, __u32 type_id)
4028*f7c14bbaSAndroid Build Coastguard Worker {
4029*f7c14bbaSAndroid Build Coastguard Worker 	while (is_type_mapped(d, type_id) && d->map[type_id] != type_id)
4030*f7c14bbaSAndroid Build Coastguard Worker 		type_id = d->map[type_id];
4031*f7c14bbaSAndroid Build Coastguard Worker 	return type_id;
4032*f7c14bbaSAndroid Build Coastguard Worker }
4033*f7c14bbaSAndroid Build Coastguard Worker 
4034*f7c14bbaSAndroid Build Coastguard Worker /*
4035*f7c14bbaSAndroid Build Coastguard Worker  * Resolve FWD to underlying STRUCT/UNION, if any; otherwise return original
4036*f7c14bbaSAndroid Build Coastguard Worker  * type ID.
4037*f7c14bbaSAndroid Build Coastguard Worker  */
resolve_fwd_id(struct btf_dedup * d,uint32_t type_id)4038*f7c14bbaSAndroid Build Coastguard Worker static uint32_t resolve_fwd_id(struct btf_dedup *d, uint32_t type_id)
4039*f7c14bbaSAndroid Build Coastguard Worker {
4040*f7c14bbaSAndroid Build Coastguard Worker 	__u32 orig_type_id = type_id;
4041*f7c14bbaSAndroid Build Coastguard Worker 
4042*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_fwd(btf__type_by_id(d->btf, type_id)))
4043*f7c14bbaSAndroid Build Coastguard Worker 		return type_id;
4044*f7c14bbaSAndroid Build Coastguard Worker 
4045*f7c14bbaSAndroid Build Coastguard Worker 	while (is_type_mapped(d, type_id) && d->map[type_id] != type_id)
4046*f7c14bbaSAndroid Build Coastguard Worker 		type_id = d->map[type_id];
4047*f7c14bbaSAndroid Build Coastguard Worker 
4048*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_fwd(btf__type_by_id(d->btf, type_id)))
4049*f7c14bbaSAndroid Build Coastguard Worker 		return type_id;
4050*f7c14bbaSAndroid Build Coastguard Worker 
4051*f7c14bbaSAndroid Build Coastguard Worker 	return orig_type_id;
4052*f7c14bbaSAndroid Build Coastguard Worker }
4053*f7c14bbaSAndroid Build Coastguard Worker 
4054*f7c14bbaSAndroid Build Coastguard Worker 
btf_fwd_kind(struct btf_type * t)4055*f7c14bbaSAndroid Build Coastguard Worker static inline __u16 btf_fwd_kind(struct btf_type *t)
4056*f7c14bbaSAndroid Build Coastguard Worker {
4057*f7c14bbaSAndroid Build Coastguard Worker 	return btf_kflag(t) ? BTF_KIND_UNION : BTF_KIND_STRUCT;
4058*f7c14bbaSAndroid Build Coastguard Worker }
4059*f7c14bbaSAndroid Build Coastguard Worker 
4060*f7c14bbaSAndroid Build Coastguard Worker /* Check if given two types are identical ARRAY definitions */
btf_dedup_identical_arrays(struct btf_dedup * d,__u32 id1,__u32 id2)4061*f7c14bbaSAndroid Build Coastguard Worker static bool btf_dedup_identical_arrays(struct btf_dedup *d, __u32 id1, __u32 id2)
4062*f7c14bbaSAndroid Build Coastguard Worker {
4063*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t1, *t2;
4064*f7c14bbaSAndroid Build Coastguard Worker 
4065*f7c14bbaSAndroid Build Coastguard Worker 	t1 = btf_type_by_id(d->btf, id1);
4066*f7c14bbaSAndroid Build Coastguard Worker 	t2 = btf_type_by_id(d->btf, id2);
4067*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_array(t1) || !btf_is_array(t2))
4068*f7c14bbaSAndroid Build Coastguard Worker 		return false;
4069*f7c14bbaSAndroid Build Coastguard Worker 
4070*f7c14bbaSAndroid Build Coastguard Worker 	return btf_equal_array(t1, t2);
4071*f7c14bbaSAndroid Build Coastguard Worker }
4072*f7c14bbaSAndroid Build Coastguard Worker 
4073*f7c14bbaSAndroid Build Coastguard Worker /* Check if given two types are identical STRUCT/UNION definitions */
btf_dedup_identical_structs(struct btf_dedup * d,__u32 id1,__u32 id2)4074*f7c14bbaSAndroid Build Coastguard Worker static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32 id1, __u32 id2)
4075*f7c14bbaSAndroid Build Coastguard Worker {
4076*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_member *m1, *m2;
4077*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t1, *t2;
4078*f7c14bbaSAndroid Build Coastguard Worker 	int n, i;
4079*f7c14bbaSAndroid Build Coastguard Worker 
4080*f7c14bbaSAndroid Build Coastguard Worker 	t1 = btf_type_by_id(d->btf, id1);
4081*f7c14bbaSAndroid Build Coastguard Worker 	t2 = btf_type_by_id(d->btf, id2);
4082*f7c14bbaSAndroid Build Coastguard Worker 
4083*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_is_composite(t1) || btf_kind(t1) != btf_kind(t2))
4084*f7c14bbaSAndroid Build Coastguard Worker 		return false;
4085*f7c14bbaSAndroid Build Coastguard Worker 
4086*f7c14bbaSAndroid Build Coastguard Worker 	if (!btf_shallow_equal_struct(t1, t2))
4087*f7c14bbaSAndroid Build Coastguard Worker 		return false;
4088*f7c14bbaSAndroid Build Coastguard Worker 
4089*f7c14bbaSAndroid Build Coastguard Worker 	m1 = btf_members(t1);
4090*f7c14bbaSAndroid Build Coastguard Worker 	m2 = btf_members(t2);
4091*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0, n = btf_vlen(t1); i < n; i++, m1++, m2++) {
4092*f7c14bbaSAndroid Build Coastguard Worker 		if (m1->type != m2->type &&
4093*f7c14bbaSAndroid Build Coastguard Worker 		    !btf_dedup_identical_arrays(d, m1->type, m2->type) &&
4094*f7c14bbaSAndroid Build Coastguard Worker 		    !btf_dedup_identical_structs(d, m1->type, m2->type))
4095*f7c14bbaSAndroid Build Coastguard Worker 			return false;
4096*f7c14bbaSAndroid Build Coastguard Worker 	}
4097*f7c14bbaSAndroid Build Coastguard Worker 	return true;
4098*f7c14bbaSAndroid Build Coastguard Worker }
4099*f7c14bbaSAndroid Build Coastguard Worker 
4100*f7c14bbaSAndroid Build Coastguard Worker /*
4101*f7c14bbaSAndroid Build Coastguard Worker  * Check equivalence of BTF type graph formed by candidate struct/union (we'll
4102*f7c14bbaSAndroid Build Coastguard Worker  * call it "candidate graph" in this description for brevity) to a type graph
4103*f7c14bbaSAndroid Build Coastguard Worker  * formed by (potential) canonical struct/union ("canonical graph" for brevity
4104*f7c14bbaSAndroid Build Coastguard Worker  * here, though keep in mind that not all types in canonical graph are
4105*f7c14bbaSAndroid Build Coastguard Worker  * necessarily canonical representatives themselves, some of them might be
4106*f7c14bbaSAndroid Build Coastguard Worker  * duplicates or its uniqueness might not have been established yet).
4107*f7c14bbaSAndroid Build Coastguard Worker  * Returns:
4108*f7c14bbaSAndroid Build Coastguard Worker  *  - >0, if type graphs are equivalent;
4109*f7c14bbaSAndroid Build Coastguard Worker  *  -  0, if not equivalent;
4110*f7c14bbaSAndroid Build Coastguard Worker  *  - <0, on error.
4111*f7c14bbaSAndroid Build Coastguard Worker  *
4112*f7c14bbaSAndroid Build Coastguard Worker  * Algorithm performs side-by-side DFS traversal of both type graphs and checks
4113*f7c14bbaSAndroid Build Coastguard Worker  * equivalence of BTF types at each step. If at any point BTF types in candidate
4114*f7c14bbaSAndroid Build Coastguard Worker  * and canonical graphs are not compatible structurally, whole graphs are
4115*f7c14bbaSAndroid Build Coastguard Worker  * incompatible. If types are structurally equivalent (i.e., all information
4116*f7c14bbaSAndroid Build Coastguard Worker  * except referenced type IDs is exactly the same), a mapping from `canon_id` to
4117*f7c14bbaSAndroid Build Coastguard Worker  * a `cand_id` is recored in hypothetical mapping (`btf_dedup->hypot_map`).
4118*f7c14bbaSAndroid Build Coastguard Worker  * If a type references other types, then those referenced types are checked
4119*f7c14bbaSAndroid Build Coastguard Worker  * for equivalence recursively.
4120*f7c14bbaSAndroid Build Coastguard Worker  *
4121*f7c14bbaSAndroid Build Coastguard Worker  * During DFS traversal, if we find that for current `canon_id` type we
4122*f7c14bbaSAndroid Build Coastguard Worker  * already have some mapping in hypothetical map, we check for two possible
4123*f7c14bbaSAndroid Build Coastguard Worker  * situations:
4124*f7c14bbaSAndroid Build Coastguard Worker  *   - `canon_id` is mapped to exactly the same type as `cand_id`. This will
4125*f7c14bbaSAndroid Build Coastguard Worker  *     happen when type graphs have cycles. In this case we assume those two
4126*f7c14bbaSAndroid Build Coastguard Worker  *     types are equivalent.
4127*f7c14bbaSAndroid Build Coastguard Worker  *   - `canon_id` is mapped to different type. This is contradiction in our
4128*f7c14bbaSAndroid Build Coastguard Worker  *     hypothetical mapping, because same graph in canonical graph corresponds
4129*f7c14bbaSAndroid Build Coastguard Worker  *     to two different types in candidate graph, which for equivalent type
4130*f7c14bbaSAndroid Build Coastguard Worker  *     graphs shouldn't happen. This condition terminates equivalence check
4131*f7c14bbaSAndroid Build Coastguard Worker  *     with negative result.
4132*f7c14bbaSAndroid Build Coastguard Worker  *
4133*f7c14bbaSAndroid Build Coastguard Worker  * If type graphs traversal exhausts types to check and find no contradiction,
4134*f7c14bbaSAndroid Build Coastguard Worker  * then type graphs are equivalent.
4135*f7c14bbaSAndroid Build Coastguard Worker  *
4136*f7c14bbaSAndroid Build Coastguard Worker  * When checking types for equivalence, there is one special case: FWD types.
4137*f7c14bbaSAndroid Build Coastguard Worker  * If FWD type resolution is allowed and one of the types (either from canonical
4138*f7c14bbaSAndroid Build Coastguard Worker  * or candidate graph) is FWD and other is STRUCT/UNION (depending on FWD's kind
4139*f7c14bbaSAndroid Build Coastguard Worker  * flag) and their names match, hypothetical mapping is updated to point from
4140*f7c14bbaSAndroid Build Coastguard Worker  * FWD to STRUCT/UNION. If graphs will be determined as equivalent successfully,
4141*f7c14bbaSAndroid Build Coastguard Worker  * this mapping will be used to record FWD -> STRUCT/UNION mapping permanently.
4142*f7c14bbaSAndroid Build Coastguard Worker  *
4143*f7c14bbaSAndroid Build Coastguard Worker  * Technically, this could lead to incorrect FWD to STRUCT/UNION resolution,
4144*f7c14bbaSAndroid Build Coastguard Worker  * if there are two exactly named (or anonymous) structs/unions that are
4145*f7c14bbaSAndroid Build Coastguard Worker  * compatible structurally, one of which has FWD field, while other is concrete
4146*f7c14bbaSAndroid Build Coastguard Worker  * STRUCT/UNION, but according to C sources they are different structs/unions
4147*f7c14bbaSAndroid Build Coastguard Worker  * that are referencing different types with the same name. This is extremely
4148*f7c14bbaSAndroid Build Coastguard Worker  * unlikely to happen, but btf_dedup API allows to disable FWD resolution if
4149*f7c14bbaSAndroid Build Coastguard Worker  * this logic is causing problems.
4150*f7c14bbaSAndroid Build Coastguard Worker  *
4151*f7c14bbaSAndroid Build Coastguard Worker  * Doing FWD resolution means that both candidate and/or canonical graphs can
4152*f7c14bbaSAndroid Build Coastguard Worker  * consists of portions of the graph that come from multiple compilation units.
4153*f7c14bbaSAndroid Build Coastguard Worker  * This is due to the fact that types within single compilation unit are always
4154*f7c14bbaSAndroid Build Coastguard Worker  * deduplicated and FWDs are already resolved, if referenced struct/union
4155*f7c14bbaSAndroid Build Coastguard Worker  * definiton is available. So, if we had unresolved FWD and found corresponding
4156*f7c14bbaSAndroid Build Coastguard Worker  * STRUCT/UNION, they will be from different compilation units. This
4157*f7c14bbaSAndroid Build Coastguard Worker  * consequently means that when we "link" FWD to corresponding STRUCT/UNION,
4158*f7c14bbaSAndroid Build Coastguard Worker  * type graph will likely have at least two different BTF types that describe
4159*f7c14bbaSAndroid Build Coastguard Worker  * same type (e.g., most probably there will be two different BTF types for the
4160*f7c14bbaSAndroid Build Coastguard Worker  * same 'int' primitive type) and could even have "overlapping" parts of type
4161*f7c14bbaSAndroid Build Coastguard Worker  * graph that describe same subset of types.
4162*f7c14bbaSAndroid Build Coastguard Worker  *
4163*f7c14bbaSAndroid Build Coastguard Worker  * This in turn means that our assumption that each type in canonical graph
4164*f7c14bbaSAndroid Build Coastguard Worker  * must correspond to exactly one type in candidate graph might not hold
4165*f7c14bbaSAndroid Build Coastguard Worker  * anymore and will make it harder to detect contradictions using hypothetical
4166*f7c14bbaSAndroid Build Coastguard Worker  * map. To handle this problem, we allow to follow FWD -> STRUCT/UNION
4167*f7c14bbaSAndroid Build Coastguard Worker  * resolution only in canonical graph. FWDs in candidate graphs are never
4168*f7c14bbaSAndroid Build Coastguard Worker  * resolved. To see why it's OK, let's check all possible situations w.r.t. FWDs
4169*f7c14bbaSAndroid Build Coastguard Worker  * that can occur:
4170*f7c14bbaSAndroid Build Coastguard Worker  *   - Both types in canonical and candidate graphs are FWDs. If they are
4171*f7c14bbaSAndroid Build Coastguard Worker  *     structurally equivalent, then they can either be both resolved to the
4172*f7c14bbaSAndroid Build Coastguard Worker  *     same STRUCT/UNION or not resolved at all. In both cases they are
4173*f7c14bbaSAndroid Build Coastguard Worker  *     equivalent and there is no need to resolve FWD on candidate side.
4174*f7c14bbaSAndroid Build Coastguard Worker  *   - Both types in canonical and candidate graphs are concrete STRUCT/UNION,
4175*f7c14bbaSAndroid Build Coastguard Worker  *     so nothing to resolve as well, algorithm will check equivalence anyway.
4176*f7c14bbaSAndroid Build Coastguard Worker  *   - Type in canonical graph is FWD, while type in candidate is concrete
4177*f7c14bbaSAndroid Build Coastguard Worker  *     STRUCT/UNION. In this case candidate graph comes from single compilation
4178*f7c14bbaSAndroid Build Coastguard Worker  *     unit, so there is exactly one BTF type for each unique C type. After
4179*f7c14bbaSAndroid Build Coastguard Worker  *     resolving FWD into STRUCT/UNION, there might be more than one BTF type
4180*f7c14bbaSAndroid Build Coastguard Worker  *     in canonical graph mapping to single BTF type in candidate graph, but
4181*f7c14bbaSAndroid Build Coastguard Worker  *     because hypothetical mapping maps from canonical to candidate types, it's
4182*f7c14bbaSAndroid Build Coastguard Worker  *     alright, and we still maintain the property of having single `canon_id`
4183*f7c14bbaSAndroid Build Coastguard Worker  *     mapping to single `cand_id` (there could be two different `canon_id`
4184*f7c14bbaSAndroid Build Coastguard Worker  *     mapped to the same `cand_id`, but it's not contradictory).
4185*f7c14bbaSAndroid Build Coastguard Worker  *   - Type in canonical graph is concrete STRUCT/UNION, while type in candidate
4186*f7c14bbaSAndroid Build Coastguard Worker  *     graph is FWD. In this case we are just going to check compatibility of
4187*f7c14bbaSAndroid Build Coastguard Worker  *     STRUCT/UNION and corresponding FWD, and if they are compatible, we'll
4188*f7c14bbaSAndroid Build Coastguard Worker  *     assume that whatever STRUCT/UNION FWD resolves to must be equivalent to
4189*f7c14bbaSAndroid Build Coastguard Worker  *     a concrete STRUCT/UNION from canonical graph. If the rest of type graphs
4190*f7c14bbaSAndroid Build Coastguard Worker  *     turn out equivalent, we'll re-resolve FWD to concrete STRUCT/UNION from
4191*f7c14bbaSAndroid Build Coastguard Worker  *     canonical graph.
4192*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_is_equiv(struct btf_dedup * d,__u32 cand_id,__u32 canon_id)4193*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
4194*f7c14bbaSAndroid Build Coastguard Worker 			      __u32 canon_id)
4195*f7c14bbaSAndroid Build Coastguard Worker {
4196*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *cand_type;
4197*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *canon_type;
4198*f7c14bbaSAndroid Build Coastguard Worker 	__u32 hypot_type_id;
4199*f7c14bbaSAndroid Build Coastguard Worker 	__u16 cand_kind;
4200*f7c14bbaSAndroid Build Coastguard Worker 	__u16 canon_kind;
4201*f7c14bbaSAndroid Build Coastguard Worker 	int i, eq;
4202*f7c14bbaSAndroid Build Coastguard Worker 
4203*f7c14bbaSAndroid Build Coastguard Worker 	/* if both resolve to the same canonical, they must be equivalent */
4204*f7c14bbaSAndroid Build Coastguard Worker 	if (resolve_type_id(d, cand_id) == resolve_type_id(d, canon_id))
4205*f7c14bbaSAndroid Build Coastguard Worker 		return 1;
4206*f7c14bbaSAndroid Build Coastguard Worker 
4207*f7c14bbaSAndroid Build Coastguard Worker 	canon_id = resolve_fwd_id(d, canon_id);
4208*f7c14bbaSAndroid Build Coastguard Worker 
4209*f7c14bbaSAndroid Build Coastguard Worker 	hypot_type_id = d->hypot_map[canon_id];
4210*f7c14bbaSAndroid Build Coastguard Worker 	if (hypot_type_id <= BTF_MAX_NR_TYPES) {
4211*f7c14bbaSAndroid Build Coastguard Worker 		if (hypot_type_id == cand_id)
4212*f7c14bbaSAndroid Build Coastguard Worker 			return 1;
4213*f7c14bbaSAndroid Build Coastguard Worker 		/* In some cases compiler will generate different DWARF types
4214*f7c14bbaSAndroid Build Coastguard Worker 		 * for *identical* array type definitions and use them for
4215*f7c14bbaSAndroid Build Coastguard Worker 		 * different fields within the *same* struct. This breaks type
4216*f7c14bbaSAndroid Build Coastguard Worker 		 * equivalence check, which makes an assumption that candidate
4217*f7c14bbaSAndroid Build Coastguard Worker 		 * types sub-graph has a consistent and deduped-by-compiler
4218*f7c14bbaSAndroid Build Coastguard Worker 		 * types within a single CU. So work around that by explicitly
4219*f7c14bbaSAndroid Build Coastguard Worker 		 * allowing identical array types here.
4220*f7c14bbaSAndroid Build Coastguard Worker 		 */
4221*f7c14bbaSAndroid Build Coastguard Worker 		if (btf_dedup_identical_arrays(d, hypot_type_id, cand_id))
4222*f7c14bbaSAndroid Build Coastguard Worker 			return 1;
4223*f7c14bbaSAndroid Build Coastguard Worker 		/* It turns out that similar situation can happen with
4224*f7c14bbaSAndroid Build Coastguard Worker 		 * struct/union sometimes, sigh... Handle the case where
4225*f7c14bbaSAndroid Build Coastguard Worker 		 * structs/unions are exactly the same, down to the referenced
4226*f7c14bbaSAndroid Build Coastguard Worker 		 * type IDs. Anything more complicated (e.g., if referenced
4227*f7c14bbaSAndroid Build Coastguard Worker 		 * types are different, but equivalent) is *way more*
4228*f7c14bbaSAndroid Build Coastguard Worker 		 * complicated and requires a many-to-many equivalence mapping.
4229*f7c14bbaSAndroid Build Coastguard Worker 		 */
4230*f7c14bbaSAndroid Build Coastguard Worker 		if (btf_dedup_identical_structs(d, hypot_type_id, cand_id))
4231*f7c14bbaSAndroid Build Coastguard Worker 			return 1;
4232*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4233*f7c14bbaSAndroid Build Coastguard Worker 	}
4234*f7c14bbaSAndroid Build Coastguard Worker 
4235*f7c14bbaSAndroid Build Coastguard Worker 	if (btf_dedup_hypot_map_add(d, canon_id, cand_id))
4236*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOMEM;
4237*f7c14bbaSAndroid Build Coastguard Worker 
4238*f7c14bbaSAndroid Build Coastguard Worker 	cand_type = btf_type_by_id(d->btf, cand_id);
4239*f7c14bbaSAndroid Build Coastguard Worker 	canon_type = btf_type_by_id(d->btf, canon_id);
4240*f7c14bbaSAndroid Build Coastguard Worker 	cand_kind = btf_kind(cand_type);
4241*f7c14bbaSAndroid Build Coastguard Worker 	canon_kind = btf_kind(canon_type);
4242*f7c14bbaSAndroid Build Coastguard Worker 
4243*f7c14bbaSAndroid Build Coastguard Worker 	if (cand_type->name_off != canon_type->name_off)
4244*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4245*f7c14bbaSAndroid Build Coastguard Worker 
4246*f7c14bbaSAndroid Build Coastguard Worker 	/* FWD <--> STRUCT/UNION equivalence check, if enabled */
4247*f7c14bbaSAndroid Build Coastguard Worker 	if ((cand_kind == BTF_KIND_FWD || canon_kind == BTF_KIND_FWD)
4248*f7c14bbaSAndroid Build Coastguard Worker 	    && cand_kind != canon_kind) {
4249*f7c14bbaSAndroid Build Coastguard Worker 		__u16 real_kind;
4250*f7c14bbaSAndroid Build Coastguard Worker 		__u16 fwd_kind;
4251*f7c14bbaSAndroid Build Coastguard Worker 
4252*f7c14bbaSAndroid Build Coastguard Worker 		if (cand_kind == BTF_KIND_FWD) {
4253*f7c14bbaSAndroid Build Coastguard Worker 			real_kind = canon_kind;
4254*f7c14bbaSAndroid Build Coastguard Worker 			fwd_kind = btf_fwd_kind(cand_type);
4255*f7c14bbaSAndroid Build Coastguard Worker 		} else {
4256*f7c14bbaSAndroid Build Coastguard Worker 			real_kind = cand_kind;
4257*f7c14bbaSAndroid Build Coastguard Worker 			fwd_kind = btf_fwd_kind(canon_type);
4258*f7c14bbaSAndroid Build Coastguard Worker 			/* we'd need to resolve base FWD to STRUCT/UNION */
4259*f7c14bbaSAndroid Build Coastguard Worker 			if (fwd_kind == real_kind && canon_id < d->btf->start_id)
4260*f7c14bbaSAndroid Build Coastguard Worker 				d->hypot_adjust_canon = true;
4261*f7c14bbaSAndroid Build Coastguard Worker 		}
4262*f7c14bbaSAndroid Build Coastguard Worker 		return fwd_kind == real_kind;
4263*f7c14bbaSAndroid Build Coastguard Worker 	}
4264*f7c14bbaSAndroid Build Coastguard Worker 
4265*f7c14bbaSAndroid Build Coastguard Worker 	if (cand_kind != canon_kind)
4266*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4267*f7c14bbaSAndroid Build Coastguard Worker 
4268*f7c14bbaSAndroid Build Coastguard Worker 	switch (cand_kind) {
4269*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_INT:
4270*f7c14bbaSAndroid Build Coastguard Worker 		return btf_equal_int_tag(cand_type, canon_type);
4271*f7c14bbaSAndroid Build Coastguard Worker 
4272*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM:
4273*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64:
4274*f7c14bbaSAndroid Build Coastguard Worker 		return btf_compat_enum(cand_type, canon_type);
4275*f7c14bbaSAndroid Build Coastguard Worker 
4276*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FWD:
4277*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FLOAT:
4278*f7c14bbaSAndroid Build Coastguard Worker 		return btf_equal_common(cand_type, canon_type);
4279*f7c14bbaSAndroid Build Coastguard Worker 
4280*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
4281*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
4282*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
4283*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
4284*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
4285*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC:
4286*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
4287*f7c14bbaSAndroid Build Coastguard Worker 		if (cand_type->info != canon_type->info)
4288*f7c14bbaSAndroid Build Coastguard Worker 			return 0;
4289*f7c14bbaSAndroid Build Coastguard Worker 		return btf_dedup_is_equiv(d, cand_type->type, canon_type->type);
4290*f7c14bbaSAndroid Build Coastguard Worker 
4291*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY: {
4292*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_array *cand_arr, *canon_arr;
4293*f7c14bbaSAndroid Build Coastguard Worker 
4294*f7c14bbaSAndroid Build Coastguard Worker 		if (!btf_compat_array(cand_type, canon_type))
4295*f7c14bbaSAndroid Build Coastguard Worker 			return 0;
4296*f7c14bbaSAndroid Build Coastguard Worker 		cand_arr = btf_array(cand_type);
4297*f7c14bbaSAndroid Build Coastguard Worker 		canon_arr = btf_array(canon_type);
4298*f7c14bbaSAndroid Build Coastguard Worker 		eq = btf_dedup_is_equiv(d, cand_arr->index_type, canon_arr->index_type);
4299*f7c14bbaSAndroid Build Coastguard Worker 		if (eq <= 0)
4300*f7c14bbaSAndroid Build Coastguard Worker 			return eq;
4301*f7c14bbaSAndroid Build Coastguard Worker 		return btf_dedup_is_equiv(d, cand_arr->type, canon_arr->type);
4302*f7c14bbaSAndroid Build Coastguard Worker 	}
4303*f7c14bbaSAndroid Build Coastguard Worker 
4304*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
4305*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION: {
4306*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_member *cand_m, *canon_m;
4307*f7c14bbaSAndroid Build Coastguard Worker 		__u16 vlen;
4308*f7c14bbaSAndroid Build Coastguard Worker 
4309*f7c14bbaSAndroid Build Coastguard Worker 		if (!btf_shallow_equal_struct(cand_type, canon_type))
4310*f7c14bbaSAndroid Build Coastguard Worker 			return 0;
4311*f7c14bbaSAndroid Build Coastguard Worker 		vlen = btf_vlen(cand_type);
4312*f7c14bbaSAndroid Build Coastguard Worker 		cand_m = btf_members(cand_type);
4313*f7c14bbaSAndroid Build Coastguard Worker 		canon_m = btf_members(canon_type);
4314*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < vlen; i++) {
4315*f7c14bbaSAndroid Build Coastguard Worker 			eq = btf_dedup_is_equiv(d, cand_m->type, canon_m->type);
4316*f7c14bbaSAndroid Build Coastguard Worker 			if (eq <= 0)
4317*f7c14bbaSAndroid Build Coastguard Worker 				return eq;
4318*f7c14bbaSAndroid Build Coastguard Worker 			cand_m++;
4319*f7c14bbaSAndroid Build Coastguard Worker 			canon_m++;
4320*f7c14bbaSAndroid Build Coastguard Worker 		}
4321*f7c14bbaSAndroid Build Coastguard Worker 
4322*f7c14bbaSAndroid Build Coastguard Worker 		return 1;
4323*f7c14bbaSAndroid Build Coastguard Worker 	}
4324*f7c14bbaSAndroid Build Coastguard Worker 
4325*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO: {
4326*f7c14bbaSAndroid Build Coastguard Worker 		const struct btf_param *cand_p, *canon_p;
4327*f7c14bbaSAndroid Build Coastguard Worker 		__u16 vlen;
4328*f7c14bbaSAndroid Build Coastguard Worker 
4329*f7c14bbaSAndroid Build Coastguard Worker 		if (!btf_compat_fnproto(cand_type, canon_type))
4330*f7c14bbaSAndroid Build Coastguard Worker 			return 0;
4331*f7c14bbaSAndroid Build Coastguard Worker 		eq = btf_dedup_is_equiv(d, cand_type->type, canon_type->type);
4332*f7c14bbaSAndroid Build Coastguard Worker 		if (eq <= 0)
4333*f7c14bbaSAndroid Build Coastguard Worker 			return eq;
4334*f7c14bbaSAndroid Build Coastguard Worker 		vlen = btf_vlen(cand_type);
4335*f7c14bbaSAndroid Build Coastguard Worker 		cand_p = btf_params(cand_type);
4336*f7c14bbaSAndroid Build Coastguard Worker 		canon_p = btf_params(canon_type);
4337*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < vlen; i++) {
4338*f7c14bbaSAndroid Build Coastguard Worker 			eq = btf_dedup_is_equiv(d, cand_p->type, canon_p->type);
4339*f7c14bbaSAndroid Build Coastguard Worker 			if (eq <= 0)
4340*f7c14bbaSAndroid Build Coastguard Worker 				return eq;
4341*f7c14bbaSAndroid Build Coastguard Worker 			cand_p++;
4342*f7c14bbaSAndroid Build Coastguard Worker 			canon_p++;
4343*f7c14bbaSAndroid Build Coastguard Worker 		}
4344*f7c14bbaSAndroid Build Coastguard Worker 		return 1;
4345*f7c14bbaSAndroid Build Coastguard Worker 	}
4346*f7c14bbaSAndroid Build Coastguard Worker 
4347*f7c14bbaSAndroid Build Coastguard Worker 	default:
4348*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
4349*f7c14bbaSAndroid Build Coastguard Worker 	}
4350*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4351*f7c14bbaSAndroid Build Coastguard Worker }
4352*f7c14bbaSAndroid Build Coastguard Worker 
4353*f7c14bbaSAndroid Build Coastguard Worker /*
4354*f7c14bbaSAndroid Build Coastguard Worker  * Use hypothetical mapping, produced by successful type graph equivalence
4355*f7c14bbaSAndroid Build Coastguard Worker  * check, to augment existing struct/union canonical mapping, where possible.
4356*f7c14bbaSAndroid Build Coastguard Worker  *
4357*f7c14bbaSAndroid Build Coastguard Worker  * If BTF_KIND_FWD resolution is allowed, this mapping is also used to record
4358*f7c14bbaSAndroid Build Coastguard Worker  * FWD -> STRUCT/UNION correspondence as well. FWD resolution is bidirectional:
4359*f7c14bbaSAndroid Build Coastguard Worker  * it doesn't matter if FWD type was part of canonical graph or candidate one,
4360*f7c14bbaSAndroid Build Coastguard Worker  * we are recording the mapping anyway. As opposed to carefulness required
4361*f7c14bbaSAndroid Build Coastguard Worker  * for struct/union correspondence mapping (described below), for FWD resolution
4362*f7c14bbaSAndroid Build Coastguard Worker  * it's not important, as by the time that FWD type (reference type) will be
4363*f7c14bbaSAndroid Build Coastguard Worker  * deduplicated all structs/unions will be deduped already anyway.
4364*f7c14bbaSAndroid Build Coastguard Worker  *
4365*f7c14bbaSAndroid Build Coastguard Worker  * Recording STRUCT/UNION mapping is purely a performance optimization and is
4366*f7c14bbaSAndroid Build Coastguard Worker  * not required for correctness. It needs to be done carefully to ensure that
4367*f7c14bbaSAndroid Build Coastguard Worker  * struct/union from candidate's type graph is not mapped into corresponding
4368*f7c14bbaSAndroid Build Coastguard Worker  * struct/union from canonical type graph that itself hasn't been resolved into
4369*f7c14bbaSAndroid Build Coastguard Worker  * canonical representative. The only guarantee we have is that canonical
4370*f7c14bbaSAndroid Build Coastguard Worker  * struct/union was determined as canonical and that won't change. But any
4371*f7c14bbaSAndroid Build Coastguard Worker  * types referenced through that struct/union fields could have been not yet
4372*f7c14bbaSAndroid Build Coastguard Worker  * resolved, so in case like that it's too early to establish any kind of
4373*f7c14bbaSAndroid Build Coastguard Worker  * correspondence between structs/unions.
4374*f7c14bbaSAndroid Build Coastguard Worker  *
4375*f7c14bbaSAndroid Build Coastguard Worker  * No canonical correspondence is derived for primitive types (they are already
4376*f7c14bbaSAndroid Build Coastguard Worker  * deduplicated completely already anyway) or reference types (they rely on
4377*f7c14bbaSAndroid Build Coastguard Worker  * stability of struct/union canonical relationship for equivalence checks).
4378*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_merge_hypot_map(struct btf_dedup * d)4379*f7c14bbaSAndroid Build Coastguard Worker static void btf_dedup_merge_hypot_map(struct btf_dedup *d)
4380*f7c14bbaSAndroid Build Coastguard Worker {
4381*f7c14bbaSAndroid Build Coastguard Worker 	__u32 canon_type_id, targ_type_id;
4382*f7c14bbaSAndroid Build Coastguard Worker 	__u16 t_kind, c_kind;
4383*f7c14bbaSAndroid Build Coastguard Worker 	__u32 t_id, c_id;
4384*f7c14bbaSAndroid Build Coastguard Worker 	int i;
4385*f7c14bbaSAndroid Build Coastguard Worker 
4386*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->hypot_cnt; i++) {
4387*f7c14bbaSAndroid Build Coastguard Worker 		canon_type_id = d->hypot_list[i];
4388*f7c14bbaSAndroid Build Coastguard Worker 		targ_type_id = d->hypot_map[canon_type_id];
4389*f7c14bbaSAndroid Build Coastguard Worker 		t_id = resolve_type_id(d, targ_type_id);
4390*f7c14bbaSAndroid Build Coastguard Worker 		c_id = resolve_type_id(d, canon_type_id);
4391*f7c14bbaSAndroid Build Coastguard Worker 		t_kind = btf_kind(btf__type_by_id(d->btf, t_id));
4392*f7c14bbaSAndroid Build Coastguard Worker 		c_kind = btf_kind(btf__type_by_id(d->btf, c_id));
4393*f7c14bbaSAndroid Build Coastguard Worker 		/*
4394*f7c14bbaSAndroid Build Coastguard Worker 		 * Resolve FWD into STRUCT/UNION.
4395*f7c14bbaSAndroid Build Coastguard Worker 		 * It's ok to resolve FWD into STRUCT/UNION that's not yet
4396*f7c14bbaSAndroid Build Coastguard Worker 		 * mapped to canonical representative (as opposed to
4397*f7c14bbaSAndroid Build Coastguard Worker 		 * STRUCT/UNION <--> STRUCT/UNION mapping logic below), because
4398*f7c14bbaSAndroid Build Coastguard Worker 		 * eventually that struct is going to be mapped and all resolved
4399*f7c14bbaSAndroid Build Coastguard Worker 		 * FWDs will automatically resolve to correct canonical
4400*f7c14bbaSAndroid Build Coastguard Worker 		 * representative. This will happen before ref type deduping,
4401*f7c14bbaSAndroid Build Coastguard Worker 		 * which critically depends on stability of these mapping. This
4402*f7c14bbaSAndroid Build Coastguard Worker 		 * stability is not a requirement for STRUCT/UNION equivalence
4403*f7c14bbaSAndroid Build Coastguard Worker 		 * checks, though.
4404*f7c14bbaSAndroid Build Coastguard Worker 		 */
4405*f7c14bbaSAndroid Build Coastguard Worker 
4406*f7c14bbaSAndroid Build Coastguard Worker 		/* if it's the split BTF case, we still need to point base FWD
4407*f7c14bbaSAndroid Build Coastguard Worker 		 * to STRUCT/UNION in a split BTF, because FWDs from split BTF
4408*f7c14bbaSAndroid Build Coastguard Worker 		 * will be resolved against base FWD. If we don't point base
4409*f7c14bbaSAndroid Build Coastguard Worker 		 * canonical FWD to the resolved STRUCT/UNION, then all the
4410*f7c14bbaSAndroid Build Coastguard Worker 		 * FWDs in split BTF won't be correctly resolved to a proper
4411*f7c14bbaSAndroid Build Coastguard Worker 		 * STRUCT/UNION.
4412*f7c14bbaSAndroid Build Coastguard Worker 		 */
4413*f7c14bbaSAndroid Build Coastguard Worker 		if (t_kind != BTF_KIND_FWD && c_kind == BTF_KIND_FWD)
4414*f7c14bbaSAndroid Build Coastguard Worker 			d->map[c_id] = t_id;
4415*f7c14bbaSAndroid Build Coastguard Worker 
4416*f7c14bbaSAndroid Build Coastguard Worker 		/* if graph equivalence determined that we'd need to adjust
4417*f7c14bbaSAndroid Build Coastguard Worker 		 * base canonical types, then we need to only point base FWDs
4418*f7c14bbaSAndroid Build Coastguard Worker 		 * to STRUCTs/UNIONs and do no more modifications. For all
4419*f7c14bbaSAndroid Build Coastguard Worker 		 * other purposes the type graphs were not equivalent.
4420*f7c14bbaSAndroid Build Coastguard Worker 		 */
4421*f7c14bbaSAndroid Build Coastguard Worker 		if (d->hypot_adjust_canon)
4422*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4423*f7c14bbaSAndroid Build Coastguard Worker 
4424*f7c14bbaSAndroid Build Coastguard Worker 		if (t_kind == BTF_KIND_FWD && c_kind != BTF_KIND_FWD)
4425*f7c14bbaSAndroid Build Coastguard Worker 			d->map[t_id] = c_id;
4426*f7c14bbaSAndroid Build Coastguard Worker 
4427*f7c14bbaSAndroid Build Coastguard Worker 		if ((t_kind == BTF_KIND_STRUCT || t_kind == BTF_KIND_UNION) &&
4428*f7c14bbaSAndroid Build Coastguard Worker 		    c_kind != BTF_KIND_FWD &&
4429*f7c14bbaSAndroid Build Coastguard Worker 		    is_type_mapped(d, c_id) &&
4430*f7c14bbaSAndroid Build Coastguard Worker 		    !is_type_mapped(d, t_id)) {
4431*f7c14bbaSAndroid Build Coastguard Worker 			/*
4432*f7c14bbaSAndroid Build Coastguard Worker 			 * as a perf optimization, we can map struct/union
4433*f7c14bbaSAndroid Build Coastguard Worker 			 * that's part of type graph we just verified for
4434*f7c14bbaSAndroid Build Coastguard Worker 			 * equivalence. We can do that for struct/union that has
4435*f7c14bbaSAndroid Build Coastguard Worker 			 * canonical representative only, though.
4436*f7c14bbaSAndroid Build Coastguard Worker 			 */
4437*f7c14bbaSAndroid Build Coastguard Worker 			d->map[t_id] = c_id;
4438*f7c14bbaSAndroid Build Coastguard Worker 		}
4439*f7c14bbaSAndroid Build Coastguard Worker 	}
4440*f7c14bbaSAndroid Build Coastguard Worker }
4441*f7c14bbaSAndroid Build Coastguard Worker 
4442*f7c14bbaSAndroid Build Coastguard Worker /*
4443*f7c14bbaSAndroid Build Coastguard Worker  * Deduplicate struct/union types.
4444*f7c14bbaSAndroid Build Coastguard Worker  *
4445*f7c14bbaSAndroid Build Coastguard Worker  * For each struct/union type its type signature hash is calculated, taking
4446*f7c14bbaSAndroid Build Coastguard Worker  * into account type's name, size, number, order and names of fields, but
4447*f7c14bbaSAndroid Build Coastguard Worker  * ignoring type ID's referenced from fields, because they might not be deduped
4448*f7c14bbaSAndroid Build Coastguard Worker  * completely until after reference types deduplication phase. This type hash
4449*f7c14bbaSAndroid Build Coastguard Worker  * is used to iterate over all potential canonical types, sharing same hash.
4450*f7c14bbaSAndroid Build Coastguard Worker  * For each canonical candidate we check whether type graphs that they form
4451*f7c14bbaSAndroid Build Coastguard Worker  * (through referenced types in fields and so on) are equivalent using algorithm
4452*f7c14bbaSAndroid Build Coastguard Worker  * implemented in `btf_dedup_is_equiv`. If such equivalence is found and
4453*f7c14bbaSAndroid Build Coastguard Worker  * BTF_KIND_FWD resolution is allowed, then hypothetical mapping
4454*f7c14bbaSAndroid Build Coastguard Worker  * (btf_dedup->hypot_map) produced by aforementioned type graph equivalence
4455*f7c14bbaSAndroid Build Coastguard Worker  * algorithm is used to record FWD -> STRUCT/UNION mapping. It's also used to
4456*f7c14bbaSAndroid Build Coastguard Worker  * potentially map other structs/unions to their canonical representatives,
4457*f7c14bbaSAndroid Build Coastguard Worker  * if such relationship hasn't yet been established. This speeds up algorithm
4458*f7c14bbaSAndroid Build Coastguard Worker  * by eliminating some of the duplicate work.
4459*f7c14bbaSAndroid Build Coastguard Worker  *
4460*f7c14bbaSAndroid Build Coastguard Worker  * If no matching canonical representative was found, struct/union is marked
4461*f7c14bbaSAndroid Build Coastguard Worker  * as canonical for itself and is added into btf_dedup->dedup_table hash map
4462*f7c14bbaSAndroid Build Coastguard Worker  * for further look ups.
4463*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_struct_type(struct btf_dedup * d,__u32 type_id)4464*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_struct_type(struct btf_dedup *d, __u32 type_id)
4465*f7c14bbaSAndroid Build Coastguard Worker {
4466*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *cand_type, *t;
4467*f7c14bbaSAndroid Build Coastguard Worker 	struct hashmap_entry *hash_entry;
4468*f7c14bbaSAndroid Build Coastguard Worker 	/* if we don't find equivalent type, then we are canonical */
4469*f7c14bbaSAndroid Build Coastguard Worker 	__u32 new_id = type_id;
4470*f7c14bbaSAndroid Build Coastguard Worker 	__u16 kind;
4471*f7c14bbaSAndroid Build Coastguard Worker 	long h;
4472*f7c14bbaSAndroid Build Coastguard Worker 
4473*f7c14bbaSAndroid Build Coastguard Worker 	/* already deduped or is in process of deduping (loop detected) */
4474*f7c14bbaSAndroid Build Coastguard Worker 	if (d->map[type_id] <= BTF_MAX_NR_TYPES)
4475*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4476*f7c14bbaSAndroid Build Coastguard Worker 
4477*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_type_by_id(d->btf, type_id);
4478*f7c14bbaSAndroid Build Coastguard Worker 	kind = btf_kind(t);
4479*f7c14bbaSAndroid Build Coastguard Worker 
4480*f7c14bbaSAndroid Build Coastguard Worker 	if (kind != BTF_KIND_STRUCT && kind != BTF_KIND_UNION)
4481*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4482*f7c14bbaSAndroid Build Coastguard Worker 
4483*f7c14bbaSAndroid Build Coastguard Worker 	h = btf_hash_struct(t);
4484*f7c14bbaSAndroid Build Coastguard Worker 	for_each_dedup_cand(d, hash_entry, h) {
4485*f7c14bbaSAndroid Build Coastguard Worker 		__u32 cand_id = hash_entry->value;
4486*f7c14bbaSAndroid Build Coastguard Worker 		int eq;
4487*f7c14bbaSAndroid Build Coastguard Worker 
4488*f7c14bbaSAndroid Build Coastguard Worker 		/*
4489*f7c14bbaSAndroid Build Coastguard Worker 		 * Even though btf_dedup_is_equiv() checks for
4490*f7c14bbaSAndroid Build Coastguard Worker 		 * btf_shallow_equal_struct() internally when checking two
4491*f7c14bbaSAndroid Build Coastguard Worker 		 * structs (unions) for equivalence, we need to guard here
4492*f7c14bbaSAndroid Build Coastguard Worker 		 * from picking matching FWD type as a dedup candidate.
4493*f7c14bbaSAndroid Build Coastguard Worker 		 * This can happen due to hash collision. In such case just
4494*f7c14bbaSAndroid Build Coastguard Worker 		 * relying on btf_dedup_is_equiv() would lead to potentially
4495*f7c14bbaSAndroid Build Coastguard Worker 		 * creating a loop (FWD -> STRUCT and STRUCT -> FWD), because
4496*f7c14bbaSAndroid Build Coastguard Worker 		 * FWD and compatible STRUCT/UNION are considered equivalent.
4497*f7c14bbaSAndroid Build Coastguard Worker 		 */
4498*f7c14bbaSAndroid Build Coastguard Worker 		cand_type = btf_type_by_id(d->btf, cand_id);
4499*f7c14bbaSAndroid Build Coastguard Worker 		if (!btf_shallow_equal_struct(t, cand_type))
4500*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4501*f7c14bbaSAndroid Build Coastguard Worker 
4502*f7c14bbaSAndroid Build Coastguard Worker 		btf_dedup_clear_hypot_map(d);
4503*f7c14bbaSAndroid Build Coastguard Worker 		eq = btf_dedup_is_equiv(d, type_id, cand_id);
4504*f7c14bbaSAndroid Build Coastguard Worker 		if (eq < 0)
4505*f7c14bbaSAndroid Build Coastguard Worker 			return eq;
4506*f7c14bbaSAndroid Build Coastguard Worker 		if (!eq)
4507*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4508*f7c14bbaSAndroid Build Coastguard Worker 		btf_dedup_merge_hypot_map(d);
4509*f7c14bbaSAndroid Build Coastguard Worker 		if (d->hypot_adjust_canon) /* not really equivalent */
4510*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4511*f7c14bbaSAndroid Build Coastguard Worker 		new_id = cand_id;
4512*f7c14bbaSAndroid Build Coastguard Worker 		break;
4513*f7c14bbaSAndroid Build Coastguard Worker 	}
4514*f7c14bbaSAndroid Build Coastguard Worker 
4515*f7c14bbaSAndroid Build Coastguard Worker 	d->map[type_id] = new_id;
4516*f7c14bbaSAndroid Build Coastguard Worker 	if (type_id == new_id && btf_dedup_table_add(d, h, type_id))
4517*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOMEM;
4518*f7c14bbaSAndroid Build Coastguard Worker 
4519*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4520*f7c14bbaSAndroid Build Coastguard Worker }
4521*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_struct_types(struct btf_dedup * d)4522*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_struct_types(struct btf_dedup *d)
4523*f7c14bbaSAndroid Build Coastguard Worker {
4524*f7c14bbaSAndroid Build Coastguard Worker 	int i, err;
4525*f7c14bbaSAndroid Build Coastguard Worker 
4526*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->btf->nr_types; i++) {
4527*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_dedup_struct_type(d, d->btf->start_id + i);
4528*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
4529*f7c14bbaSAndroid Build Coastguard Worker 			return err;
4530*f7c14bbaSAndroid Build Coastguard Worker 	}
4531*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4532*f7c14bbaSAndroid Build Coastguard Worker }
4533*f7c14bbaSAndroid Build Coastguard Worker 
4534*f7c14bbaSAndroid Build Coastguard Worker /*
4535*f7c14bbaSAndroid Build Coastguard Worker  * Deduplicate reference type.
4536*f7c14bbaSAndroid Build Coastguard Worker  *
4537*f7c14bbaSAndroid Build Coastguard Worker  * Once all primitive and struct/union types got deduplicated, we can easily
4538*f7c14bbaSAndroid Build Coastguard Worker  * deduplicate all other (reference) BTF types. This is done in two steps:
4539*f7c14bbaSAndroid Build Coastguard Worker  *
4540*f7c14bbaSAndroid Build Coastguard Worker  * 1. Resolve all referenced type IDs into their canonical type IDs. This
4541*f7c14bbaSAndroid Build Coastguard Worker  * resolution can be done either immediately for primitive or struct/union types
4542*f7c14bbaSAndroid Build Coastguard Worker  * (because they were deduped in previous two phases) or recursively for
4543*f7c14bbaSAndroid Build Coastguard Worker  * reference types. Recursion will always terminate at either primitive or
4544*f7c14bbaSAndroid Build Coastguard Worker  * struct/union type, at which point we can "unwind" chain of reference types
4545*f7c14bbaSAndroid Build Coastguard Worker  * one by one. There is no danger of encountering cycles because in C type
4546*f7c14bbaSAndroid Build Coastguard Worker  * system the only way to form type cycle is through struct/union, so any chain
4547*f7c14bbaSAndroid Build Coastguard Worker  * of reference types, even those taking part in a type cycle, will inevitably
4548*f7c14bbaSAndroid Build Coastguard Worker  * reach struct/union at some point.
4549*f7c14bbaSAndroid Build Coastguard Worker  *
4550*f7c14bbaSAndroid Build Coastguard Worker  * 2. Once all referenced type IDs are resolved into canonical ones, BTF type
4551*f7c14bbaSAndroid Build Coastguard Worker  * becomes "stable", in the sense that no further deduplication will cause
4552*f7c14bbaSAndroid Build Coastguard Worker  * any changes to it. With that, it's now possible to calculate type's signature
4553*f7c14bbaSAndroid Build Coastguard Worker  * hash (this time taking into account referenced type IDs) and loop over all
4554*f7c14bbaSAndroid Build Coastguard Worker  * potential canonical representatives. If no match was found, current type
4555*f7c14bbaSAndroid Build Coastguard Worker  * will become canonical representative of itself and will be added into
4556*f7c14bbaSAndroid Build Coastguard Worker  * btf_dedup->dedup_table as another possible canonical representative.
4557*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_ref_type(struct btf_dedup * d,__u32 type_id)4558*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
4559*f7c14bbaSAndroid Build Coastguard Worker {
4560*f7c14bbaSAndroid Build Coastguard Worker 	struct hashmap_entry *hash_entry;
4561*f7c14bbaSAndroid Build Coastguard Worker 	__u32 new_id = type_id, cand_id;
4562*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t, *cand;
4563*f7c14bbaSAndroid Build Coastguard Worker 	/* if we don't find equivalent type, then we are representative type */
4564*f7c14bbaSAndroid Build Coastguard Worker 	int ref_type_id;
4565*f7c14bbaSAndroid Build Coastguard Worker 	long h;
4566*f7c14bbaSAndroid Build Coastguard Worker 
4567*f7c14bbaSAndroid Build Coastguard Worker 	if (d->map[type_id] == BTF_IN_PROGRESS_ID)
4568*f7c14bbaSAndroid Build Coastguard Worker 		return -ELOOP;
4569*f7c14bbaSAndroid Build Coastguard Worker 	if (d->map[type_id] <= BTF_MAX_NR_TYPES)
4570*f7c14bbaSAndroid Build Coastguard Worker 		return resolve_type_id(d, type_id);
4571*f7c14bbaSAndroid Build Coastguard Worker 
4572*f7c14bbaSAndroid Build Coastguard Worker 	t = btf_type_by_id(d->btf, type_id);
4573*f7c14bbaSAndroid Build Coastguard Worker 	d->map[type_id] = BTF_IN_PROGRESS_ID;
4574*f7c14bbaSAndroid Build Coastguard Worker 
4575*f7c14bbaSAndroid Build Coastguard Worker 	switch (btf_kind(t)) {
4576*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
4577*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
4578*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
4579*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
4580*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
4581*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC:
4582*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
4583*f7c14bbaSAndroid Build Coastguard Worker 		ref_type_id = btf_dedup_ref_type(d, t->type);
4584*f7c14bbaSAndroid Build Coastguard Worker 		if (ref_type_id < 0)
4585*f7c14bbaSAndroid Build Coastguard Worker 			return ref_type_id;
4586*f7c14bbaSAndroid Build Coastguard Worker 		t->type = ref_type_id;
4587*f7c14bbaSAndroid Build Coastguard Worker 
4588*f7c14bbaSAndroid Build Coastguard Worker 		h = btf_hash_common(t);
4589*f7c14bbaSAndroid Build Coastguard Worker 		for_each_dedup_cand(d, hash_entry, h) {
4590*f7c14bbaSAndroid Build Coastguard Worker 			cand_id = hash_entry->value;
4591*f7c14bbaSAndroid Build Coastguard Worker 			cand = btf_type_by_id(d->btf, cand_id);
4592*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_equal_common(t, cand)) {
4593*f7c14bbaSAndroid Build Coastguard Worker 				new_id = cand_id;
4594*f7c14bbaSAndroid Build Coastguard Worker 				break;
4595*f7c14bbaSAndroid Build Coastguard Worker 			}
4596*f7c14bbaSAndroid Build Coastguard Worker 		}
4597*f7c14bbaSAndroid Build Coastguard Worker 		break;
4598*f7c14bbaSAndroid Build Coastguard Worker 
4599*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DECL_TAG:
4600*f7c14bbaSAndroid Build Coastguard Worker 		ref_type_id = btf_dedup_ref_type(d, t->type);
4601*f7c14bbaSAndroid Build Coastguard Worker 		if (ref_type_id < 0)
4602*f7c14bbaSAndroid Build Coastguard Worker 			return ref_type_id;
4603*f7c14bbaSAndroid Build Coastguard Worker 		t->type = ref_type_id;
4604*f7c14bbaSAndroid Build Coastguard Worker 
4605*f7c14bbaSAndroid Build Coastguard Worker 		h = btf_hash_int_decl_tag(t);
4606*f7c14bbaSAndroid Build Coastguard Worker 		for_each_dedup_cand(d, hash_entry, h) {
4607*f7c14bbaSAndroid Build Coastguard Worker 			cand_id = hash_entry->value;
4608*f7c14bbaSAndroid Build Coastguard Worker 			cand = btf_type_by_id(d->btf, cand_id);
4609*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_equal_int_tag(t, cand)) {
4610*f7c14bbaSAndroid Build Coastguard Worker 				new_id = cand_id;
4611*f7c14bbaSAndroid Build Coastguard Worker 				break;
4612*f7c14bbaSAndroid Build Coastguard Worker 			}
4613*f7c14bbaSAndroid Build Coastguard Worker 		}
4614*f7c14bbaSAndroid Build Coastguard Worker 		break;
4615*f7c14bbaSAndroid Build Coastguard Worker 
4616*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY: {
4617*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_array *info = btf_array(t);
4618*f7c14bbaSAndroid Build Coastguard Worker 
4619*f7c14bbaSAndroid Build Coastguard Worker 		ref_type_id = btf_dedup_ref_type(d, info->type);
4620*f7c14bbaSAndroid Build Coastguard Worker 		if (ref_type_id < 0)
4621*f7c14bbaSAndroid Build Coastguard Worker 			return ref_type_id;
4622*f7c14bbaSAndroid Build Coastguard Worker 		info->type = ref_type_id;
4623*f7c14bbaSAndroid Build Coastguard Worker 
4624*f7c14bbaSAndroid Build Coastguard Worker 		ref_type_id = btf_dedup_ref_type(d, info->index_type);
4625*f7c14bbaSAndroid Build Coastguard Worker 		if (ref_type_id < 0)
4626*f7c14bbaSAndroid Build Coastguard Worker 			return ref_type_id;
4627*f7c14bbaSAndroid Build Coastguard Worker 		info->index_type = ref_type_id;
4628*f7c14bbaSAndroid Build Coastguard Worker 
4629*f7c14bbaSAndroid Build Coastguard Worker 		h = btf_hash_array(t);
4630*f7c14bbaSAndroid Build Coastguard Worker 		for_each_dedup_cand(d, hash_entry, h) {
4631*f7c14bbaSAndroid Build Coastguard Worker 			cand_id = hash_entry->value;
4632*f7c14bbaSAndroid Build Coastguard Worker 			cand = btf_type_by_id(d->btf, cand_id);
4633*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_equal_array(t, cand)) {
4634*f7c14bbaSAndroid Build Coastguard Worker 				new_id = cand_id;
4635*f7c14bbaSAndroid Build Coastguard Worker 				break;
4636*f7c14bbaSAndroid Build Coastguard Worker 			}
4637*f7c14bbaSAndroid Build Coastguard Worker 		}
4638*f7c14bbaSAndroid Build Coastguard Worker 		break;
4639*f7c14bbaSAndroid Build Coastguard Worker 	}
4640*f7c14bbaSAndroid Build Coastguard Worker 
4641*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO: {
4642*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_param *param;
4643*f7c14bbaSAndroid Build Coastguard Worker 		__u16 vlen;
4644*f7c14bbaSAndroid Build Coastguard Worker 		int i;
4645*f7c14bbaSAndroid Build Coastguard Worker 
4646*f7c14bbaSAndroid Build Coastguard Worker 		ref_type_id = btf_dedup_ref_type(d, t->type);
4647*f7c14bbaSAndroid Build Coastguard Worker 		if (ref_type_id < 0)
4648*f7c14bbaSAndroid Build Coastguard Worker 			return ref_type_id;
4649*f7c14bbaSAndroid Build Coastguard Worker 		t->type = ref_type_id;
4650*f7c14bbaSAndroid Build Coastguard Worker 
4651*f7c14bbaSAndroid Build Coastguard Worker 		vlen = btf_vlen(t);
4652*f7c14bbaSAndroid Build Coastguard Worker 		param = btf_params(t);
4653*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0; i < vlen; i++) {
4654*f7c14bbaSAndroid Build Coastguard Worker 			ref_type_id = btf_dedup_ref_type(d, param->type);
4655*f7c14bbaSAndroid Build Coastguard Worker 			if (ref_type_id < 0)
4656*f7c14bbaSAndroid Build Coastguard Worker 				return ref_type_id;
4657*f7c14bbaSAndroid Build Coastguard Worker 			param->type = ref_type_id;
4658*f7c14bbaSAndroid Build Coastguard Worker 			param++;
4659*f7c14bbaSAndroid Build Coastguard Worker 		}
4660*f7c14bbaSAndroid Build Coastguard Worker 
4661*f7c14bbaSAndroid Build Coastguard Worker 		h = btf_hash_fnproto(t);
4662*f7c14bbaSAndroid Build Coastguard Worker 		for_each_dedup_cand(d, hash_entry, h) {
4663*f7c14bbaSAndroid Build Coastguard Worker 			cand_id = hash_entry->value;
4664*f7c14bbaSAndroid Build Coastguard Worker 			cand = btf_type_by_id(d->btf, cand_id);
4665*f7c14bbaSAndroid Build Coastguard Worker 			if (btf_equal_fnproto(t, cand)) {
4666*f7c14bbaSAndroid Build Coastguard Worker 				new_id = cand_id;
4667*f7c14bbaSAndroid Build Coastguard Worker 				break;
4668*f7c14bbaSAndroid Build Coastguard Worker 			}
4669*f7c14bbaSAndroid Build Coastguard Worker 		}
4670*f7c14bbaSAndroid Build Coastguard Worker 		break;
4671*f7c14bbaSAndroid Build Coastguard Worker 	}
4672*f7c14bbaSAndroid Build Coastguard Worker 
4673*f7c14bbaSAndroid Build Coastguard Worker 	default:
4674*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
4675*f7c14bbaSAndroid Build Coastguard Worker 	}
4676*f7c14bbaSAndroid Build Coastguard Worker 
4677*f7c14bbaSAndroid Build Coastguard Worker 	d->map[type_id] = new_id;
4678*f7c14bbaSAndroid Build Coastguard Worker 	if (type_id == new_id && btf_dedup_table_add(d, h, type_id))
4679*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOMEM;
4680*f7c14bbaSAndroid Build Coastguard Worker 
4681*f7c14bbaSAndroid Build Coastguard Worker 	return new_id;
4682*f7c14bbaSAndroid Build Coastguard Worker }
4683*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_ref_types(struct btf_dedup * d)4684*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_ref_types(struct btf_dedup *d)
4685*f7c14bbaSAndroid Build Coastguard Worker {
4686*f7c14bbaSAndroid Build Coastguard Worker 	int i, err;
4687*f7c14bbaSAndroid Build Coastguard Worker 
4688*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->btf->nr_types; i++) {
4689*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_dedup_ref_type(d, d->btf->start_id + i);
4690*f7c14bbaSAndroid Build Coastguard Worker 		if (err < 0)
4691*f7c14bbaSAndroid Build Coastguard Worker 			return err;
4692*f7c14bbaSAndroid Build Coastguard Worker 	}
4693*f7c14bbaSAndroid Build Coastguard Worker 	/* we won't need d->dedup_table anymore */
4694*f7c14bbaSAndroid Build Coastguard Worker 	hashmap__free(d->dedup_table);
4695*f7c14bbaSAndroid Build Coastguard Worker 	d->dedup_table = NULL;
4696*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4697*f7c14bbaSAndroid Build Coastguard Worker }
4698*f7c14bbaSAndroid Build Coastguard Worker 
4699*f7c14bbaSAndroid Build Coastguard Worker /*
4700*f7c14bbaSAndroid Build Coastguard Worker  * Collect a map from type names to type ids for all canonical structs
4701*f7c14bbaSAndroid Build Coastguard Worker  * and unions. If the same name is shared by several canonical types
4702*f7c14bbaSAndroid Build Coastguard Worker  * use a special value 0 to indicate this fact.
4703*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_fill_unique_names_map(struct btf_dedup * d,struct hashmap * names_map)4704*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_fill_unique_names_map(struct btf_dedup *d, struct hashmap *names_map)
4705*f7c14bbaSAndroid Build Coastguard Worker {
4706*f7c14bbaSAndroid Build Coastguard Worker 	__u32 nr_types = btf__type_cnt(d->btf);
4707*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t;
4708*f7c14bbaSAndroid Build Coastguard Worker 	__u32 type_id;
4709*f7c14bbaSAndroid Build Coastguard Worker 	__u16 kind;
4710*f7c14bbaSAndroid Build Coastguard Worker 	int err;
4711*f7c14bbaSAndroid Build Coastguard Worker 
4712*f7c14bbaSAndroid Build Coastguard Worker 	/*
4713*f7c14bbaSAndroid Build Coastguard Worker 	 * Iterate over base and split module ids in order to get all
4714*f7c14bbaSAndroid Build Coastguard Worker 	 * available structs in the map.
4715*f7c14bbaSAndroid Build Coastguard Worker 	 */
4716*f7c14bbaSAndroid Build Coastguard Worker 	for (type_id = 1; type_id < nr_types; ++type_id) {
4717*f7c14bbaSAndroid Build Coastguard Worker 		t = btf_type_by_id(d->btf, type_id);
4718*f7c14bbaSAndroid Build Coastguard Worker 		kind = btf_kind(t);
4719*f7c14bbaSAndroid Build Coastguard Worker 
4720*f7c14bbaSAndroid Build Coastguard Worker 		if (kind != BTF_KIND_STRUCT && kind != BTF_KIND_UNION)
4721*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4722*f7c14bbaSAndroid Build Coastguard Worker 
4723*f7c14bbaSAndroid Build Coastguard Worker 		/* Skip non-canonical types */
4724*f7c14bbaSAndroid Build Coastguard Worker 		if (type_id != d->map[type_id])
4725*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4726*f7c14bbaSAndroid Build Coastguard Worker 
4727*f7c14bbaSAndroid Build Coastguard Worker 		err = hashmap__add(names_map, t->name_off, type_id);
4728*f7c14bbaSAndroid Build Coastguard Worker 		if (err == -EEXIST)
4729*f7c14bbaSAndroid Build Coastguard Worker 			err = hashmap__set(names_map, t->name_off, 0, NULL, NULL);
4730*f7c14bbaSAndroid Build Coastguard Worker 
4731*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
4732*f7c14bbaSAndroid Build Coastguard Worker 			return err;
4733*f7c14bbaSAndroid Build Coastguard Worker 	}
4734*f7c14bbaSAndroid Build Coastguard Worker 
4735*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4736*f7c14bbaSAndroid Build Coastguard Worker }
4737*f7c14bbaSAndroid Build Coastguard Worker 
btf_dedup_resolve_fwd(struct btf_dedup * d,struct hashmap * names_map,__u32 type_id)4738*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_resolve_fwd(struct btf_dedup *d, struct hashmap *names_map, __u32 type_id)
4739*f7c14bbaSAndroid Build Coastguard Worker {
4740*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *t = btf_type_by_id(d->btf, type_id);
4741*f7c14bbaSAndroid Build Coastguard Worker 	enum btf_fwd_kind fwd_kind = btf_kflag(t);
4742*f7c14bbaSAndroid Build Coastguard Worker 	__u16 cand_kind, kind = btf_kind(t);
4743*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_type *cand_t;
4744*f7c14bbaSAndroid Build Coastguard Worker 	uintptr_t cand_id;
4745*f7c14bbaSAndroid Build Coastguard Worker 
4746*f7c14bbaSAndroid Build Coastguard Worker 	if (kind != BTF_KIND_FWD)
4747*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4748*f7c14bbaSAndroid Build Coastguard Worker 
4749*f7c14bbaSAndroid Build Coastguard Worker 	/* Skip if this FWD already has a mapping */
4750*f7c14bbaSAndroid Build Coastguard Worker 	if (type_id != d->map[type_id])
4751*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4752*f7c14bbaSAndroid Build Coastguard Worker 
4753*f7c14bbaSAndroid Build Coastguard Worker 	if (!hashmap__find(names_map, t->name_off, &cand_id))
4754*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4755*f7c14bbaSAndroid Build Coastguard Worker 
4756*f7c14bbaSAndroid Build Coastguard Worker 	/* Zero is a special value indicating that name is not unique */
4757*f7c14bbaSAndroid Build Coastguard Worker 	if (!cand_id)
4758*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4759*f7c14bbaSAndroid Build Coastguard Worker 
4760*f7c14bbaSAndroid Build Coastguard Worker 	cand_t = btf_type_by_id(d->btf, cand_id);
4761*f7c14bbaSAndroid Build Coastguard Worker 	cand_kind = btf_kind(cand_t);
4762*f7c14bbaSAndroid Build Coastguard Worker 	if ((cand_kind == BTF_KIND_STRUCT && fwd_kind != BTF_FWD_STRUCT) ||
4763*f7c14bbaSAndroid Build Coastguard Worker 	    (cand_kind == BTF_KIND_UNION && fwd_kind != BTF_FWD_UNION))
4764*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4765*f7c14bbaSAndroid Build Coastguard Worker 
4766*f7c14bbaSAndroid Build Coastguard Worker 	d->map[type_id] = cand_id;
4767*f7c14bbaSAndroid Build Coastguard Worker 
4768*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4769*f7c14bbaSAndroid Build Coastguard Worker }
4770*f7c14bbaSAndroid Build Coastguard Worker 
4771*f7c14bbaSAndroid Build Coastguard Worker /*
4772*f7c14bbaSAndroid Build Coastguard Worker  * Resolve unambiguous forward declarations.
4773*f7c14bbaSAndroid Build Coastguard Worker  *
4774*f7c14bbaSAndroid Build Coastguard Worker  * The lion's share of all FWD declarations is resolved during
4775*f7c14bbaSAndroid Build Coastguard Worker  * `btf_dedup_struct_types` phase when different type graphs are
4776*f7c14bbaSAndroid Build Coastguard Worker  * compared against each other. However, if in some compilation unit a
4777*f7c14bbaSAndroid Build Coastguard Worker  * FWD declaration is not a part of a type graph compared against
4778*f7c14bbaSAndroid Build Coastguard Worker  * another type graph that declaration's canonical type would not be
4779*f7c14bbaSAndroid Build Coastguard Worker  * changed. Example:
4780*f7c14bbaSAndroid Build Coastguard Worker  *
4781*f7c14bbaSAndroid Build Coastguard Worker  * CU #1:
4782*f7c14bbaSAndroid Build Coastguard Worker  *
4783*f7c14bbaSAndroid Build Coastguard Worker  * struct foo;
4784*f7c14bbaSAndroid Build Coastguard Worker  * struct foo *some_global;
4785*f7c14bbaSAndroid Build Coastguard Worker  *
4786*f7c14bbaSAndroid Build Coastguard Worker  * CU #2:
4787*f7c14bbaSAndroid Build Coastguard Worker  *
4788*f7c14bbaSAndroid Build Coastguard Worker  * struct foo { int u; };
4789*f7c14bbaSAndroid Build Coastguard Worker  * struct foo *another_global;
4790*f7c14bbaSAndroid Build Coastguard Worker  *
4791*f7c14bbaSAndroid Build Coastguard Worker  * After `btf_dedup_struct_types` the BTF looks as follows:
4792*f7c14bbaSAndroid Build Coastguard Worker  *
4793*f7c14bbaSAndroid Build Coastguard Worker  * [1] STRUCT 'foo' size=4 vlen=1 ...
4794*f7c14bbaSAndroid Build Coastguard Worker  * [2] INT 'int' size=4 ...
4795*f7c14bbaSAndroid Build Coastguard Worker  * [3] PTR '(anon)' type_id=1
4796*f7c14bbaSAndroid Build Coastguard Worker  * [4] FWD 'foo' fwd_kind=struct
4797*f7c14bbaSAndroid Build Coastguard Worker  * [5] PTR '(anon)' type_id=4
4798*f7c14bbaSAndroid Build Coastguard Worker  *
4799*f7c14bbaSAndroid Build Coastguard Worker  * This pass assumes that such FWD declarations should be mapped to
4800*f7c14bbaSAndroid Build Coastguard Worker  * structs or unions with identical name in case if the name is not
4801*f7c14bbaSAndroid Build Coastguard Worker  * ambiguous.
4802*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_resolve_fwds(struct btf_dedup * d)4803*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_resolve_fwds(struct btf_dedup *d)
4804*f7c14bbaSAndroid Build Coastguard Worker {
4805*f7c14bbaSAndroid Build Coastguard Worker 	int i, err;
4806*f7c14bbaSAndroid Build Coastguard Worker 	struct hashmap *names_map;
4807*f7c14bbaSAndroid Build Coastguard Worker 
4808*f7c14bbaSAndroid Build Coastguard Worker 	names_map = hashmap__new(btf_dedup_identity_hash_fn, btf_dedup_equal_fn, NULL);
4809*f7c14bbaSAndroid Build Coastguard Worker 	if (IS_ERR(names_map))
4810*f7c14bbaSAndroid Build Coastguard Worker 		return PTR_ERR(names_map);
4811*f7c14bbaSAndroid Build Coastguard Worker 
4812*f7c14bbaSAndroid Build Coastguard Worker 	err = btf_dedup_fill_unique_names_map(d, names_map);
4813*f7c14bbaSAndroid Build Coastguard Worker 	if (err < 0)
4814*f7c14bbaSAndroid Build Coastguard Worker 		goto exit;
4815*f7c14bbaSAndroid Build Coastguard Worker 
4816*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->btf->nr_types; i++) {
4817*f7c14bbaSAndroid Build Coastguard Worker 		err = btf_dedup_resolve_fwd(d, names_map, d->btf->start_id + i);
4818*f7c14bbaSAndroid Build Coastguard Worker 		if (err < 0)
4819*f7c14bbaSAndroid Build Coastguard Worker 			break;
4820*f7c14bbaSAndroid Build Coastguard Worker 	}
4821*f7c14bbaSAndroid Build Coastguard Worker 
4822*f7c14bbaSAndroid Build Coastguard Worker exit:
4823*f7c14bbaSAndroid Build Coastguard Worker 	hashmap__free(names_map);
4824*f7c14bbaSAndroid Build Coastguard Worker 	return err;
4825*f7c14bbaSAndroid Build Coastguard Worker }
4826*f7c14bbaSAndroid Build Coastguard Worker 
4827*f7c14bbaSAndroid Build Coastguard Worker /*
4828*f7c14bbaSAndroid Build Coastguard Worker  * Compact types.
4829*f7c14bbaSAndroid Build Coastguard Worker  *
4830*f7c14bbaSAndroid Build Coastguard Worker  * After we established for each type its corresponding canonical representative
4831*f7c14bbaSAndroid Build Coastguard Worker  * type, we now can eliminate types that are not canonical and leave only
4832*f7c14bbaSAndroid Build Coastguard Worker  * canonical ones layed out sequentially in memory by copying them over
4833*f7c14bbaSAndroid Build Coastguard Worker  * duplicates. During compaction btf_dedup->hypot_map array is reused to store
4834*f7c14bbaSAndroid Build Coastguard Worker  * a map from original type ID to a new compacted type ID, which will be used
4835*f7c14bbaSAndroid Build Coastguard Worker  * during next phase to "fix up" type IDs, referenced from struct/union and
4836*f7c14bbaSAndroid Build Coastguard Worker  * reference types.
4837*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_compact_types(struct btf_dedup * d)4838*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_compact_types(struct btf_dedup *d)
4839*f7c14bbaSAndroid Build Coastguard Worker {
4840*f7c14bbaSAndroid Build Coastguard Worker 	__u32 *new_offs;
4841*f7c14bbaSAndroid Build Coastguard Worker 	__u32 next_type_id = d->btf->start_id;
4842*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_type *t;
4843*f7c14bbaSAndroid Build Coastguard Worker 	void *p;
4844*f7c14bbaSAndroid Build Coastguard Worker 	int i, id, len;
4845*f7c14bbaSAndroid Build Coastguard Worker 
4846*f7c14bbaSAndroid Build Coastguard Worker 	/* we are going to reuse hypot_map to store compaction remapping */
4847*f7c14bbaSAndroid Build Coastguard Worker 	d->hypot_map[0] = 0;
4848*f7c14bbaSAndroid Build Coastguard Worker 	/* base BTF types are not renumbered */
4849*f7c14bbaSAndroid Build Coastguard Worker 	for (id = 1; id < d->btf->start_id; id++)
4850*f7c14bbaSAndroid Build Coastguard Worker 		d->hypot_map[id] = id;
4851*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0, id = d->btf->start_id; i < d->btf->nr_types; i++, id++)
4852*f7c14bbaSAndroid Build Coastguard Worker 		d->hypot_map[id] = BTF_UNPROCESSED_ID;
4853*f7c14bbaSAndroid Build Coastguard Worker 
4854*f7c14bbaSAndroid Build Coastguard Worker 	p = d->btf->types_data;
4855*f7c14bbaSAndroid Build Coastguard Worker 
4856*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0, id = d->btf->start_id; i < d->btf->nr_types; i++, id++) {
4857*f7c14bbaSAndroid Build Coastguard Worker 		if (d->map[id] != id)
4858*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4859*f7c14bbaSAndroid Build Coastguard Worker 
4860*f7c14bbaSAndroid Build Coastguard Worker 		t = btf__type_by_id(d->btf, id);
4861*f7c14bbaSAndroid Build Coastguard Worker 		len = btf_type_size(t);
4862*f7c14bbaSAndroid Build Coastguard Worker 		if (len < 0)
4863*f7c14bbaSAndroid Build Coastguard Worker 			return len;
4864*f7c14bbaSAndroid Build Coastguard Worker 
4865*f7c14bbaSAndroid Build Coastguard Worker 		memmove(p, t, len);
4866*f7c14bbaSAndroid Build Coastguard Worker 		d->hypot_map[id] = next_type_id;
4867*f7c14bbaSAndroid Build Coastguard Worker 		d->btf->type_offs[next_type_id - d->btf->start_id] = p - d->btf->types_data;
4868*f7c14bbaSAndroid Build Coastguard Worker 		p += len;
4869*f7c14bbaSAndroid Build Coastguard Worker 		next_type_id++;
4870*f7c14bbaSAndroid Build Coastguard Worker 	}
4871*f7c14bbaSAndroid Build Coastguard Worker 
4872*f7c14bbaSAndroid Build Coastguard Worker 	/* shrink struct btf's internal types index and update btf_header */
4873*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->nr_types = next_type_id - d->btf->start_id;
4874*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->type_offs_cap = d->btf->nr_types;
4875*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->hdr->type_len = p - d->btf->types_data;
4876*f7c14bbaSAndroid Build Coastguard Worker 	new_offs = libbpf_reallocarray(d->btf->type_offs, d->btf->type_offs_cap,
4877*f7c14bbaSAndroid Build Coastguard Worker 				       sizeof(*new_offs));
4878*f7c14bbaSAndroid Build Coastguard Worker 	if (d->btf->type_offs_cap && !new_offs)
4879*f7c14bbaSAndroid Build Coastguard Worker 		return -ENOMEM;
4880*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->type_offs = new_offs;
4881*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->hdr->str_off = d->btf->hdr->type_len;
4882*f7c14bbaSAndroid Build Coastguard Worker 	d->btf->raw_size = d->btf->hdr->hdr_len + d->btf->hdr->type_len + d->btf->hdr->str_len;
4883*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4884*f7c14bbaSAndroid Build Coastguard Worker }
4885*f7c14bbaSAndroid Build Coastguard Worker 
4886*f7c14bbaSAndroid Build Coastguard Worker /*
4887*f7c14bbaSAndroid Build Coastguard Worker  * Figure out final (deduplicated and compacted) type ID for provided original
4888*f7c14bbaSAndroid Build Coastguard Worker  * `type_id` by first resolving it into corresponding canonical type ID and
4889*f7c14bbaSAndroid Build Coastguard Worker  * then mapping it to a deduplicated type ID, stored in btf_dedup->hypot_map,
4890*f7c14bbaSAndroid Build Coastguard Worker  * which is populated during compaction phase.
4891*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_remap_type_id(__u32 * type_id,void * ctx)4892*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_remap_type_id(__u32 *type_id, void *ctx)
4893*f7c14bbaSAndroid Build Coastguard Worker {
4894*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_dedup *d = ctx;
4895*f7c14bbaSAndroid Build Coastguard Worker 	__u32 resolved_type_id, new_type_id;
4896*f7c14bbaSAndroid Build Coastguard Worker 
4897*f7c14bbaSAndroid Build Coastguard Worker 	resolved_type_id = resolve_type_id(d, *type_id);
4898*f7c14bbaSAndroid Build Coastguard Worker 	new_type_id = d->hypot_map[resolved_type_id];
4899*f7c14bbaSAndroid Build Coastguard Worker 	if (new_type_id > BTF_MAX_NR_TYPES)
4900*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
4901*f7c14bbaSAndroid Build Coastguard Worker 
4902*f7c14bbaSAndroid Build Coastguard Worker 	*type_id = new_type_id;
4903*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4904*f7c14bbaSAndroid Build Coastguard Worker }
4905*f7c14bbaSAndroid Build Coastguard Worker 
4906*f7c14bbaSAndroid Build Coastguard Worker /*
4907*f7c14bbaSAndroid Build Coastguard Worker  * Remap referenced type IDs into deduped type IDs.
4908*f7c14bbaSAndroid Build Coastguard Worker  *
4909*f7c14bbaSAndroid Build Coastguard Worker  * After BTF types are deduplicated and compacted, their final type IDs may
4910*f7c14bbaSAndroid Build Coastguard Worker  * differ from original ones. The map from original to a corresponding
4911*f7c14bbaSAndroid Build Coastguard Worker  * deduped type ID is stored in btf_dedup->hypot_map and is populated during
4912*f7c14bbaSAndroid Build Coastguard Worker  * compaction phase. During remapping phase we are rewriting all type IDs
4913*f7c14bbaSAndroid Build Coastguard Worker  * referenced from any BTF type (e.g., struct fields, func proto args, etc) to
4914*f7c14bbaSAndroid Build Coastguard Worker  * their final deduped type IDs.
4915*f7c14bbaSAndroid Build Coastguard Worker  */
btf_dedup_remap_types(struct btf_dedup * d)4916*f7c14bbaSAndroid Build Coastguard Worker static int btf_dedup_remap_types(struct btf_dedup *d)
4917*f7c14bbaSAndroid Build Coastguard Worker {
4918*f7c14bbaSAndroid Build Coastguard Worker 	int i, r;
4919*f7c14bbaSAndroid Build Coastguard Worker 
4920*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < d->btf->nr_types; i++) {
4921*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_type *t = btf_type_by_id(d->btf, d->btf->start_id + i);
4922*f7c14bbaSAndroid Build Coastguard Worker 
4923*f7c14bbaSAndroid Build Coastguard Worker 		r = btf_type_visit_type_ids(t, btf_dedup_remap_type_id, d);
4924*f7c14bbaSAndroid Build Coastguard Worker 		if (r)
4925*f7c14bbaSAndroid Build Coastguard Worker 			return r;
4926*f7c14bbaSAndroid Build Coastguard Worker 	}
4927*f7c14bbaSAndroid Build Coastguard Worker 
4928*f7c14bbaSAndroid Build Coastguard Worker 	if (!d->btf_ext)
4929*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
4930*f7c14bbaSAndroid Build Coastguard Worker 
4931*f7c14bbaSAndroid Build Coastguard Worker 	r = btf_ext_visit_type_ids(d->btf_ext, btf_dedup_remap_type_id, d);
4932*f7c14bbaSAndroid Build Coastguard Worker 	if (r)
4933*f7c14bbaSAndroid Build Coastguard Worker 		return r;
4934*f7c14bbaSAndroid Build Coastguard Worker 
4935*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
4936*f7c14bbaSAndroid Build Coastguard Worker }
4937*f7c14bbaSAndroid Build Coastguard Worker 
4938*f7c14bbaSAndroid Build Coastguard Worker /*
4939*f7c14bbaSAndroid Build Coastguard Worker  * Probe few well-known locations for vmlinux kernel image and try to load BTF
4940*f7c14bbaSAndroid Build Coastguard Worker  * data out of it to use for target BTF.
4941*f7c14bbaSAndroid Build Coastguard Worker  */
btf__load_vmlinux_btf(void)4942*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__load_vmlinux_btf(void)
4943*f7c14bbaSAndroid Build Coastguard Worker {
4944*f7c14bbaSAndroid Build Coastguard Worker 	const char *sysfs_btf_path = "/sys/kernel/btf/vmlinux";
4945*f7c14bbaSAndroid Build Coastguard Worker 	/* fall back locations, trying to find vmlinux on disk */
4946*f7c14bbaSAndroid Build Coastguard Worker 	const char *locations[] = {
4947*f7c14bbaSAndroid Build Coastguard Worker 		"/boot/vmlinux-%1$s",
4948*f7c14bbaSAndroid Build Coastguard Worker 		"/lib/modules/%1$s/vmlinux-%1$s",
4949*f7c14bbaSAndroid Build Coastguard Worker 		"/lib/modules/%1$s/build/vmlinux",
4950*f7c14bbaSAndroid Build Coastguard Worker 		"/usr/lib/modules/%1$s/kernel/vmlinux",
4951*f7c14bbaSAndroid Build Coastguard Worker 		"/usr/lib/debug/boot/vmlinux-%1$s",
4952*f7c14bbaSAndroid Build Coastguard Worker 		"/usr/lib/debug/boot/vmlinux-%1$s.debug",
4953*f7c14bbaSAndroid Build Coastguard Worker 		"/usr/lib/debug/lib/modules/%1$s/vmlinux",
4954*f7c14bbaSAndroid Build Coastguard Worker 	};
4955*f7c14bbaSAndroid Build Coastguard Worker 	char path[PATH_MAX + 1];
4956*f7c14bbaSAndroid Build Coastguard Worker 	struct utsname buf;
4957*f7c14bbaSAndroid Build Coastguard Worker 	struct btf *btf;
4958*f7c14bbaSAndroid Build Coastguard Worker 	int i, err;
4959*f7c14bbaSAndroid Build Coastguard Worker 
4960*f7c14bbaSAndroid Build Coastguard Worker 	/* is canonical sysfs location accessible? */
4961*f7c14bbaSAndroid Build Coastguard Worker 	if (faccessat(AT_FDCWD, sysfs_btf_path, F_OK, AT_EACCESS) < 0) {
4962*f7c14bbaSAndroid Build Coastguard Worker 		pr_warn("kernel BTF is missing at '%s', was CONFIG_DEBUG_INFO_BTF enabled?\n",
4963*f7c14bbaSAndroid Build Coastguard Worker 			sysfs_btf_path);
4964*f7c14bbaSAndroid Build Coastguard Worker 	} else {
4965*f7c14bbaSAndroid Build Coastguard Worker 		btf = btf__parse(sysfs_btf_path, NULL);
4966*f7c14bbaSAndroid Build Coastguard Worker 		if (!btf) {
4967*f7c14bbaSAndroid Build Coastguard Worker 			err = -errno;
4968*f7c14bbaSAndroid Build Coastguard Worker 			pr_warn("failed to read kernel BTF from '%s': %d\n", sysfs_btf_path, err);
4969*f7c14bbaSAndroid Build Coastguard Worker 			return libbpf_err_ptr(err);
4970*f7c14bbaSAndroid Build Coastguard Worker 		}
4971*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("loaded kernel BTF from '%s'\n", sysfs_btf_path);
4972*f7c14bbaSAndroid Build Coastguard Worker 		return btf;
4973*f7c14bbaSAndroid Build Coastguard Worker 	}
4974*f7c14bbaSAndroid Build Coastguard Worker 
4975*f7c14bbaSAndroid Build Coastguard Worker 	/* try fallback locations */
4976*f7c14bbaSAndroid Build Coastguard Worker 	uname(&buf);
4977*f7c14bbaSAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(locations); i++) {
4978*f7c14bbaSAndroid Build Coastguard Worker 		snprintf(path, PATH_MAX, locations[i], buf.release);
4979*f7c14bbaSAndroid Build Coastguard Worker 
4980*f7c14bbaSAndroid Build Coastguard Worker 		if (faccessat(AT_FDCWD, path, R_OK, AT_EACCESS))
4981*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4982*f7c14bbaSAndroid Build Coastguard Worker 
4983*f7c14bbaSAndroid Build Coastguard Worker 		btf = btf__parse(path, NULL);
4984*f7c14bbaSAndroid Build Coastguard Worker 		err = libbpf_get_error(btf);
4985*f7c14bbaSAndroid Build Coastguard Worker 		pr_debug("loading kernel BTF '%s': %d\n", path, err);
4986*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
4987*f7c14bbaSAndroid Build Coastguard Worker 			continue;
4988*f7c14bbaSAndroid Build Coastguard Worker 
4989*f7c14bbaSAndroid Build Coastguard Worker 		return btf;
4990*f7c14bbaSAndroid Build Coastguard Worker 	}
4991*f7c14bbaSAndroid Build Coastguard Worker 
4992*f7c14bbaSAndroid Build Coastguard Worker 	pr_warn("failed to find valid kernel BTF\n");
4993*f7c14bbaSAndroid Build Coastguard Worker 	return libbpf_err_ptr(-ESRCH);
4994*f7c14bbaSAndroid Build Coastguard Worker }
4995*f7c14bbaSAndroid Build Coastguard Worker 
4996*f7c14bbaSAndroid Build Coastguard Worker struct btf *libbpf_find_kernel_btf(void) __attribute__((alias("btf__load_vmlinux_btf")));
4997*f7c14bbaSAndroid Build Coastguard Worker 
btf__load_module_btf(const char * module_name,struct btf * vmlinux_btf)4998*f7c14bbaSAndroid Build Coastguard Worker struct btf *btf__load_module_btf(const char *module_name, struct btf *vmlinux_btf)
4999*f7c14bbaSAndroid Build Coastguard Worker {
5000*f7c14bbaSAndroid Build Coastguard Worker 	char path[80];
5001*f7c14bbaSAndroid Build Coastguard Worker 
5002*f7c14bbaSAndroid Build Coastguard Worker 	snprintf(path, sizeof(path), "/sys/kernel/btf/%s", module_name);
5003*f7c14bbaSAndroid Build Coastguard Worker 	return btf__parse_split(path, vmlinux_btf);
5004*f7c14bbaSAndroid Build Coastguard Worker }
5005*f7c14bbaSAndroid Build Coastguard Worker 
btf_type_visit_type_ids(struct btf_type * t,type_id_visit_fn visit,void * ctx)5006*f7c14bbaSAndroid Build Coastguard Worker int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ctx)
5007*f7c14bbaSAndroid Build Coastguard Worker {
5008*f7c14bbaSAndroid Build Coastguard Worker 	int i, n, err;
5009*f7c14bbaSAndroid Build Coastguard Worker 
5010*f7c14bbaSAndroid Build Coastguard Worker 	switch (btf_kind(t)) {
5011*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_INT:
5012*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FLOAT:
5013*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM:
5014*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64:
5015*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
5016*f7c14bbaSAndroid Build Coastguard Worker 
5017*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FWD:
5018*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_CONST:
5019*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VOLATILE:
5020*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_RESTRICT:
5021*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_PTR:
5022*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPEDEF:
5023*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC:
5024*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_VAR:
5025*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DECL_TAG:
5026*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_TYPE_TAG:
5027*f7c14bbaSAndroid Build Coastguard Worker 		return visit(&t->type, ctx);
5028*f7c14bbaSAndroid Build Coastguard Worker 
5029*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ARRAY: {
5030*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_array *a = btf_array(t);
5031*f7c14bbaSAndroid Build Coastguard Worker 
5032*f7c14bbaSAndroid Build Coastguard Worker 		err = visit(&a->type, ctx);
5033*f7c14bbaSAndroid Build Coastguard Worker 		err = err ?: visit(&a->index_type, ctx);
5034*f7c14bbaSAndroid Build Coastguard Worker 		return err;
5035*f7c14bbaSAndroid Build Coastguard Worker 	}
5036*f7c14bbaSAndroid Build Coastguard Worker 
5037*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
5038*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION: {
5039*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_member *m = btf_members(t);
5040*f7c14bbaSAndroid Build Coastguard Worker 
5041*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
5042*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&m->type, ctx);
5043*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5044*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5045*f7c14bbaSAndroid Build Coastguard Worker 		}
5046*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
5047*f7c14bbaSAndroid Build Coastguard Worker 	}
5048*f7c14bbaSAndroid Build Coastguard Worker 
5049*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO: {
5050*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_param *m = btf_params(t);
5051*f7c14bbaSAndroid Build Coastguard Worker 
5052*f7c14bbaSAndroid Build Coastguard Worker 		err = visit(&t->type, ctx);
5053*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
5054*f7c14bbaSAndroid Build Coastguard Worker 			return err;
5055*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
5056*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&m->type, ctx);
5057*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5058*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5059*f7c14bbaSAndroid Build Coastguard Worker 		}
5060*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
5061*f7c14bbaSAndroid Build Coastguard Worker 	}
5062*f7c14bbaSAndroid Build Coastguard Worker 
5063*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_DATASEC: {
5064*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_var_secinfo *m = btf_var_secinfos(t);
5065*f7c14bbaSAndroid Build Coastguard Worker 
5066*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
5067*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&m->type, ctx);
5068*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5069*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5070*f7c14bbaSAndroid Build Coastguard Worker 		}
5071*f7c14bbaSAndroid Build Coastguard Worker 		return 0;
5072*f7c14bbaSAndroid Build Coastguard Worker 	}
5073*f7c14bbaSAndroid Build Coastguard Worker 
5074*f7c14bbaSAndroid Build Coastguard Worker 	default:
5075*f7c14bbaSAndroid Build Coastguard Worker 		return -EINVAL;
5076*f7c14bbaSAndroid Build Coastguard Worker 	}
5077*f7c14bbaSAndroid Build Coastguard Worker }
5078*f7c14bbaSAndroid Build Coastguard Worker 
btf_type_visit_str_offs(struct btf_type * t,str_off_visit_fn visit,void * ctx)5079*f7c14bbaSAndroid Build Coastguard Worker int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ctx)
5080*f7c14bbaSAndroid Build Coastguard Worker {
5081*f7c14bbaSAndroid Build Coastguard Worker 	int i, n, err;
5082*f7c14bbaSAndroid Build Coastguard Worker 
5083*f7c14bbaSAndroid Build Coastguard Worker 	err = visit(&t->name_off, ctx);
5084*f7c14bbaSAndroid Build Coastguard Worker 	if (err)
5085*f7c14bbaSAndroid Build Coastguard Worker 		return err;
5086*f7c14bbaSAndroid Build Coastguard Worker 
5087*f7c14bbaSAndroid Build Coastguard Worker 	switch (btf_kind(t)) {
5088*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_STRUCT:
5089*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_UNION: {
5090*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_member *m = btf_members(t);
5091*f7c14bbaSAndroid Build Coastguard Worker 
5092*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
5093*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&m->name_off, ctx);
5094*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5095*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5096*f7c14bbaSAndroid Build Coastguard Worker 		}
5097*f7c14bbaSAndroid Build Coastguard Worker 		break;
5098*f7c14bbaSAndroid Build Coastguard Worker 	}
5099*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM: {
5100*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_enum *m = btf_enum(t);
5101*f7c14bbaSAndroid Build Coastguard Worker 
5102*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
5103*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&m->name_off, ctx);
5104*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5105*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5106*f7c14bbaSAndroid Build Coastguard Worker 		}
5107*f7c14bbaSAndroid Build Coastguard Worker 		break;
5108*f7c14bbaSAndroid Build Coastguard Worker 	}
5109*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_ENUM64: {
5110*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_enum64 *m = btf_enum64(t);
5111*f7c14bbaSAndroid Build Coastguard Worker 
5112*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
5113*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&m->name_off, ctx);
5114*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5115*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5116*f7c14bbaSAndroid Build Coastguard Worker 		}
5117*f7c14bbaSAndroid Build Coastguard Worker 		break;
5118*f7c14bbaSAndroid Build Coastguard Worker 	}
5119*f7c14bbaSAndroid Build Coastguard Worker 	case BTF_KIND_FUNC_PROTO: {
5120*f7c14bbaSAndroid Build Coastguard Worker 		struct btf_param *m = btf_params(t);
5121*f7c14bbaSAndroid Build Coastguard Worker 
5122*f7c14bbaSAndroid Build Coastguard Worker 		for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
5123*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&m->name_off, ctx);
5124*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5125*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5126*f7c14bbaSAndroid Build Coastguard Worker 		}
5127*f7c14bbaSAndroid Build Coastguard Worker 		break;
5128*f7c14bbaSAndroid Build Coastguard Worker 	}
5129*f7c14bbaSAndroid Build Coastguard Worker 	default:
5130*f7c14bbaSAndroid Build Coastguard Worker 		break;
5131*f7c14bbaSAndroid Build Coastguard Worker 	}
5132*f7c14bbaSAndroid Build Coastguard Worker 
5133*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
5134*f7c14bbaSAndroid Build Coastguard Worker }
5135*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext_visit_type_ids(struct btf_ext * btf_ext,type_id_visit_fn visit,void * ctx)5136*f7c14bbaSAndroid Build Coastguard Worker int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx)
5137*f7c14bbaSAndroid Build Coastguard Worker {
5138*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_ext_info *seg;
5139*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext_info_sec *sec;
5140*f7c14bbaSAndroid Build Coastguard Worker 	int i, err;
5141*f7c14bbaSAndroid Build Coastguard Worker 
5142*f7c14bbaSAndroid Build Coastguard Worker 	seg = &btf_ext->func_info;
5143*f7c14bbaSAndroid Build Coastguard Worker 	for_each_btf_ext_sec(seg, sec) {
5144*f7c14bbaSAndroid Build Coastguard Worker 		struct bpf_func_info_min *rec;
5145*f7c14bbaSAndroid Build Coastguard Worker 
5146*f7c14bbaSAndroid Build Coastguard Worker 		for_each_btf_ext_rec(seg, sec, i, rec) {
5147*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&rec->type_id, ctx);
5148*f7c14bbaSAndroid Build Coastguard Worker 			if (err < 0)
5149*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5150*f7c14bbaSAndroid Build Coastguard Worker 		}
5151*f7c14bbaSAndroid Build Coastguard Worker 	}
5152*f7c14bbaSAndroid Build Coastguard Worker 
5153*f7c14bbaSAndroid Build Coastguard Worker 	seg = &btf_ext->core_relo_info;
5154*f7c14bbaSAndroid Build Coastguard Worker 	for_each_btf_ext_sec(seg, sec) {
5155*f7c14bbaSAndroid Build Coastguard Worker 		struct bpf_core_relo *rec;
5156*f7c14bbaSAndroid Build Coastguard Worker 
5157*f7c14bbaSAndroid Build Coastguard Worker 		for_each_btf_ext_rec(seg, sec, i, rec) {
5158*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&rec->type_id, ctx);
5159*f7c14bbaSAndroid Build Coastguard Worker 			if (err < 0)
5160*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5161*f7c14bbaSAndroid Build Coastguard Worker 		}
5162*f7c14bbaSAndroid Build Coastguard Worker 	}
5163*f7c14bbaSAndroid Build Coastguard Worker 
5164*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
5165*f7c14bbaSAndroid Build Coastguard Worker }
5166*f7c14bbaSAndroid Build Coastguard Worker 
btf_ext_visit_str_offs(struct btf_ext * btf_ext,str_off_visit_fn visit,void * ctx)5167*f7c14bbaSAndroid Build Coastguard Worker int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx)
5168*f7c14bbaSAndroid Build Coastguard Worker {
5169*f7c14bbaSAndroid Build Coastguard Worker 	const struct btf_ext_info *seg;
5170*f7c14bbaSAndroid Build Coastguard Worker 	struct btf_ext_info_sec *sec;
5171*f7c14bbaSAndroid Build Coastguard Worker 	int i, err;
5172*f7c14bbaSAndroid Build Coastguard Worker 
5173*f7c14bbaSAndroid Build Coastguard Worker 	seg = &btf_ext->func_info;
5174*f7c14bbaSAndroid Build Coastguard Worker 	for_each_btf_ext_sec(seg, sec) {
5175*f7c14bbaSAndroid Build Coastguard Worker 		err = visit(&sec->sec_name_off, ctx);
5176*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
5177*f7c14bbaSAndroid Build Coastguard Worker 			return err;
5178*f7c14bbaSAndroid Build Coastguard Worker 	}
5179*f7c14bbaSAndroid Build Coastguard Worker 
5180*f7c14bbaSAndroid Build Coastguard Worker 	seg = &btf_ext->line_info;
5181*f7c14bbaSAndroid Build Coastguard Worker 	for_each_btf_ext_sec(seg, sec) {
5182*f7c14bbaSAndroid Build Coastguard Worker 		struct bpf_line_info_min *rec;
5183*f7c14bbaSAndroid Build Coastguard Worker 
5184*f7c14bbaSAndroid Build Coastguard Worker 		err = visit(&sec->sec_name_off, ctx);
5185*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
5186*f7c14bbaSAndroid Build Coastguard Worker 			return err;
5187*f7c14bbaSAndroid Build Coastguard Worker 
5188*f7c14bbaSAndroid Build Coastguard Worker 		for_each_btf_ext_rec(seg, sec, i, rec) {
5189*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&rec->file_name_off, ctx);
5190*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5191*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5192*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&rec->line_off, ctx);
5193*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5194*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5195*f7c14bbaSAndroid Build Coastguard Worker 		}
5196*f7c14bbaSAndroid Build Coastguard Worker 	}
5197*f7c14bbaSAndroid Build Coastguard Worker 
5198*f7c14bbaSAndroid Build Coastguard Worker 	seg = &btf_ext->core_relo_info;
5199*f7c14bbaSAndroid Build Coastguard Worker 	for_each_btf_ext_sec(seg, sec) {
5200*f7c14bbaSAndroid Build Coastguard Worker 		struct bpf_core_relo *rec;
5201*f7c14bbaSAndroid Build Coastguard Worker 
5202*f7c14bbaSAndroid Build Coastguard Worker 		err = visit(&sec->sec_name_off, ctx);
5203*f7c14bbaSAndroid Build Coastguard Worker 		if (err)
5204*f7c14bbaSAndroid Build Coastguard Worker 			return err;
5205*f7c14bbaSAndroid Build Coastguard Worker 
5206*f7c14bbaSAndroid Build Coastguard Worker 		for_each_btf_ext_rec(seg, sec, i, rec) {
5207*f7c14bbaSAndroid Build Coastguard Worker 			err = visit(&rec->access_str_off, ctx);
5208*f7c14bbaSAndroid Build Coastguard Worker 			if (err)
5209*f7c14bbaSAndroid Build Coastguard Worker 				return err;
5210*f7c14bbaSAndroid Build Coastguard Worker 		}
5211*f7c14bbaSAndroid Build Coastguard Worker 	}
5212*f7c14bbaSAndroid Build Coastguard Worker 
5213*f7c14bbaSAndroid Build Coastguard Worker 	return 0;
5214*f7c14bbaSAndroid Build Coastguard Worker }
5215