Linux Audio

Check our new training course

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