Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
   1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
   2/* Copyright (C) 2019 Facebook */
   3
   4#ifndef _GNU_SOURCE
   5#define _GNU_SOURCE
   6#endif
   7#include <ctype.h>
   8#include <errno.h>
   9#include <fcntl.h>
  10#include <linux/err.h>
  11#include <stdbool.h>
  12#include <stdio.h>
  13#include <string.h>
  14#include <unistd.h>
  15#include <bpf/bpf.h>
  16#include <bpf/libbpf.h>
  17#include <bpf/libbpf_internal.h>
  18#include <sys/types.h>
  19#include <sys/stat.h>
  20#include <sys/mman.h>
  21#include <bpf/btf.h>
  22
  23#include "json_writer.h"
  24#include "main.h"
  25
  26#define MAX_OBJ_NAME_LEN 64
  27
  28static void sanitize_identifier(char *name)
  29{
  30	int i;
  31
  32	for (i = 0; name[i]; i++)
  33		if (!isalnum(name[i]) && name[i] != '_')
  34			name[i] = '_';
  35}
  36
  37static bool str_has_prefix(const char *str, const char *prefix)
  38{
  39	return strncmp(str, prefix, strlen(prefix)) == 0;
  40}
  41
  42static bool str_has_suffix(const char *str, const char *suffix)
  43{
  44	size_t i, n1 = strlen(str), n2 = strlen(suffix);
  45
  46	if (n1 < n2)
  47		return false;
  48
  49	for (i = 0; i < n2; i++) {
  50		if (str[n1 - i - 1] != suffix[n2 - i - 1])
  51			return false;
  52	}
  53
  54	return true;
  55}
  56
  57static void get_obj_name(char *name, const char *file)
  58{
  59	/* Using basename() GNU version which doesn't modify arg. */
  60	strncpy(name, basename(file), MAX_OBJ_NAME_LEN - 1);
  61	name[MAX_OBJ_NAME_LEN - 1] = '\0';
  62	if (str_has_suffix(name, ".o"))
  63		name[strlen(name) - 2] = '\0';
  64	sanitize_identifier(name);
  65}
  66
  67static void get_header_guard(char *guard, const char *obj_name, const char *suffix)
  68{
  69	int i;
  70
  71	sprintf(guard, "__%s_%s__", obj_name, suffix);
  72	for (i = 0; guard[i]; i++)
  73		guard[i] = toupper(guard[i]);
  74}
  75
  76static bool get_map_ident(const struct bpf_map *map, char *buf, size_t buf_sz)
  77{
  78	static const char *sfxs[] = { ".data", ".rodata", ".bss", ".kconfig" };
  79	const char *name = bpf_map__name(map);
  80	int i, n;
  81
  82	if (!bpf_map__is_internal(map)) {
  83		snprintf(buf, buf_sz, "%s", name);
  84		return true;
  85	}
  86
  87	for  (i = 0, n = ARRAY_SIZE(sfxs); i < n; i++) {
  88		const char *sfx = sfxs[i], *p;
  89
  90		p = strstr(name, sfx);
  91		if (p) {
  92			snprintf(buf, buf_sz, "%s", p + 1);
  93			sanitize_identifier(buf);
  94			return true;
  95		}
  96	}
  97
  98	return false;
  99}
 100
 101static bool get_datasec_ident(const char *sec_name, char *buf, size_t buf_sz)
 102{
 103	static const char *pfxs[] = { ".data", ".rodata", ".bss", ".kconfig" };
 104	int i, n;
 105
 106	for  (i = 0, n = ARRAY_SIZE(pfxs); i < n; i++) {
 107		const char *pfx = pfxs[i];
 108
 109		if (str_has_prefix(sec_name, pfx)) {
 110			snprintf(buf, buf_sz, "%s", sec_name + 1);
 111			sanitize_identifier(buf);
 112			return true;
 113		}
 114	}
 115
 116	return false;
 117}
 118
 119static void codegen_btf_dump_printf(void *ctx, const char *fmt, va_list args)
 120{
 121	vprintf(fmt, args);
 122}
 123
 124static int codegen_datasec_def(struct bpf_object *obj,
 125			       struct btf *btf,
 126			       struct btf_dump *d,
 127			       const struct btf_type *sec,
 128			       const char *obj_name)
 129{
 130	const char *sec_name = btf__name_by_offset(btf, sec->name_off);
 131	const struct btf_var_secinfo *sec_var = btf_var_secinfos(sec);
 132	int i, err, off = 0, pad_cnt = 0, vlen = btf_vlen(sec);
 133	char var_ident[256], sec_ident[256];
 134	bool strip_mods = false;
 135
 136	if (!get_datasec_ident(sec_name, sec_ident, sizeof(sec_ident)))
 137		return 0;
 138
 139	if (strcmp(sec_name, ".kconfig") != 0)
 140		strip_mods = true;
 141
 142	printf("	struct %s__%s {\n", obj_name, sec_ident);
 143	for (i = 0; i < vlen; i++, sec_var++) {
 144		const struct btf_type *var = btf__type_by_id(btf, sec_var->type);
 145		const char *var_name = btf__name_by_offset(btf, var->name_off);
 146		DECLARE_LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts,
 147			.field_name = var_ident,
 148			.indent_level = 2,
 149			.strip_mods = strip_mods,
 150		);
 151		int need_off = sec_var->offset, align_off, align;
 152		__u32 var_type_id = var->type;
 153
 154		/* static variables are not exposed through BPF skeleton */
 155		if (btf_var(var)->linkage == BTF_VAR_STATIC)
 156			continue;
 157
 158		if (off > need_off) {
 159			p_err("Something is wrong for %s's variable #%d: need offset %d, already at %d.\n",
 160			      sec_name, i, need_off, off);
 161			return -EINVAL;
 162		}
 163
 164		align = btf__align_of(btf, var->type);
 165		if (align <= 0) {
 166			p_err("Failed to determine alignment of variable '%s': %d",
 167			      var_name, align);
 168			return -EINVAL;
 169		}
 170		/* Assume 32-bit architectures when generating data section
 171		 * struct memory layout. Given bpftool can't know which target
 172		 * host architecture it's emitting skeleton for, we need to be
 173		 * conservative and assume 32-bit one to ensure enough padding
 174		 * bytes are generated for pointer and long types. This will
 175		 * still work correctly for 64-bit architectures, because in
 176		 * the worst case we'll generate unnecessary padding field,
 177		 * which on 64-bit architectures is not strictly necessary and
 178		 * would be handled by natural 8-byte alignment. But it still
 179		 * will be a correct memory layout, based on recorded offsets
 180		 * in BTF.
 181		 */
 182		if (align > 4)
 183			align = 4;
 184
 185		align_off = (off + align - 1) / align * align;
 186		if (align_off != need_off) {
 187			printf("\t\tchar __pad%d[%d];\n",
 188			       pad_cnt, need_off - off);
 189			pad_cnt++;
 190		}
 191
 192		/* sanitize variable name, e.g., for static vars inside
 193		 * a function, it's name is '<function name>.<variable name>',
 194		 * which we'll turn into a '<function name>_<variable name>'
 195		 */
 196		var_ident[0] = '\0';
 197		strncat(var_ident, var_name, sizeof(var_ident) - 1);
 198		sanitize_identifier(var_ident);
 199
 200		printf("\t\t");
 201		err = btf_dump__emit_type_decl(d, var_type_id, &opts);
 202		if (err)
 203			return err;
 204		printf(";\n");
 205
 206		off = sec_var->offset + sec_var->size;
 207	}
 208	printf("	} *%s;\n", sec_ident);
 209	return 0;
 210}
 211
 212static const struct btf_type *find_type_for_map(struct btf *btf, const char *map_ident)
 213{
 214	int n = btf__type_cnt(btf), i;
 215	char sec_ident[256];
 216
 217	for (i = 1; i < n; i++) {
 218		const struct btf_type *t = btf__type_by_id(btf, i);
 219		const char *name;
 220
 221		if (!btf_is_datasec(t))
 222			continue;
 223
 224		name = btf__str_by_offset(btf, t->name_off);
 225		if (!get_datasec_ident(name, sec_ident, sizeof(sec_ident)))
 226			continue;
 227
 228		if (strcmp(sec_ident, map_ident) == 0)
 229			return t;
 230	}
 231	return NULL;
 232}
 233
 234static bool is_internal_mmapable_map(const struct bpf_map *map, char *buf, size_t sz)
 235{
 236	if (!bpf_map__is_internal(map) || !(bpf_map__map_flags(map) & BPF_F_MMAPABLE))
 237		return false;
 238
 239	if (!get_map_ident(map, buf, sz))
 240		return false;
 241
 242	return true;
 243}
 244
 245static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
 246{
 247	struct btf *btf = bpf_object__btf(obj);
 248	struct btf_dump *d;
 249	struct bpf_map *map;
 250	const struct btf_type *sec;
 251	char map_ident[256];
 252	int err = 0;
 253
 254	d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
 255	if (!d)
 256		return -errno;
 257
 258	bpf_object__for_each_map(map, obj) {
 259		/* only generate definitions for memory-mapped internal maps */
 260		if (!is_internal_mmapable_map(map, map_ident, sizeof(map_ident)))
 261			continue;
 262
 263		sec = find_type_for_map(btf, map_ident);
 264
 265		/* In some cases (e.g., sections like .rodata.cst16 containing
 266		 * compiler allocated string constants only) there will be
 267		 * special internal maps with no corresponding DATASEC BTF
 268		 * type. In such case, generate empty structs for each such
 269		 * map. It will still be memory-mapped and its contents
 270		 * accessible from user-space through BPF skeleton.
 271		 */
 272		if (!sec) {
 273			printf("	struct %s__%s {\n", obj_name, map_ident);
 274			printf("	} *%s;\n", map_ident);
 275		} else {
 276			err = codegen_datasec_def(obj, btf, d, sec, obj_name);
 277			if (err)
 278				goto out;
 279		}
 280	}
 281
 282
 283out:
 284	btf_dump__free(d);
 285	return err;
 286}
 287
 288static bool btf_is_ptr_to_func_proto(const struct btf *btf,
 289				     const struct btf_type *v)
 290{
 291	return btf_is_ptr(v) && btf_is_func_proto(btf__type_by_id(btf, v->type));
 292}
 293
 294static int codegen_subskel_datasecs(struct bpf_object *obj, const char *obj_name)
 295{
 296	struct btf *btf = bpf_object__btf(obj);
 297	struct btf_dump *d;
 298	struct bpf_map *map;
 299	const struct btf_type *sec, *var;
 300	const struct btf_var_secinfo *sec_var;
 301	int i, err = 0, vlen;
 302	char map_ident[256], sec_ident[256];
 303	bool strip_mods = false, needs_typeof = false;
 304	const char *sec_name, *var_name;
 305	__u32 var_type_id;
 306
 307	d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
 308	if (!d)
 309		return -errno;
 310
 311	bpf_object__for_each_map(map, obj) {
 312		/* only generate definitions for memory-mapped internal maps */
 313		if (!is_internal_mmapable_map(map, map_ident, sizeof(map_ident)))
 314			continue;
 315
 316		sec = find_type_for_map(btf, map_ident);
 317		if (!sec)
 318			continue;
 319
 320		sec_name = btf__name_by_offset(btf, sec->name_off);
 321		if (!get_datasec_ident(sec_name, sec_ident, sizeof(sec_ident)))
 322			continue;
 323
 324		strip_mods = strcmp(sec_name, ".kconfig") != 0;
 325		printf("	struct %s__%s {\n", obj_name, sec_ident);
 326
 327		sec_var = btf_var_secinfos(sec);
 328		vlen = btf_vlen(sec);
 329		for (i = 0; i < vlen; i++, sec_var++) {
 330			DECLARE_LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts,
 331				.indent_level = 2,
 332				.strip_mods = strip_mods,
 333				/* we'll print the name separately */
 334				.field_name = "",
 335			);
 336
 337			var = btf__type_by_id(btf, sec_var->type);
 338			var_name = btf__name_by_offset(btf, var->name_off);
 339			var_type_id = var->type;
 340
 341			/* static variables are not exposed through BPF skeleton */
 342			if (btf_var(var)->linkage == BTF_VAR_STATIC)
 343				continue;
 344
 345			/* The datasec member has KIND_VAR but we want the
 346			 * underlying type of the variable (e.g. KIND_INT).
 347			 */
 348			var = skip_mods_and_typedefs(btf, var->type, NULL);
 349
 350			printf("\t\t");
 351			/* Func and array members require special handling.
 352			 * Instead of producing `typename *var`, they produce
 353			 * `typeof(typename) *var`. This allows us to keep a
 354			 * similar syntax where the identifier is just prefixed
 355			 * by *, allowing us to ignore C declaration minutiae.
 356			 */
 357			needs_typeof = btf_is_array(var) || btf_is_ptr_to_func_proto(btf, var);
 358			if (needs_typeof)
 359				printf("typeof(");
 360
 361			err = btf_dump__emit_type_decl(d, var_type_id, &opts);
 362			if (err)
 363				goto out;
 364
 365			if (needs_typeof)
 366				printf(")");
 367
 368			printf(" *%s;\n", var_name);
 369		}
 370		printf("	} %s;\n", sec_ident);
 371	}
 372
 373out:
 374	btf_dump__free(d);
 375	return err;
 376}
 377
 378static void codegen(const char *template, ...)
 379{
 380	const char *src, *end;
 381	int skip_tabs = 0, n;
 382	char *s, *dst;
 383	va_list args;
 384	char c;
 385
 386	n = strlen(template);
 387	s = malloc(n + 1);
 388	if (!s)
 389		exit(-1);
 390	src = template;
 391	dst = s;
 392
 393	/* find out "baseline" indentation to skip */
 394	while ((c = *src++)) {
 395		if (c == '\t') {
 396			skip_tabs++;
 397		} else if (c == '\n') {
 398			break;
 399		} else {
 400			p_err("unrecognized character at pos %td in template '%s': '%c'",
 401			      src - template - 1, template, c);
 402			free(s);
 403			exit(-1);
 404		}
 405	}
 406
 407	while (*src) {
 408		/* skip baseline indentation tabs */
 409		for (n = skip_tabs; n > 0; n--, src++) {
 410			if (*src != '\t') {
 411				p_err("not enough tabs at pos %td in template '%s'",
 412				      src - template - 1, template);
 413				free(s);
 414				exit(-1);
 415			}
 416		}
 417		/* trim trailing whitespace */
 418		end = strchrnul(src, '\n');
 419		for (n = end - src; n > 0 && isspace(src[n - 1]); n--)
 420			;
 421		memcpy(dst, src, n);
 422		dst += n;
 423		if (*end)
 424			*dst++ = '\n';
 425		src = *end ? end + 1 : end;
 426	}
 427	*dst++ = '\0';
 428
 429	/* print out using adjusted template */
 430	va_start(args, template);
 431	n = vprintf(s, args);
 432	va_end(args);
 433
 434	free(s);
 435}
 436
 437static void print_hex(const char *data, int data_sz)
 438{
 439	int i, len;
 440
 441	for (i = 0, len = 0; i < data_sz; i++) {
 442		int w = data[i] ? 4 : 2;
 443
 444		len += w;
 445		if (len > 78) {
 446			printf("\\\n");
 447			len = w;
 448		}
 449		if (!data[i])
 450			printf("\\0");
 451		else
 452			printf("\\x%02x", (unsigned char)data[i]);
 453	}
 454}
 455
 456static size_t bpf_map_mmap_sz(const struct bpf_map *map)
 457{
 458	long page_sz = sysconf(_SC_PAGE_SIZE);
 459	size_t map_sz;
 460
 461	map_sz = (size_t)roundup(bpf_map__value_size(map), 8) * bpf_map__max_entries(map);
 462	map_sz = roundup(map_sz, page_sz);
 463	return map_sz;
 464}
 465
 466/* Emit type size asserts for all top-level fields in memory-mapped internal maps. */
 467static void codegen_asserts(struct bpf_object *obj, const char *obj_name)
 468{
 469	struct btf *btf = bpf_object__btf(obj);
 470	struct bpf_map *map;
 471	struct btf_var_secinfo *sec_var;
 472	int i, vlen;
 473	const struct btf_type *sec;
 474	char map_ident[256], var_ident[256];
 475
 476	if (!btf)
 477		return;
 478
 479	codegen("\
 480		\n\
 481		__attribute__((unused)) static void			    \n\
 482		%1$s__assert(struct %1$s *s __attribute__((unused)))	    \n\
 483		{							    \n\
 484		#ifdef __cplusplus					    \n\
 485		#define _Static_assert static_assert			    \n\
 486		#endif							    \n\
 487		", obj_name);
 488
 489	bpf_object__for_each_map(map, obj) {
 490		if (!is_internal_mmapable_map(map, map_ident, sizeof(map_ident)))
 491			continue;
 492
 493		sec = find_type_for_map(btf, map_ident);
 494		if (!sec) {
 495			/* best effort, couldn't find the type for this map */
 496			continue;
 497		}
 498
 499		sec_var = btf_var_secinfos(sec);
 500		vlen =  btf_vlen(sec);
 501
 502		for (i = 0; i < vlen; i++, sec_var++) {
 503			const struct btf_type *var = btf__type_by_id(btf, sec_var->type);
 504			const char *var_name = btf__name_by_offset(btf, var->name_off);
 505			long var_size;
 506
 507			/* static variables are not exposed through BPF skeleton */
 508			if (btf_var(var)->linkage == BTF_VAR_STATIC)
 509				continue;
 510
 511			var_size = btf__resolve_size(btf, var->type);
 512			if (var_size < 0)
 513				continue;
 514
 515			var_ident[0] = '\0';
 516			strncat(var_ident, var_name, sizeof(var_ident) - 1);
 517			sanitize_identifier(var_ident);
 518
 519			printf("\t_Static_assert(sizeof(s->%s->%s) == %ld, \"unexpected size of '%s'\");\n",
 520			       map_ident, var_ident, var_size, var_ident);
 521		}
 522	}
 523	codegen("\
 524		\n\
 525		#ifdef __cplusplus					    \n\
 526		#undef _Static_assert					    \n\
 527		#endif							    \n\
 528		}							    \n\
 529		");
 530}
 531
 532static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name)
 533{
 534	struct bpf_program *prog;
 535
 536	bpf_object__for_each_program(prog, obj) {
 537		const char *tp_name;
 538
 539		codegen("\
 540			\n\
 541			\n\
 542			static inline int					    \n\
 543			%1$s__%2$s__attach(struct %1$s *skel)			    \n\
 544			{							    \n\
 545				int prog_fd = skel->progs.%2$s.prog_fd;		    \n\
 546			", obj_name, bpf_program__name(prog));
 547
 548		switch (bpf_program__type(prog)) {
 549		case BPF_PROG_TYPE_RAW_TRACEPOINT:
 550			tp_name = strchr(bpf_program__section_name(prog), '/') + 1;
 551			printf("\tint fd = skel_raw_tracepoint_open(\"%s\", prog_fd);\n", tp_name);
 552			break;
 553		case BPF_PROG_TYPE_TRACING:
 554		case BPF_PROG_TYPE_LSM:
 555			if (bpf_program__expected_attach_type(prog) == BPF_TRACE_ITER)
 556				printf("\tint fd = skel_link_create(prog_fd, 0, BPF_TRACE_ITER);\n");
 557			else
 558				printf("\tint fd = skel_raw_tracepoint_open(NULL, prog_fd);\n");
 559			break;
 560		default:
 561			printf("\tint fd = ((void)prog_fd, 0); /* auto-attach not supported */\n");
 562			break;
 563		}
 564		codegen("\
 565			\n\
 566										    \n\
 567				if (fd > 0)					    \n\
 568					skel->links.%1$s_fd = fd;		    \n\
 569				return fd;					    \n\
 570			}							    \n\
 571			", bpf_program__name(prog));
 572	}
 573
 574	codegen("\
 575		\n\
 576									    \n\
 577		static inline int					    \n\
 578		%1$s__attach(struct %1$s *skel)				    \n\
 579		{							    \n\
 580			int ret = 0;					    \n\
 581									    \n\
 582		", obj_name);
 583
 584	bpf_object__for_each_program(prog, obj) {
 585		codegen("\
 586			\n\
 587				ret = ret < 0 ? ret : %1$s__%2$s__attach(skel);   \n\
 588			", obj_name, bpf_program__name(prog));
 589	}
 590
 591	codegen("\
 592		\n\
 593			return ret < 0 ? ret : 0;			    \n\
 594		}							    \n\
 595									    \n\
 596		static inline void					    \n\
 597		%1$s__detach(struct %1$s *skel)				    \n\
 598		{							    \n\
 599		", obj_name);
 600
 601	bpf_object__for_each_program(prog, obj) {
 602		codegen("\
 603			\n\
 604				skel_closenz(skel->links.%1$s_fd);	    \n\
 605			", bpf_program__name(prog));
 606	}
 607
 608	codegen("\
 609		\n\
 610		}							    \n\
 611		");
 612}
 613
 614static void codegen_destroy(struct bpf_object *obj, const char *obj_name)
 615{
 616	struct bpf_program *prog;
 617	struct bpf_map *map;
 618	char ident[256];
 619
 620	codegen("\
 621		\n\
 622		static void						    \n\
 623		%1$s__destroy(struct %1$s *skel)			    \n\
 624		{							    \n\
 625			if (!skel)					    \n\
 626				return;					    \n\
 627			%1$s__detach(skel);				    \n\
 628		",
 629		obj_name);
 630
 631	bpf_object__for_each_program(prog, obj) {
 632		codegen("\
 633			\n\
 634				skel_closenz(skel->progs.%1$s.prog_fd);	    \n\
 635			", bpf_program__name(prog));
 636	}
 637
 638	bpf_object__for_each_map(map, obj) {
 639		if (!get_map_ident(map, ident, sizeof(ident)))
 640			continue;
 641		if (bpf_map__is_internal(map) &&
 642		    (bpf_map__map_flags(map) & BPF_F_MMAPABLE))
 643			printf("\tskel_free_map_data(skel->%1$s, skel->maps.%1$s.initial_value, %2$zd);\n",
 644			       ident, bpf_map_mmap_sz(map));
 645		codegen("\
 646			\n\
 647				skel_closenz(skel->maps.%1$s.map_fd);	    \n\
 648			", ident);
 649	}
 650	codegen("\
 651		\n\
 652			skel_free(skel);				    \n\
 653		}							    \n\
 654		",
 655		obj_name);
 656}
 657
 658static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *header_guard)
 659{
 660	DECLARE_LIBBPF_OPTS(gen_loader_opts, opts);
 661	struct bpf_map *map;
 662	char ident[256];
 663	int err = 0;
 664
 665	err = bpf_object__gen_loader(obj, &opts);
 666	if (err)
 667		return err;
 668
 669	err = bpf_object__load(obj);
 670	if (err) {
 671		p_err("failed to load object file");
 672		goto out;
 673	}
 674	/* If there was no error during load then gen_loader_opts
 675	 * are populated with the loader program.
 676	 */
 677
 678	/* finish generating 'struct skel' */
 679	codegen("\
 680		\n\
 681		};							    \n\
 682		", obj_name);
 683
 684
 685	codegen_attach_detach(obj, obj_name);
 686
 687	codegen_destroy(obj, obj_name);
 688
 689	codegen("\
 690		\n\
 691		static inline struct %1$s *				    \n\
 692		%1$s__open(void)					    \n\
 693		{							    \n\
 694			struct %1$s *skel;				    \n\
 695									    \n\
 696			skel = skel_alloc(sizeof(*skel));		    \n\
 697			if (!skel)					    \n\
 698				goto cleanup;				    \n\
 699			skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\
 700		",
 701		obj_name, opts.data_sz);
 702	bpf_object__for_each_map(map, obj) {
 703		const void *mmap_data = NULL;
 704		size_t mmap_size = 0;
 705
 706		if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
 707			continue;
 708
 709		codegen("\
 710		\n\
 711			{						    \n\
 712				static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
 713		");
 714		mmap_data = bpf_map__initial_value(map, &mmap_size);
 715		print_hex(mmap_data, mmap_size);
 716		codegen("\
 717		\n\
 718		\";							    \n\
 719									    \n\
 720				skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\
 721								sizeof(data) - 1);\n\
 722				if (!skel->%1$s)			    \n\
 723					goto cleanup;			    \n\
 724				skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\
 725			}						    \n\
 726			", ident, bpf_map_mmap_sz(map));
 727	}
 728	codegen("\
 729		\n\
 730			return skel;					    \n\
 731		cleanup:						    \n\
 732			%1$s__destroy(skel);				    \n\
 733			return NULL;					    \n\
 734		}							    \n\
 735									    \n\
 736		static inline int					    \n\
 737		%1$s__load(struct %1$s *skel)				    \n\
 738		{							    \n\
 739			struct bpf_load_and_run_opts opts = {};		    \n\
 740			int err;					    \n\
 741			static const char opts_data[] __attribute__((__aligned__(8))) = \"\\\n\
 742		",
 743		obj_name);
 744	print_hex(opts.data, opts.data_sz);
 745	codegen("\
 746		\n\
 747		\";							    \n\
 748			static const char opts_insn[] __attribute__((__aligned__(8))) = \"\\\n\
 749		");
 750	print_hex(opts.insns, opts.insns_sz);
 751	codegen("\
 752		\n\
 753		\";							    \n\
 754									    \n\
 755			opts.ctx = (struct bpf_loader_ctx *)skel;	    \n\
 756			opts.data_sz = sizeof(opts_data) - 1;		    \n\
 757			opts.data = (void *)opts_data;			    \n\
 758			opts.insns_sz = sizeof(opts_insn) - 1;		    \n\
 759			opts.insns = (void *)opts_insn;			    \n\
 760									    \n\
 761			err = bpf_load_and_run(&opts);			    \n\
 762			if (err < 0)					    \n\
 763				return err;				    \n\
 764		");
 765	bpf_object__for_each_map(map, obj) {
 766		const char *mmap_flags;
 767
 768		if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
 769			continue;
 770
 771		if (bpf_map__map_flags(map) & BPF_F_RDONLY_PROG)
 772			mmap_flags = "PROT_READ";
 773		else
 774			mmap_flags = "PROT_READ | PROT_WRITE";
 775
 776		codegen("\
 777		\n\
 778			skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value,  \n\
 779							%2$zd, %3$s, skel->maps.%1$s.map_fd);\n\
 780			if (!skel->%1$s)				    \n\
 781				return -ENOMEM;				    \n\
 782			",
 783		       ident, bpf_map_mmap_sz(map), mmap_flags);
 784	}
 785	codegen("\
 786		\n\
 787			return 0;					    \n\
 788		}							    \n\
 789									    \n\
 790		static inline struct %1$s *				    \n\
 791		%1$s__open_and_load(void)				    \n\
 792		{							    \n\
 793			struct %1$s *skel;				    \n\
 794									    \n\
 795			skel = %1$s__open();				    \n\
 796			if (!skel)					    \n\
 797				return NULL;				    \n\
 798			if (%1$s__load(skel)) {				    \n\
 799				%1$s__destroy(skel);			    \n\
 800				return NULL;				    \n\
 801			}						    \n\
 802			return skel;					    \n\
 803		}							    \n\
 804									    \n\
 805		", obj_name);
 806
 807	codegen_asserts(obj, obj_name);
 808
 809	codegen("\
 810		\n\
 811									    \n\
 812		#endif /* %s */						    \n\
 813		",
 814		header_guard);
 815	err = 0;
 816out:
 817	return err;
 818}
 819
 820static void
 821codegen_maps_skeleton(struct bpf_object *obj, size_t map_cnt, bool mmaped)
 822{
 823	struct bpf_map *map;
 824	char ident[256];
 825	size_t i;
 826
 827	if (!map_cnt)
 828		return;
 829
 830	codegen("\
 831		\n\
 832									\n\
 833			/* maps */				    \n\
 834			s->map_cnt = %zu;			    \n\
 835			s->map_skel_sz = sizeof(*s->maps);	    \n\
 836			s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);\n\
 837			if (!s->maps) {				    \n\
 838				err = -ENOMEM;			    \n\
 839				goto err;			    \n\
 840			}					    \n\
 841		",
 842		map_cnt
 843	);
 844	i = 0;
 845	bpf_object__for_each_map(map, obj) {
 846		if (!get_map_ident(map, ident, sizeof(ident)))
 847			continue;
 848
 849		codegen("\
 850			\n\
 851									\n\
 852				s->maps[%zu].name = \"%s\";	    \n\
 853				s->maps[%zu].map = &obj->maps.%s;   \n\
 854			",
 855			i, bpf_map__name(map), i, ident);
 856		/* memory-mapped internal maps */
 857		if (mmaped && is_internal_mmapable_map(map, ident, sizeof(ident))) {
 858			printf("\ts->maps[%zu].mmaped = (void **)&obj->%s;\n",
 859				i, ident);
 860		}
 861		i++;
 862	}
 863}
 864
 865static void
 866codegen_progs_skeleton(struct bpf_object *obj, size_t prog_cnt, bool populate_links)
 867{
 868	struct bpf_program *prog;
 869	int i;
 870
 871	if (!prog_cnt)
 872		return;
 873
 874	codegen("\
 875		\n\
 876									\n\
 877			/* programs */				    \n\
 878			s->prog_cnt = %zu;			    \n\
 879			s->prog_skel_sz = sizeof(*s->progs);	    \n\
 880			s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);\n\
 881			if (!s->progs) {			    \n\
 882				err = -ENOMEM;			    \n\
 883				goto err;			    \n\
 884			}					    \n\
 885		",
 886		prog_cnt
 887	);
 888	i = 0;
 889	bpf_object__for_each_program(prog, obj) {
 890		codegen("\
 891			\n\
 892									\n\
 893				s->progs[%1$zu].name = \"%2$s\";    \n\
 894				s->progs[%1$zu].prog = &obj->progs.%2$s;\n\
 895			",
 896			i, bpf_program__name(prog));
 897
 898		if (populate_links) {
 899			codegen("\
 900				\n\
 901					s->progs[%1$zu].link = &obj->links.%2$s;\n\
 902				",
 903				i, bpf_program__name(prog));
 904		}
 905		i++;
 906	}
 907}
 908
 909static int do_skeleton(int argc, char **argv)
 910{
 911	char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
 912	size_t map_cnt = 0, prog_cnt = 0, file_sz, mmap_sz;
 913	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
 914	char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
 915	struct bpf_object *obj = NULL;
 916	const char *file;
 917	char ident[256];
 918	struct bpf_program *prog;
 919	int fd, err = -1;
 920	struct bpf_map *map;
 921	struct btf *btf;
 922	struct stat st;
 923
 924	if (!REQ_ARGS(1)) {
 925		usage();
 926		return -1;
 927	}
 928	file = GET_ARG();
 929
 930	while (argc) {
 931		if (!REQ_ARGS(2))
 932			return -1;
 933
 934		if (is_prefix(*argv, "name")) {
 935			NEXT_ARG();
 936
 937			if (obj_name[0] != '\0') {
 938				p_err("object name already specified");
 939				return -1;
 940			}
 941
 942			strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
 943			obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
 944		} else {
 945			p_err("unknown arg %s", *argv);
 946			return -1;
 947		}
 948
 949		NEXT_ARG();
 950	}
 951
 952	if (argc) {
 953		p_err("extra unknown arguments");
 954		return -1;
 955	}
 956
 957	if (stat(file, &st)) {
 958		p_err("failed to stat() %s: %s", file, strerror(errno));
 959		return -1;
 960	}
 961	file_sz = st.st_size;
 962	mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
 963	fd = open(file, O_RDONLY);
 964	if (fd < 0) {
 965		p_err("failed to open() %s: %s", file, strerror(errno));
 966		return -1;
 967	}
 968	obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
 969	if (obj_data == MAP_FAILED) {
 970		obj_data = NULL;
 971		p_err("failed to mmap() %s: %s", file, strerror(errno));
 972		goto out;
 973	}
 974	if (obj_name[0] == '\0')
 975		get_obj_name(obj_name, file);
 976	opts.object_name = obj_name;
 977	if (verifier_logs)
 978		/* log_level1 + log_level2 + stats, but not stable UAPI */
 979		opts.kernel_log_level = 1 + 2 + 4;
 980	obj = bpf_object__open_mem(obj_data, file_sz, &opts);
 981	if (!obj) {
 982		char err_buf[256];
 983
 984		err = -errno;
 985		libbpf_strerror(err, err_buf, sizeof(err_buf));
 986		p_err("failed to open BPF object file: %s", err_buf);
 987		goto out;
 988	}
 989
 990	bpf_object__for_each_map(map, obj) {
 991		if (!get_map_ident(map, ident, sizeof(ident))) {
 992			p_err("ignoring unrecognized internal map '%s'...",
 993			      bpf_map__name(map));
 994			continue;
 995		}
 996		map_cnt++;
 997	}
 998	bpf_object__for_each_program(prog, obj) {
 999		prog_cnt++;
1000	}
1001
1002	get_header_guard(header_guard, obj_name, "SKEL_H");
1003	if (use_loader) {
1004		codegen("\
1005		\n\
1006		/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
1007		/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */		    \n\
1008		#ifndef %2$s						    \n\
1009		#define %2$s						    \n\
1010									    \n\
1011		#include <bpf/skel_internal.h>				    \n\
1012									    \n\
1013		struct %1$s {						    \n\
1014			struct bpf_loader_ctx ctx;			    \n\
1015		",
1016		obj_name, header_guard
1017		);
1018	} else {
1019		codegen("\
1020		\n\
1021		/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
1022									    \n\
1023		/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */		    \n\
1024		#ifndef %2$s						    \n\
1025		#define %2$s						    \n\
1026									    \n\
1027		#include <errno.h>					    \n\
1028		#include <stdlib.h>					    \n\
1029		#include <bpf/libbpf.h>					    \n\
1030									    \n\
1031		struct %1$s {						    \n\
1032			struct bpf_object_skeleton *skeleton;		    \n\
1033			struct bpf_object *obj;				    \n\
1034		",
1035		obj_name, header_guard
1036		);
1037	}
1038
1039	if (map_cnt) {
1040		printf("\tstruct {\n");
1041		bpf_object__for_each_map(map, obj) {
1042			if (!get_map_ident(map, ident, sizeof(ident)))
1043				continue;
1044			if (use_loader)
1045				printf("\t\tstruct bpf_map_desc %s;\n", ident);
1046			else
1047				printf("\t\tstruct bpf_map *%s;\n", ident);
1048		}
1049		printf("\t} maps;\n");
1050	}
1051
1052	if (prog_cnt) {
1053		printf("\tstruct {\n");
1054		bpf_object__for_each_program(prog, obj) {
1055			if (use_loader)
1056				printf("\t\tstruct bpf_prog_desc %s;\n",
1057				       bpf_program__name(prog));
1058			else
1059				printf("\t\tstruct bpf_program *%s;\n",
1060				       bpf_program__name(prog));
1061		}
1062		printf("\t} progs;\n");
1063		printf("\tstruct {\n");
1064		bpf_object__for_each_program(prog, obj) {
1065			if (use_loader)
1066				printf("\t\tint %s_fd;\n",
1067				       bpf_program__name(prog));
1068			else
1069				printf("\t\tstruct bpf_link *%s;\n",
1070				       bpf_program__name(prog));
1071		}
1072		printf("\t} links;\n");
1073	}
1074
1075	btf = bpf_object__btf(obj);
1076	if (btf) {
1077		err = codegen_datasecs(obj, obj_name);
1078		if (err)
1079			goto out;
1080	}
1081	if (use_loader) {
1082		err = gen_trace(obj, obj_name, header_guard);
1083		goto out;
1084	}
1085
1086	codegen("\
1087		\n\
1088									    \n\
1089		#ifdef __cplusplus					    \n\
1090			static inline struct %1$s *open(const struct bpf_object_open_opts *opts = nullptr);\n\
1091			static inline struct %1$s *open_and_load();	    \n\
1092			static inline int load(struct %1$s *skel);	    \n\
1093			static inline int attach(struct %1$s *skel);	    \n\
1094			static inline void detach(struct %1$s *skel);	    \n\
1095			static inline void destroy(struct %1$s *skel);	    \n\
1096			static inline const void *elf_bytes(size_t *sz);    \n\
1097		#endif /* __cplusplus */				    \n\
1098		};							    \n\
1099									    \n\
1100		static void						    \n\
1101		%1$s__destroy(struct %1$s *obj)				    \n\
1102		{							    \n\
1103			if (!obj)					    \n\
1104				return;					    \n\
1105			if (obj->skeleton)				    \n\
1106				bpf_object__destroy_skeleton(obj->skeleton);\n\
1107			free(obj);					    \n\
1108		}							    \n\
1109									    \n\
1110		static inline int					    \n\
1111		%1$s__create_skeleton(struct %1$s *obj);		    \n\
1112									    \n\
1113		static inline struct %1$s *				    \n\
1114		%1$s__open_opts(const struct bpf_object_open_opts *opts)    \n\
1115		{							    \n\
1116			struct %1$s *obj;				    \n\
1117			int err;					    \n\
1118									    \n\
1119			obj = (struct %1$s *)calloc(1, sizeof(*obj));	    \n\
1120			if (!obj) {					    \n\
1121				errno = ENOMEM;				    \n\
1122				return NULL;				    \n\
1123			}						    \n\
1124									    \n\
1125			err = %1$s__create_skeleton(obj);		    \n\
1126			if (err)					    \n\
1127				goto err_out;				    \n\
1128									    \n\
1129			err = bpf_object__open_skeleton(obj->skeleton, opts);\n\
1130			if (err)					    \n\
1131				goto err_out;				    \n\
1132									    \n\
1133			return obj;					    \n\
1134		err_out:						    \n\
1135			%1$s__destroy(obj);				    \n\
1136			errno = -err;					    \n\
1137			return NULL;					    \n\
1138		}							    \n\
1139									    \n\
1140		static inline struct %1$s *				    \n\
1141		%1$s__open(void)					    \n\
1142		{							    \n\
1143			return %1$s__open_opts(NULL);			    \n\
1144		}							    \n\
1145									    \n\
1146		static inline int					    \n\
1147		%1$s__load(struct %1$s *obj)				    \n\
1148		{							    \n\
1149			return bpf_object__load_skeleton(obj->skeleton);    \n\
1150		}							    \n\
1151									    \n\
1152		static inline struct %1$s *				    \n\
1153		%1$s__open_and_load(void)				    \n\
1154		{							    \n\
1155			struct %1$s *obj;				    \n\
1156			int err;					    \n\
1157									    \n\
1158			obj = %1$s__open();				    \n\
1159			if (!obj)					    \n\
1160				return NULL;				    \n\
1161			err = %1$s__load(obj);				    \n\
1162			if (err) {					    \n\
1163				%1$s__destroy(obj);			    \n\
1164				errno = -err;				    \n\
1165				return NULL;				    \n\
1166			}						    \n\
1167			return obj;					    \n\
1168		}							    \n\
1169									    \n\
1170		static inline int					    \n\
1171		%1$s__attach(struct %1$s *obj)				    \n\
1172		{							    \n\
1173			return bpf_object__attach_skeleton(obj->skeleton);  \n\
1174		}							    \n\
1175									    \n\
1176		static inline void					    \n\
1177		%1$s__detach(struct %1$s *obj)				    \n\
1178		{							    \n\
1179			bpf_object__detach_skeleton(obj->skeleton);	    \n\
1180		}							    \n\
1181		",
1182		obj_name
1183	);
1184
1185	codegen("\
1186		\n\
1187									    \n\
1188		static inline const void *%1$s__elf_bytes(size_t *sz);	    \n\
1189									    \n\
1190		static inline int					    \n\
1191		%1$s__create_skeleton(struct %1$s *obj)			    \n\
1192		{							    \n\
1193			struct bpf_object_skeleton *s;			    \n\
1194			int err;					    \n\
1195									    \n\
1196			s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));\n\
1197			if (!s)	{					    \n\
1198				err = -ENOMEM;				    \n\
1199				goto err;				    \n\
1200			}						    \n\
1201									    \n\
1202			s->sz = sizeof(*s);				    \n\
1203			s->name = \"%1$s\";				    \n\
1204			s->obj = &obj->obj;				    \n\
1205		",
1206		obj_name
1207	);
1208
1209	codegen_maps_skeleton(obj, map_cnt, true /*mmaped*/);
1210	codegen_progs_skeleton(obj, prog_cnt, true /*populate_links*/);
1211
1212	codegen("\
1213		\n\
1214									    \n\
1215			s->data = %1$s__elf_bytes(&s->data_sz);		    \n\
1216									    \n\
1217			obj->skeleton = s;				    \n\
1218			return 0;					    \n\
1219		err:							    \n\
1220			bpf_object__destroy_skeleton(s);		    \n\
1221			return err;					    \n\
1222		}							    \n\
1223									    \n\
1224		static inline const void *%1$s__elf_bytes(size_t *sz)	    \n\
1225		{							    \n\
1226			static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
1227		",
1228		obj_name
1229	);
1230
1231	/* embed contents of BPF object file */
1232	print_hex(obj_data, file_sz);
1233
1234	codegen("\
1235		\n\
1236		\";							    \n\
1237									    \n\
1238			*sz = sizeof(data) - 1;				    \n\
1239			return (const void *)data;			    \n\
1240		}							    \n\
1241									    \n\
1242		#ifdef __cplusplus					    \n\
1243		struct %1$s *%1$s::open(const struct bpf_object_open_opts *opts) { return %1$s__open_opts(opts); }\n\
1244		struct %1$s *%1$s::open_and_load() { return %1$s__open_and_load(); }	\n\
1245		int %1$s::load(struct %1$s *skel) { return %1$s__load(skel); }		\n\
1246		int %1$s::attach(struct %1$s *skel) { return %1$s__attach(skel); }	\n\
1247		void %1$s::detach(struct %1$s *skel) { %1$s__detach(skel); }		\n\
1248		void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); }		\n\
1249		const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
1250		#endif /* __cplusplus */				    \n\
1251									    \n\
1252		",
1253		obj_name);
1254
1255	codegen_asserts(obj, obj_name);
1256
1257	codegen("\
1258		\n\
1259									    \n\
1260		#endif /* %1$s */					    \n\
1261		",
1262		header_guard);
1263	err = 0;
1264out:
1265	bpf_object__close(obj);
1266	if (obj_data)
1267		munmap(obj_data, mmap_sz);
1268	close(fd);
1269	return err;
1270}
1271
1272/* Subskeletons are like skeletons, except they don't own the bpf_object,
1273 * associated maps, links, etc. Instead, they know about the existence of
1274 * variables, maps, programs and are able to find their locations
1275 * _at runtime_ from an already loaded bpf_object.
1276 *
1277 * This allows for library-like BPF objects to have userspace counterparts
1278 * with access to their own items without having to know anything about the
1279 * final BPF object that the library was linked into.
1280 */
1281static int do_subskeleton(int argc, char **argv)
1282{
1283	char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SUBSKEL_H__")];
1284	size_t i, len, file_sz, map_cnt = 0, prog_cnt = 0, mmap_sz, var_cnt = 0, var_idx = 0;
1285	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
1286	char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
1287	struct bpf_object *obj = NULL;
1288	const char *file, *var_name;
1289	char ident[256];
1290	int fd, err = -1, map_type_id;
1291	const struct bpf_map *map;
1292	struct bpf_program *prog;
1293	struct btf *btf;
1294	const struct btf_type *map_type, *var_type;
1295	const struct btf_var_secinfo *var;
1296	struct stat st;
1297
1298	if (!REQ_ARGS(1)) {
1299		usage();
1300		return -1;
1301	}
1302	file = GET_ARG();
1303
1304	while (argc) {
1305		if (!REQ_ARGS(2))
1306			return -1;
1307
1308		if (is_prefix(*argv, "name")) {
1309			NEXT_ARG();
1310
1311			if (obj_name[0] != '\0') {
1312				p_err("object name already specified");
1313				return -1;
1314			}
1315
1316			strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
1317			obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
1318		} else {
1319			p_err("unknown arg %s", *argv);
1320			return -1;
1321		}
1322
1323		NEXT_ARG();
1324	}
1325
1326	if (argc) {
1327		p_err("extra unknown arguments");
1328		return -1;
1329	}
1330
1331	if (use_loader) {
1332		p_err("cannot use loader for subskeletons");
1333		return -1;
1334	}
1335
1336	if (stat(file, &st)) {
1337		p_err("failed to stat() %s: %s", file, strerror(errno));
1338		return -1;
1339	}
1340	file_sz = st.st_size;
1341	mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
1342	fd = open(file, O_RDONLY);
1343	if (fd < 0) {
1344		p_err("failed to open() %s: %s", file, strerror(errno));
1345		return -1;
1346	}
1347	obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
1348	if (obj_data == MAP_FAILED) {
1349		obj_data = NULL;
1350		p_err("failed to mmap() %s: %s", file, strerror(errno));
1351		goto out;
1352	}
1353	if (obj_name[0] == '\0')
1354		get_obj_name(obj_name, file);
1355
1356	/* The empty object name allows us to use bpf_map__name and produce
1357	 * ELF section names out of it. (".data" instead of "obj.data")
1358	 */
1359	opts.object_name = "";
1360	obj = bpf_object__open_mem(obj_data, file_sz, &opts);
1361	if (!obj) {
1362		char err_buf[256];
1363
1364		libbpf_strerror(errno, err_buf, sizeof(err_buf));
1365		p_err("failed to open BPF object file: %s", err_buf);
1366		obj = NULL;
1367		goto out;
1368	}
1369
1370	btf = bpf_object__btf(obj);
1371	if (!btf) {
1372		err = -1;
1373		p_err("need btf type information for %s", obj_name);
1374		goto out;
1375	}
1376
1377	bpf_object__for_each_program(prog, obj) {
1378		prog_cnt++;
1379	}
1380
1381	/* First, count how many variables we have to find.
1382	 * We need this in advance so the subskel can allocate the right
1383	 * amount of storage.
1384	 */
1385	bpf_object__for_each_map(map, obj) {
1386		if (!get_map_ident(map, ident, sizeof(ident)))
1387			continue;
1388
1389		/* Also count all maps that have a name */
1390		map_cnt++;
1391
1392		if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
1393			continue;
1394
1395		map_type_id = bpf_map__btf_value_type_id(map);
1396		if (map_type_id <= 0) {
1397			err = map_type_id;
1398			goto out;
1399		}
1400		map_type = btf__type_by_id(btf, map_type_id);
1401
1402		var = btf_var_secinfos(map_type);
1403		len = btf_vlen(map_type);
1404		for (i = 0; i < len; i++, var++) {
1405			var_type = btf__type_by_id(btf, var->type);
1406
1407			if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
1408				continue;
1409
1410			var_cnt++;
1411		}
1412	}
1413
1414	get_header_guard(header_guard, obj_name, "SUBSKEL_H");
1415	codegen("\
1416	\n\
1417	/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */	    \n\
1418									    \n\
1419	/* THIS FILE IS AUTOGENERATED! */				    \n\
1420	#ifndef %2$s							    \n\
1421	#define %2$s							    \n\
1422									    \n\
1423	#include <errno.h>						    \n\
1424	#include <stdlib.h>						    \n\
1425	#include <bpf/libbpf.h>						    \n\
1426									    \n\
1427	struct %1$s {							    \n\
1428		struct bpf_object *obj;					    \n\
1429		struct bpf_object_subskeleton *subskel;			    \n\
1430	", obj_name, header_guard);
1431
1432	if (map_cnt) {
1433		printf("\tstruct {\n");
1434		bpf_object__for_each_map(map, obj) {
1435			if (!get_map_ident(map, ident, sizeof(ident)))
1436				continue;
1437			printf("\t\tstruct bpf_map *%s;\n", ident);
1438		}
1439		printf("\t} maps;\n");
1440	}
1441
1442	if (prog_cnt) {
1443		printf("\tstruct {\n");
1444		bpf_object__for_each_program(prog, obj) {
1445			printf("\t\tstruct bpf_program *%s;\n",
1446				bpf_program__name(prog));
1447		}
1448		printf("\t} progs;\n");
1449	}
1450
1451	err = codegen_subskel_datasecs(obj, obj_name);
1452	if (err)
1453		goto out;
1454
1455	/* emit code that will allocate enough storage for all symbols */
1456	codegen("\
1457		\n\
1458									    \n\
1459		#ifdef __cplusplus					    \n\
1460			static inline struct %1$s *open(const struct bpf_object *src);\n\
1461			static inline void destroy(struct %1$s *skel);	    \n\
1462		#endif /* __cplusplus */				    \n\
1463		};							    \n\
1464									    \n\
1465		static inline void					    \n\
1466		%1$s__destroy(struct %1$s *skel)			    \n\
1467		{							    \n\
1468			if (!skel)					    \n\
1469				return;					    \n\
1470			if (skel->subskel)				    \n\
1471				bpf_object__destroy_subskeleton(skel->subskel);\n\
1472			free(skel);					    \n\
1473		}							    \n\
1474									    \n\
1475		static inline struct %1$s *				    \n\
1476		%1$s__open(const struct bpf_object *src)		    \n\
1477		{							    \n\
1478			struct %1$s *obj;				    \n\
1479			struct bpf_object_subskeleton *s;		    \n\
1480			int err;					    \n\
1481									    \n\
1482			obj = (struct %1$s *)calloc(1, sizeof(*obj));	    \n\
1483			if (!obj) {					    \n\
1484				err = -ENOMEM;				    \n\
1485				goto err;				    \n\
1486			}						    \n\
1487			s = (struct bpf_object_subskeleton *)calloc(1, sizeof(*s));\n\
1488			if (!s) {					    \n\
1489				err = -ENOMEM;				    \n\
1490				goto err;				    \n\
1491			}						    \n\
1492			s->sz = sizeof(*s);				    \n\
1493			s->obj = src;					    \n\
1494			s->var_skel_sz = sizeof(*s->vars);		    \n\
1495			obj->subskel = s;				    \n\
1496									    \n\
1497			/* vars */					    \n\
1498			s->var_cnt = %2$d;				    \n\
1499			s->vars = (struct bpf_var_skeleton *)calloc(%2$d, sizeof(*s->vars));\n\
1500			if (!s->vars) {					    \n\
1501				err = -ENOMEM;				    \n\
1502				goto err;				    \n\
1503			}						    \n\
1504		",
1505		obj_name, var_cnt
1506	);
1507
1508	/* walk through each symbol and emit the runtime representation */
1509	bpf_object__for_each_map(map, obj) {
1510		if (!is_internal_mmapable_map(map, ident, sizeof(ident)))
1511			continue;
1512
1513		map_type_id = bpf_map__btf_value_type_id(map);
1514		if (map_type_id <= 0)
1515			/* skip over internal maps with no type*/
1516			continue;
1517
1518		map_type = btf__type_by_id(btf, map_type_id);
1519		var = btf_var_secinfos(map_type);
1520		len = btf_vlen(map_type);
1521		for (i = 0; i < len; i++, var++) {
1522			var_type = btf__type_by_id(btf, var->type);
1523			var_name = btf__name_by_offset(btf, var_type->name_off);
1524
1525			if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
1526				continue;
1527
1528			/* Note that we use the dot prefix in .data as the
1529			 * field access operator i.e. maps%s becomes maps.data
1530			 */
1531			codegen("\
1532			\n\
1533									    \n\
1534				s->vars[%3$d].name = \"%1$s\";		    \n\
1535				s->vars[%3$d].map = &obj->maps.%2$s;	    \n\
1536				s->vars[%3$d].addr = (void **) &obj->%2$s.%1$s;\n\
1537			", var_name, ident, var_idx);
1538
1539			var_idx++;
1540		}
1541	}
1542
1543	codegen_maps_skeleton(obj, map_cnt, false /*mmaped*/);
1544	codegen_progs_skeleton(obj, prog_cnt, false /*links*/);
1545
1546	codegen("\
1547		\n\
1548									    \n\
1549			err = bpf_object__open_subskeleton(s);		    \n\
1550			if (err)					    \n\
1551				goto err;				    \n\
1552									    \n\
1553			return obj;					    \n\
1554		err:							    \n\
1555			%1$s__destroy(obj);				    \n\
1556			errno = -err;					    \n\
1557			return NULL;					    \n\
1558		}							    \n\
1559									    \n\
1560		#ifdef __cplusplus					    \n\
1561		struct %1$s *%1$s::open(const struct bpf_object *src) { return %1$s__open(src); }\n\
1562		void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); }\n\
1563		#endif /* __cplusplus */				    \n\
1564									    \n\
1565		#endif /* %2$s */					    \n\
1566		",
1567		obj_name, header_guard);
1568	err = 0;
1569out:
1570	bpf_object__close(obj);
1571	if (obj_data)
1572		munmap(obj_data, mmap_sz);
1573	close(fd);
1574	return err;
1575}
1576
1577static int do_object(int argc, char **argv)
1578{
1579	struct bpf_linker *linker;
1580	const char *output_file, *file;
1581	int err = 0;
1582
1583	if (!REQ_ARGS(2)) {
1584		usage();
1585		return -1;
1586	}
1587
1588	output_file = GET_ARG();
1589
1590	linker = bpf_linker__new(output_file, NULL);
1591	if (!linker) {
1592		p_err("failed to create BPF linker instance");
1593		return -1;
1594	}
1595
1596	while (argc) {
1597		file = GET_ARG();
1598
1599		err = bpf_linker__add_file(linker, file, NULL);
1600		if (err) {
1601			p_err("failed to link '%s': %s (%d)", file, strerror(errno), errno);
1602			goto out;
1603		}
1604	}
1605
1606	err = bpf_linker__finalize(linker);
1607	if (err) {
1608		p_err("failed to finalize ELF file: %s (%d)", strerror(errno), errno);
1609		goto out;
1610	}
1611
1612	err = 0;
1613out:
1614	bpf_linker__free(linker);
1615	return err;
1616}
1617
1618static int do_help(int argc, char **argv)
1619{
1620	if (json_output) {
1621		jsonw_null(json_wtr);
1622		return 0;
1623	}
1624
1625	fprintf(stderr,
1626		"Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
1627		"       %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
1628		"       %1$s %2$s subskeleton FILE [name OBJECT_NAME]\n"
1629		"       %1$s %2$s min_core_btf INPUT OUTPUT OBJECT [OBJECT...]\n"
1630		"       %1$s %2$s help\n"
1631		"\n"
1632		"       " HELP_SPEC_OPTIONS " |\n"
1633		"                    {-L|--use-loader} }\n"
1634		"",
1635		bin_name, "gen");
1636
1637	return 0;
1638}
1639
1640static int btf_save_raw(const struct btf *btf, const char *path)
1641{
1642	const void *data;
1643	FILE *f = NULL;
1644	__u32 data_sz;
1645	int err = 0;
1646
1647	data = btf__raw_data(btf, &data_sz);
1648	if (!data)
1649		return -ENOMEM;
1650
1651	f = fopen(path, "wb");
1652	if (!f)
1653		return -errno;
1654
1655	if (fwrite(data, 1, data_sz, f) != data_sz)
1656		err = -errno;
1657
1658	fclose(f);
1659	return err;
1660}
1661
1662struct btfgen_info {
1663	struct btf *src_btf;
1664	struct btf *marked_btf; /* btf structure used to mark used types */
1665};
1666
1667static size_t btfgen_hash_fn(long key, void *ctx)
1668{
1669	return key;
1670}
1671
1672static bool btfgen_equal_fn(long k1, long k2, void *ctx)
1673{
1674	return k1 == k2;
1675}
1676
1677static void btfgen_free_info(struct btfgen_info *info)
1678{
1679	if (!info)
1680		return;
1681
1682	btf__free(info->src_btf);
1683	btf__free(info->marked_btf);
1684
1685	free(info);
1686}
1687
1688static struct btfgen_info *
1689btfgen_new_info(const char *targ_btf_path)
1690{
1691	struct btfgen_info *info;
1692	int err;
1693
1694	info = calloc(1, sizeof(*info));
1695	if (!info)
1696		return NULL;
1697
1698	info->src_btf = btf__parse(targ_btf_path, NULL);
1699	if (!info->src_btf) {
1700		err = -errno;
1701		p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
1702		goto err_out;
1703	}
1704
1705	info->marked_btf = btf__parse(targ_btf_path, NULL);
1706	if (!info->marked_btf) {
1707		err = -errno;
1708		p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
1709		goto err_out;
1710	}
1711
1712	return info;
1713
1714err_out:
1715	btfgen_free_info(info);
1716	errno = -err;
1717	return NULL;
1718}
1719
1720#define MARKED UINT32_MAX
1721
1722static void btfgen_mark_member(struct btfgen_info *info, int type_id, int idx)
1723{
1724	const struct btf_type *t = btf__type_by_id(info->marked_btf, type_id);
1725	struct btf_member *m = btf_members(t) + idx;
1726
1727	m->name_off = MARKED;
1728}
1729
1730static int
1731btfgen_mark_type(struct btfgen_info *info, unsigned int type_id, bool follow_pointers)
1732{
1733	const struct btf_type *btf_type = btf__type_by_id(info->src_btf, type_id);
1734	struct btf_type *cloned_type;
1735	struct btf_param *param;
1736	struct btf_array *array;
1737	int err, i;
1738
1739	if (type_id == 0)
1740		return 0;
1741
1742	/* mark type on cloned BTF as used */
1743	cloned_type = (struct btf_type *) btf__type_by_id(info->marked_btf, type_id);
1744	cloned_type->name_off = MARKED;
1745
1746	/* recursively mark other types needed by it */
1747	switch (btf_kind(btf_type)) {
1748	case BTF_KIND_UNKN:
1749	case BTF_KIND_INT:
1750	case BTF_KIND_FLOAT:
1751	case BTF_KIND_ENUM:
1752	case BTF_KIND_ENUM64:
1753	case BTF_KIND_STRUCT:
1754	case BTF_KIND_UNION:
1755		break;
1756	case BTF_KIND_PTR:
1757		if (follow_pointers) {
1758			err = btfgen_mark_type(info, btf_type->type, follow_pointers);
1759			if (err)
1760				return err;
1761		}
1762		break;
1763	case BTF_KIND_CONST:
1764	case BTF_KIND_RESTRICT:
1765	case BTF_KIND_VOLATILE:
1766	case BTF_KIND_TYPEDEF:
1767		err = btfgen_mark_type(info, btf_type->type, follow_pointers);
1768		if (err)
1769			return err;
1770		break;
1771	case BTF_KIND_ARRAY:
1772		array = btf_array(btf_type);
1773
1774		/* mark array type */
1775		err = btfgen_mark_type(info, array->type, follow_pointers);
1776		/* mark array's index type */
1777		err = err ? : btfgen_mark_type(info, array->index_type, follow_pointers);
1778		if (err)
1779			return err;
1780		break;
1781	case BTF_KIND_FUNC_PROTO:
1782		/* mark ret type */
1783		err = btfgen_mark_type(info, btf_type->type, follow_pointers);
1784		if (err)
1785			return err;
1786
1787		/* mark parameters types */
1788		param = btf_params(btf_type);
1789		for (i = 0; i < btf_vlen(btf_type); i++) {
1790			err = btfgen_mark_type(info, param->type, follow_pointers);
1791			if (err)
1792				return err;
1793			param++;
1794		}
1795		break;
1796	/* tells if some other type needs to be handled */
1797	default:
1798		p_err("unsupported kind: %s (%d)", btf_kind_str(btf_type), type_id);
1799		return -EINVAL;
1800	}
1801
1802	return 0;
1803}
1804
1805static int btfgen_record_field_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
1806{
1807	struct btf *btf = info->src_btf;
1808	const struct btf_type *btf_type;
1809	struct btf_member *btf_member;
1810	struct btf_array *array;
1811	unsigned int type_id = targ_spec->root_type_id;
1812	int idx, err;
1813
1814	/* mark root type */
1815	btf_type = btf__type_by_id(btf, type_id);
1816	err = btfgen_mark_type(info, type_id, false);
1817	if (err)
1818		return err;
1819
1820	/* mark types for complex types (arrays, unions, structures) */
1821	for (int i = 1; i < targ_spec->raw_len; i++) {
1822		/* skip typedefs and mods */
1823		while (btf_is_mod(btf_type) || btf_is_typedef(btf_type)) {
1824			type_id = btf_type->type;
1825			btf_type = btf__type_by_id(btf, type_id);
1826		}
1827
1828		switch (btf_kind(btf_type)) {
1829		case BTF_KIND_STRUCT:
1830		case BTF_KIND_UNION:
1831			idx = targ_spec->raw_spec[i];
1832			btf_member = btf_members(btf_type) + idx;
1833
1834			/* mark member */
1835			btfgen_mark_member(info, type_id, idx);
1836
1837			/* mark member's type */
1838			type_id = btf_member->type;
1839			btf_type = btf__type_by_id(btf, type_id);
1840			err = btfgen_mark_type(info, type_id, false);
1841			if (err)
1842				return err;
1843			break;
1844		case BTF_KIND_ARRAY:
1845			array = btf_array(btf_type);
1846			type_id = array->type;
1847			btf_type = btf__type_by_id(btf, type_id);
1848			break;
1849		default:
1850			p_err("unsupported kind: %s (%d)",
1851			      btf_kind_str(btf_type), btf_type->type);
1852			return -EINVAL;
1853		}
1854	}
1855
1856	return 0;
1857}
1858
1859/* Mark types, members, and member types. Compared to btfgen_record_field_relo,
1860 * this function does not rely on the target spec for inferring members, but
1861 * uses the associated BTF.
1862 *
1863 * The `behind_ptr` argument is used to stop marking of composite types reached
1864 * through a pointer. This way, we can keep BTF size in check while providing
1865 * reasonable match semantics.
1866 */
1867static int btfgen_mark_type_match(struct btfgen_info *info, __u32 type_id, bool behind_ptr)
1868{
1869	const struct btf_type *btf_type;
1870	struct btf *btf = info->src_btf;
1871	struct btf_type *cloned_type;
1872	int i, err;
1873
1874	if (type_id == 0)
1875		return 0;
1876
1877	btf_type = btf__type_by_id(btf, type_id);
1878	/* mark type on cloned BTF as used */
1879	cloned_type = (struct btf_type *)btf__type_by_id(info->marked_btf, type_id);
1880	cloned_type->name_off = MARKED;
1881
1882	switch (btf_kind(btf_type)) {
1883	case BTF_KIND_UNKN:
1884	case BTF_KIND_INT:
1885	case BTF_KIND_FLOAT:
1886	case BTF_KIND_ENUM:
1887	case BTF_KIND_ENUM64:
1888		break;
1889	case BTF_KIND_STRUCT:
1890	case BTF_KIND_UNION: {
1891		struct btf_member *m = btf_members(btf_type);
1892		__u16 vlen = btf_vlen(btf_type);
1893
1894		if (behind_ptr)
1895			break;
1896
1897		for (i = 0; i < vlen; i++, m++) {
1898			/* mark member */
1899			btfgen_mark_member(info, type_id, i);
1900
1901			/* mark member's type */
1902			err = btfgen_mark_type_match(info, m->type, false);
1903			if (err)
1904				return err;
1905		}
1906		break;
1907	}
1908	case BTF_KIND_CONST:
1909	case BTF_KIND_FWD:
1910	case BTF_KIND_RESTRICT:
1911	case BTF_KIND_TYPEDEF:
1912	case BTF_KIND_VOLATILE:
1913		return btfgen_mark_type_match(info, btf_type->type, behind_ptr);
1914	case BTF_KIND_PTR:
1915		return btfgen_mark_type_match(info, btf_type->type, true);
1916	case BTF_KIND_ARRAY: {
1917		struct btf_array *array;
1918
1919		array = btf_array(btf_type);
1920		/* mark array type */
1921		err = btfgen_mark_type_match(info, array->type, false);
1922		/* mark array's index type */
1923		err = err ? : btfgen_mark_type_match(info, array->index_type, false);
1924		if (err)
1925			return err;
1926		break;
1927	}
1928	case BTF_KIND_FUNC_PROTO: {
1929		__u16 vlen = btf_vlen(btf_type);
1930		struct btf_param *param;
1931
1932		/* mark ret type */
1933		err = btfgen_mark_type_match(info, btf_type->type, false);
1934		if (err)
1935			return err;
1936
1937		/* mark parameters types */
1938		param = btf_params(btf_type);
1939		for (i = 0; i < vlen; i++) {
1940			err = btfgen_mark_type_match(info, param->type, false);
1941			if (err)
1942				return err;
1943			param++;
1944		}
1945		break;
1946	}
1947	/* tells if some other type needs to be handled */
1948	default:
1949		p_err("unsupported kind: %s (%d)", btf_kind_str(btf_type), type_id);
1950		return -EINVAL;
1951	}
1952
1953	return 0;
1954}
1955
1956/* Mark types, members, and member types. Compared to btfgen_record_field_relo,
1957 * this function does not rely on the target spec for inferring members, but
1958 * uses the associated BTF.
1959 */
1960static int btfgen_record_type_match_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
1961{
1962	return btfgen_mark_type_match(info, targ_spec->root_type_id, false);
1963}
1964
1965static int btfgen_record_type_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
1966{
1967	return btfgen_mark_type(info, targ_spec->root_type_id, true);
1968}
1969
1970static int btfgen_record_enumval_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
1971{
1972	return btfgen_mark_type(info, targ_spec->root_type_id, false);
1973}
1974
1975static int btfgen_record_reloc(struct btfgen_info *info, struct bpf_core_spec *res)
1976{
1977	switch (res->relo_kind) {
1978	case BPF_CORE_FIELD_BYTE_OFFSET:
1979	case BPF_CORE_FIELD_BYTE_SIZE:
1980	case BPF_CORE_FIELD_EXISTS:
1981	case BPF_CORE_FIELD_SIGNED:
1982	case BPF_CORE_FIELD_LSHIFT_U64:
1983	case BPF_CORE_FIELD_RSHIFT_U64:
1984		return btfgen_record_field_relo(info, res);
1985	case BPF_CORE_TYPE_ID_LOCAL: /* BPF_CORE_TYPE_ID_LOCAL doesn't require kernel BTF */
1986		return 0;
1987	case BPF_CORE_TYPE_ID_TARGET:
1988	case BPF_CORE_TYPE_EXISTS:
1989	case BPF_CORE_TYPE_SIZE:
1990		return btfgen_record_type_relo(info, res);
1991	case BPF_CORE_TYPE_MATCHES:
1992		return btfgen_record_type_match_relo(info, res);
1993	case BPF_CORE_ENUMVAL_EXISTS:
1994	case BPF_CORE_ENUMVAL_VALUE:
1995		return btfgen_record_enumval_relo(info, res);
1996	default:
1997		return -EINVAL;
1998	}
1999}
2000
2001static struct bpf_core_cand_list *
2002btfgen_find_cands(const struct btf *local_btf, const struct btf *targ_btf, __u32 local_id)
2003{
2004	const struct btf_type *local_type;
2005	struct bpf_core_cand_list *cands = NULL;
2006	struct bpf_core_cand local_cand = {};
2007	size_t local_essent_len;
2008	const char *local_name;
2009	int err;
2010
2011	local_cand.btf = local_btf;
2012	local_cand.id = local_id;
2013
2014	local_type = btf__type_by_id(local_btf, local_id);
2015	if (!local_type) {
2016		err = -EINVAL;
2017		goto err_out;
2018	}
2019
2020	local_name = btf__name_by_offset(local_btf, local_type->name_off);
2021	if (!local_name) {
2022		err = -EINVAL;
2023		goto err_out;
2024	}
2025	local_essent_len = bpf_core_essential_name_len(local_name);
2026
2027	cands = calloc(1, sizeof(*cands));
2028	if (!cands)
2029		return NULL;
2030
2031	err = bpf_core_add_cands(&local_cand, local_essent_len, targ_btf, "vmlinux", 1, cands);
2032	if (err)
2033		goto err_out;
2034
2035	return cands;
2036
2037err_out:
2038	bpf_core_free_cands(cands);
2039	errno = -err;
2040	return NULL;
2041}
2042
2043/* Record relocation information for a single BPF object */
2044static int btfgen_record_obj(struct btfgen_info *info, const char *obj_path)
2045{
2046	const struct btf_ext_info_sec *sec;
2047	const struct bpf_core_relo *relo;
2048	const struct btf_ext_info *seg;
2049	struct hashmap_entry *entry;
2050	struct hashmap *cand_cache = NULL;
2051	struct btf_ext *btf_ext = NULL;
2052	unsigned int relo_idx;
2053	struct btf *btf = NULL;
2054	size_t i;
2055	int err;
2056
2057	btf = btf__parse(obj_path, &btf_ext);
2058	if (!btf) {
2059		err = -errno;
2060		p_err("failed to parse BPF object '%s': %s", obj_path, strerror(errno));
2061		return err;
2062	}
2063
2064	if (!btf_ext) {
2065		p_err("failed to parse BPF object '%s': section %s not found",
2066		      obj_path, BTF_EXT_ELF_SEC);
2067		err = -EINVAL;
2068		goto out;
2069	}
2070
2071	if (btf_ext->core_relo_info.len == 0) {
2072		err = 0;
2073		goto out;
2074	}
2075
2076	cand_cache = hashmap__new(btfgen_hash_fn, btfgen_equal_fn, NULL);
2077	if (IS_ERR(cand_cache)) {
2078		err = PTR_ERR(cand_cache);
2079		goto out;
2080	}
2081
2082	seg = &btf_ext->core_relo_info;
2083	for_each_btf_ext_sec(seg, sec) {
2084		for_each_btf_ext_rec(seg, sec, relo_idx, relo) {
2085			struct bpf_core_spec specs_scratch[3] = {};
2086			struct bpf_core_relo_res targ_res = {};
2087			struct bpf_core_cand_list *cands = NULL;
2088			const char *sec_name = btf__name_by_offset(btf, sec->sec_name_off);
2089
2090			if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
2091			    !hashmap__find(cand_cache, relo->type_id, &cands)) {
2092				cands = btfgen_find_cands(btf, info->src_btf, relo->type_id);
2093				if (!cands) {
2094					err = -errno;
2095					goto out;
2096				}
2097
2098				err = hashmap__set(cand_cache, relo->type_id, cands,
2099						   NULL, NULL);
2100				if (err)
2101					goto out;
2102			}
2103
2104			err = bpf_core_calc_relo_insn(sec_name, relo, relo_idx, btf, cands,
2105						      specs_scratch, &targ_res);
2106			if (err)
2107				goto out;
2108
2109			/* specs_scratch[2] is the target spec */
2110			err = btfgen_record_reloc(info, &specs_scratch[2]);
2111			if (err)
2112				goto out;
2113		}
2114	}
2115
2116out:
2117	btf__free(btf);
2118	btf_ext__free(btf_ext);
2119
2120	if (!IS_ERR_OR_NULL(cand_cache)) {
2121		hashmap__for_each_entry(cand_cache, entry, i) {
2122			bpf_core_free_cands(entry->pvalue);
2123		}
2124		hashmap__free(cand_cache);
2125	}
2126
2127	return err;
2128}
2129
2130static int btfgen_remap_id(__u32 *type_id, void *ctx)
2131{
2132	unsigned int *ids = ctx;
2133
2134	*type_id = ids[*type_id];
2135
2136	return 0;
2137}
2138
2139/* Generate BTF from relocation information previously recorded */
2140static struct btf *btfgen_get_btf(struct btfgen_info *info)
2141{
2142	struct btf *btf_new = NULL;
2143	unsigned int *ids = NULL;
2144	unsigned int i, n = btf__type_cnt(info->marked_btf);
2145	int err = 0;
2146
2147	btf_new = btf__new_empty();
2148	if (!btf_new) {
2149		err = -errno;
2150		goto err_out;
2151	}
2152
2153	ids = calloc(n, sizeof(*ids));
2154	if (!ids) {
2155		err = -errno;
2156		goto err_out;
2157	}
2158
2159	/* first pass: add all marked types to btf_new and add their new ids to the ids map */
2160	for (i = 1; i < n; i++) {
2161		const struct btf_type *cloned_type, *type;
2162		const char *name;
2163		int new_id;
2164
2165		cloned_type = btf__type_by_id(info->marked_btf, i);
2166
2167		if (cloned_type->name_off != MARKED)
2168			continue;
2169
2170		type = btf__type_by_id(info->src_btf, i);
2171
2172		/* add members for struct and union */
2173		if (btf_is_composite(type)) {
2174			struct btf_member *cloned_m, *m;
2175			unsigned short vlen;
2176			int idx_src;
2177
2178			name = btf__str_by_offset(info->src_btf, type->name_off);
2179
2180			if (btf_is_struct(type))
2181				err = btf__add_struct(btf_new, name, type->size);
2182			else
2183				err = btf__add_union(btf_new, name, type->size);
2184
2185			if (err < 0)
2186				goto err_out;
2187			new_id = err;
2188
2189			cloned_m = btf_members(cloned_type);
2190			m = btf_members(type);
2191			vlen = btf_vlen(cloned_type);
2192			for (idx_src = 0; idx_src < vlen; idx_src++, cloned_m++, m++) {
2193				/* add only members that are marked as used */
2194				if (cloned_m->name_off != MARKED)
2195					continue;
2196
2197				name = btf__str_by_offset(info->src_btf, m->name_off);
2198				err = btf__add_field(btf_new, name, m->type,
2199						     btf_member_bit_offset(cloned_type, idx_src),
2200						     btf_member_bitfield_size(cloned_type, idx_src));
2201				if (err < 0)
2202					goto err_out;
2203			}
2204		} else {
2205			err = btf__add_type(btf_new, info->src_btf, type);
2206			if (err < 0)
2207				goto err_out;
2208			new_id = err;
2209		}
2210
2211		/* add ID mapping */
2212		ids[i] = new_id;
2213	}
2214
2215	/* second pass: fix up type ids */
2216	for (i = 1; i < btf__type_cnt(btf_new); i++) {
2217		struct btf_type *btf_type = (struct btf_type *) btf__type_by_id(btf_new, i);
2218
2219		err = btf_type_visit_type_ids(btf_type, btfgen_remap_id, ids);
2220		if (err)
2221			goto err_out;
2222	}
2223
2224	free(ids);
2225	return btf_new;
2226
2227err_out:
2228	btf__free(btf_new);
2229	free(ids);
2230	errno = -err;
2231	return NULL;
2232}
2233
2234/* Create minimized BTF file for a set of BPF objects.
2235 *
2236 * The BTFGen algorithm is divided in two main parts: (1) collect the
2237 * BTF types that are involved in relocations and (2) generate the BTF
2238 * object using the collected types.
2239 *
2240 * In order to collect the types involved in the relocations, we parse
2241 * the BTF and BTF.ext sections of the BPF objects and use
2242 * bpf_core_calc_relo_insn() to get the target specification, this
2243 * indicates how the types and fields are used in a relocation.
2244 *
2245 * Types are recorded in different ways according to the kind of the
2246 * relocation. For field-based relocations only the members that are
2247 * actually used are saved in order to reduce the size of the generated
2248 * BTF file. For type-based relocations empty struct / unions are
2249 * generated and for enum-based relocations the whole type is saved.
2250 *
2251 * The second part of the algorithm generates the BTF object. It creates
2252 * an empty BTF object and fills it with the types recorded in the
2253 * previous step. This function takes care of only adding the structure
2254 * and union members that were marked as used and it also fixes up the
2255 * type IDs on the generated BTF object.
2256 */
2257static int minimize_btf(const char *src_btf, const char *dst_btf, const char *objspaths[])
2258{
2259	struct btfgen_info *info;
2260	struct btf *btf_new = NULL;
2261	int err, i;
2262
2263	info = btfgen_new_info(src_btf);
2264	if (!info) {
2265		err = -errno;
2266		p_err("failed to allocate info structure: %s", strerror(errno));
2267		goto out;
2268	}
2269
2270	for (i = 0; objspaths[i] != NULL; i++) {
2271		err = btfgen_record_obj(info, objspaths[i]);
2272		if (err) {
2273			p_err("error recording relocations for %s: %s", objspaths[i],
2274			      strerror(errno));
2275			goto out;
2276		}
2277	}
2278
2279	btf_new = btfgen_get_btf(info);
2280	if (!btf_new) {
2281		err = -errno;
2282		p_err("error generating BTF: %s", strerror(errno));
2283		goto out;
2284	}
2285
2286	err = btf_save_raw(btf_new, dst_btf);
2287	if (err) {
2288		p_err("error saving btf file: %s", strerror(errno));
2289		goto out;
2290	}
2291
2292out:
2293	btf__free(btf_new);
2294	btfgen_free_info(info);
2295
2296	return err;
2297}
2298
2299static int do_min_core_btf(int argc, char **argv)
2300{
2301	const char *input, *output, **objs;
2302	int i, err;
2303
2304	if (!REQ_ARGS(3)) {
2305		usage();
2306		return -1;
2307	}
2308
2309	input = GET_ARG();
2310	output = GET_ARG();
2311
2312	objs = (const char **) calloc(argc + 1, sizeof(*objs));
2313	if (!objs) {
2314		p_err("failed to allocate array for object names");
2315		return -ENOMEM;
2316	}
2317
2318	i = 0;
2319	while (argc)
2320		objs[i++] = GET_ARG();
2321
2322	err = minimize_btf(input, output, objs);
2323	free(objs);
2324	return err;
2325}
2326
2327static const struct cmd cmds[] = {
2328	{ "object",		do_object },
2329	{ "skeleton",		do_skeleton },
2330	{ "subskeleton",	do_subskeleton },
2331	{ "min_core_btf",	do_min_core_btf},
2332	{ "help",		do_help },
2333	{ 0 }
2334};
2335
2336int do_gen(int argc, char **argv)
2337{
2338	return cmd_select(cmds, argc, argv, do_help);
2339}