File Index
Files and directories
Sign in
FILE

gen.c

File preview with syntax highlighting.

linux-6.19.14/tools/bpf/bpftool/gen.c C
   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$zu);\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_load_and_run_opts sopts = {};
 692	char sig_buf[MAX_SIG_SIZE];
 693	__u8 prog_sha[SHA256_DIGEST_LENGTH];
 694	struct bpf_map *map;
 695
 696	char ident[256];
 697	int err = 0;
 698
 699	if (sign_progs)
 700		opts.gen_hash = true;
 701
 702	err = bpf_object__gen_loader(obj, &opts);
 703	if (err)
 704		return err;
 705
 706	err = bpf_object__load(obj);
 707	if (err) {
 708		p_err("failed to load object file");
 709		goto out;
 710	}
 711
 712	/* If there was no error during load then gen_loader_opts
 713	 * are populated with the loader program.
 714	 */
 715
 716	/* finish generating 'struct skel' */
 717	codegen("\
 718		\n\
 719		};							    \n\
 720		", obj_name);
 721
 722
 723	codegen_attach_detach(obj, obj_name);
 724
 725	codegen_destroy(obj, obj_name);
 726
 727	codegen("\
 728		\n\
 729		static inline struct %1$s *				    \n\
 730		%1$s__open(void)					    \n\
 731		{							    \n\
 732			struct %1$s *skel;				    \n\
 733									    \n\
 734			skel = skel_alloc(sizeof(*skel));		    \n\
 735			if (!skel)					    \n\
 736				goto cleanup;				    \n\
 737			skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\
 738		",
 739		obj_name, opts.data_sz);
 740	bpf_object__for_each_map(map, obj) {
 741		const void *mmap_data = NULL;
 742		size_t mmap_size = 0;
 743
 744		if (!is_mmapable_map(map, ident, sizeof(ident)))
 745			continue;
 746
 747		codegen("\
 748		\n\
 749			{						    \n\
 750				static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
 751		");
 752		mmap_data = bpf_map__initial_value(map, &mmap_size);
 753		print_hex(mmap_data, mmap_size);
 754		codegen("\
 755		\n\
 756		\";							    \n\
 757									    \n\
 758				skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\
 759								sizeof(data) - 1);\n\
 760				if (!skel->%1$s)			    \n\
 761					goto cleanup;			    \n\
 762				skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\
 763			}						    \n\
 764			", ident, bpf_map_mmap_sz(map));
 765	}
 766	codegen("\
 767		\n\
 768			return skel;					    \n\
 769		cleanup:						    \n\
 770			%1$s__destroy(skel);				    \n\
 771			return NULL;					    \n\
 772		}							    \n\
 773									    \n\
 774		static inline int					    \n\
 775		%1$s__load(struct %1$s *skel)				    \n\
 776		{							    \n\
 777			struct bpf_load_and_run_opts opts = {};		    \n\
 778			int err;					    \n\
 779			static const char opts_data[] __attribute__((__aligned__(8))) = \"\\\n\
 780		",
 781		obj_name);
 782	print_hex(opts.data, opts.data_sz);
 783	codegen("\
 784		\n\
 785		\";							    \n\
 786			static const char opts_insn[] __attribute__((__aligned__(8))) = \"\\\n\
 787		");
 788	print_hex(opts.insns, opts.insns_sz);
 789	codegen("\
 790		\n\
 791		\";\n");
 792
 793	if (sign_progs) {
 794		sopts.insns = opts.insns;
 795		sopts.insns_sz = opts.insns_sz;
 796		sopts.excl_prog_hash = prog_sha;
 797		sopts.excl_prog_hash_sz = sizeof(prog_sha);
 798		sopts.signature = sig_buf;
 799		sopts.signature_sz = MAX_SIG_SIZE;
 800
 801		err = bpftool_prog_sign(&sopts);
 802		if (err < 0) {
 803			p_err("failed to sign program");
 804			goto out;
 805		}
 806
 807		codegen("\
 808		\n\
 809			static const char opts_sig[] __attribute__((__aligned__(8))) = \"\\\n\
 810		");
 811		print_hex((const void *)sig_buf, sopts.signature_sz);
 812		codegen("\
 813		\n\
 814		\";\n");
 815
 816		codegen("\
 817		\n\
 818			static const char opts_excl_hash[] __attribute__((__aligned__(8))) = \"\\\n\
 819		");
 820		print_hex((const void *)prog_sha, sizeof(prog_sha));
 821		codegen("\
 822		\n\
 823		\";\n");
 824
 825		codegen("\
 826		\n\
 827			opts.signature = (void *)opts_sig;			\n\
 828			opts.signature_sz = sizeof(opts_sig) - 1;		\n\
 829			opts.excl_prog_hash = (void *)opts_excl_hash;		\n\
 830			opts.excl_prog_hash_sz = sizeof(opts_excl_hash) - 1;	\n\
 831			opts.keyring_id = skel->keyring_id;			\n\
 832		");
 833	}
 834
 835	codegen("\
 836		\n\
 837			opts.ctx = (struct bpf_loader_ctx *)skel;	    \n\
 838			opts.data_sz = sizeof(opts_data) - 1;		    \n\
 839			opts.data = (void *)opts_data;			    \n\
 840			opts.insns_sz = sizeof(opts_insn) - 1;		    \n\
 841			opts.insns = (void *)opts_insn;			    \n\
 842									    \n\
 843			err = bpf_load_and_run(&opts);			    \n\
 844			if (err < 0)					    \n\
 845				return err;				    \n\
 846		");
 847	bpf_object__for_each_map(map, obj) {
 848		const char *mmap_flags;
 849
 850		if (!is_mmapable_map(map, ident, sizeof(ident)))
 851			continue;
 852
 853		if (bpf_map__map_flags(map) & BPF_F_RDONLY_PROG)
 854			mmap_flags = "PROT_READ";
 855		else
 856			mmap_flags = "PROT_READ | PROT_WRITE";
 857
 858		codegen("\
 859		\n\
 860			skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value,  \n\
 861							%2$zd, %3$s, skel->maps.%1$s.map_fd);\n\
 862			if (!skel->%1$s)				    \n\
 863				return -ENOMEM;				    \n\
 864			",
 865		       ident, bpf_map_mmap_sz(map), mmap_flags);
 866	}
 867	codegen("\
 868		\n\
 869			return 0;					    \n\
 870		}							    \n\
 871									    \n\
 872		static inline struct %1$s *				    \n\
 873		%1$s__open_and_load(void)				    \n\
 874		{							    \n\
 875			struct %1$s *skel;				    \n\
 876									    \n\
 877			skel = %1$s__open();				    \n\
 878			if (!skel)					    \n\
 879				return NULL;				    \n\
 880			if (%1$s__load(skel)) {				    \n\
 881				%1$s__destroy(skel);			    \n\
 882				return NULL;				    \n\
 883			}						    \n\
 884			return skel;					    \n\
 885		}							    \n\
 886									    \n\
 887		", obj_name);
 888
 889	codegen_asserts(obj, obj_name);
 890
 891	codegen("\
 892		\n\
 893									    \n\
 894		#endif /* %s */						    \n\
 895		",
 896		header_guard);
 897	err = 0;
 898out:
 899	return err;
 900}
 901
 902static void
 903codegen_maps_skeleton(struct bpf_object *obj, size_t map_cnt, bool mmaped, bool populate_links)
 904{
 905	struct bpf_map *map;
 906	char ident[256];
 907	size_t i, map_sz;
 908
 909	if (!map_cnt)
 910		return;
 911
 912	/* for backward compatibility with old libbpf versions that don't
 913	 * handle new BPF skeleton with new struct bpf_map_skeleton definition
 914	 * that includes link field, avoid specifying new increased size,
 915	 * unless we absolutely have to (i.e., if there are struct_ops maps
 916	 * present)
 917	 */
 918	map_sz = offsetof(struct bpf_map_skeleton, link);
 919	if (populate_links) {
 920		bpf_object__for_each_map(map, obj) {
 921			if (bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS) {
 922				map_sz = sizeof(struct bpf_map_skeleton);
 923				break;
 924			}
 925		}
 926	}
 927
 928	codegen("\
 929		\n\
 930								    \n\
 931			/* maps */				    \n\
 932			s->map_cnt = %zu;			    \n\
 933			s->map_skel_sz = %zu;			    \n\
 934			s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt,\n\
 935					sizeof(*s->maps) > %zu ? sizeof(*s->maps) : %zu);\n\
 936			if (!s->maps) {				    \n\
 937				err = -ENOMEM;			    \n\
 938				goto err;			    \n\
 939			}					    \n\
 940		",
 941		map_cnt, map_sz, map_sz, map_sz
 942	);
 943	i = 0;
 944	bpf_object__for_each_map(map, obj) {
 945		if (!get_map_ident(map, ident, sizeof(ident)))
 946			continue;
 947
 948		codegen("\
 949			\n\
 950								    \n\
 951				map = (struct bpf_map_skeleton *)((char *)s->maps + %zu * s->map_skel_sz);\n\
 952				map->name = \"%s\";		    \n\
 953				map->map = &obj->maps.%s;	    \n\
 954			",
 955			i, bpf_map__name(map), ident);
 956		/* memory-mapped internal maps */
 957		if (mmaped && is_mmapable_map(map, ident, sizeof(ident))) {
 958			printf("\tmap->mmaped = (void **)&obj->%s;\n", ident);
 959		}
 960
 961		if (populate_links && bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS) {
 962			codegen("\
 963				\n\
 964					map->link = &obj->links.%s; \n\
 965				", ident);
 966		}
 967		i++;
 968	}
 969}
 970
 971static void
 972codegen_progs_skeleton(struct bpf_object *obj, size_t prog_cnt, bool populate_links)
 973{
 974	struct bpf_program *prog;
 975	int i;
 976
 977	if (!prog_cnt)
 978		return;
 979
 980	codegen("\
 981		\n\
 982									\n\
 983			/* programs */				    \n\
 984			s->prog_cnt = %zu;			    \n\
 985			s->prog_skel_sz = sizeof(*s->progs);	    \n\
 986			s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);\n\
 987			if (!s->progs) {			    \n\
 988				err = -ENOMEM;			    \n\
 989				goto err;			    \n\
 990			}					    \n\
 991		",
 992		prog_cnt
 993	);
 994	i = 0;
 995	bpf_object__for_each_program(prog, obj) {
 996		codegen("\
 997			\n\
 998									\n\
 999				s->progs[%1$zu].name = \"%2$s\";    \n\
1000				s->progs[%1$zu].prog = &obj->progs.%2$s;\n\
1001			",
1002			i, bpf_program__name(prog));
1003
1004		if (populate_links) {
1005			codegen("\
1006				\n\
1007					s->progs[%1$zu].link = &obj->links.%2$s;\n\
1008				",
1009				i, bpf_program__name(prog));
1010		}
1011		i++;
1012	}
1013}
1014
1015static int walk_st_ops_shadow_vars(struct btf *btf, const char *ident,
1016				   const struct btf_type *map_type, __u32 map_type_id)
1017{
1018	LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts, .indent_level = 3);
1019	const struct btf_type *member_type;
1020	__u32 offset, next_offset = 0;
1021	const struct btf_member *m;
1022	struct btf_dump *d = NULL;
1023	const char *member_name;
1024	__u32 member_type_id;
1025	int i, err = 0, n;
1026	int size;
1027
1028	d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
1029	if (!d)
1030		return -errno;
1031
1032	n = btf_vlen(map_type);
1033	for (i = 0, m = btf_members(map_type); i < n; i++, m++) {
1034		member_type = skip_mods_and_typedefs(btf, m->type, &member_type_id);
1035		member_name = btf__name_by_offset(btf, m->name_off);
1036
1037		offset = m->offset / 8;
1038		if (next_offset < offset)
1039			printf("\t\t\tchar __padding_%d[%u];\n", i, offset - next_offset);
1040
1041		switch (btf_kind(member_type)) {
1042		case BTF_KIND_INT:
1043		case BTF_KIND_FLOAT:
1044		case BTF_KIND_ENUM:
1045		case BTF_KIND_ENUM64:
1046			/* scalar type */
1047			printf("\t\t\t");
1048			opts.field_name = member_name;
1049			err = btf_dump__emit_type_decl(d, member_type_id, &opts);
1050			if (err) {
1051				p_err("Failed to emit type declaration for %s: %d", member_name, err);
1052				goto out;
1053			}
1054			printf(";\n");
1055
1056			size = btf__resolve_size(btf, member_type_id);
1057			if (size < 0) {
1058				p_err("Failed to resolve size of %s: %d\n", member_name, size);
1059				err = size;
1060				goto out;
1061			}
1062
1063			next_offset = offset + size;
1064			break;
1065
1066		case BTF_KIND_PTR:
1067			if (resolve_func_ptr(btf, m->type, NULL)) {
1068				/* Function pointer */
1069				printf("\t\t\tstruct bpf_program *%s;\n", member_name);
1070
1071				next_offset = offset + sizeof(void *);
1072				break;
1073			}
1074			/* All pointer types are unsupported except for
1075			 * function pointers.
1076			 */
1077			fallthrough;
1078
1079		default:
1080			/* Unsupported types
1081			 *
1082			 * Types other than scalar types and function
1083			 * pointers are currently not supported in order to
1084			 * prevent conflicts in the generated code caused
1085			 * by multiple definitions. For instance, if the
1086			 * struct type FOO is used in a struct_ops map,
1087			 * bpftool has to generate definitions for FOO,
1088			 * which may result in conflicts if FOO is defined
1089			 * in different skeleton files.
1090			 */
1091			size = btf__resolve_size(btf, member_type_id);
1092			if (size < 0) {
1093				p_err("Failed to resolve size of %s: %d\n", member_name, size);
1094				err = size;
1095				goto out;
1096			}
1097			printf("\t\t\tchar __unsupported_%d[%d];\n", i, size);
1098
1099			next_offset = offset + size;
1100			break;
1101		}
1102	}
1103
1104	/* Cannot fail since it must be a struct type */
1105	size = btf__resolve_size(btf, map_type_id);
1106	if (next_offset < (__u32)size)
1107		printf("\t\t\tchar __padding_end[%u];\n", size - next_offset);
1108
1109out:
1110	btf_dump__free(d);
1111
1112	return err;
1113}
1114
1115/* Generate the pointer of the shadow type for a struct_ops map.
1116 *
1117 * This function adds a pointer of the shadow type for a struct_ops map.
1118 * The members of a struct_ops map can be exported through a pointer to a
1119 * shadow type. The user can access these members through the pointer.
1120 *
1121 * A shadow type includes not all members, only members of some types.
1122 * They are scalar types and function pointers. The function pointers are
1123 * translated to the pointer of the struct bpf_program. The scalar types
1124 * are translated to the original type without any modifiers.
1125 *
1126 * Unsupported types will be translated to a char array to occupy the same
1127 * space as the original field, being renamed as __unsupported_*.  The user
1128 * should treat these fields as opaque data.
1129 */
1130static int gen_st_ops_shadow_type(const char *obj_name, struct btf *btf, const char *ident,
1131				  const struct bpf_map *map)
1132{
1133	const struct btf_type *map_type;
1134	const char *type_name;
1135	__u32 map_type_id;
1136	int err;
1137
1138	map_type_id = bpf_map__btf_value_type_id(map);
1139	if (map_type_id == 0)
1140		return -EINVAL;
1141	map_type = btf__type_by_id(btf, map_type_id);
1142	if (!map_type)
1143		return -EINVAL;
1144
1145	type_name = btf__name_by_offset(btf, map_type->name_off);
1146
1147	printf("\t\tstruct %s__%s__%s {\n", obj_name, ident, type_name);
1148
1149	err = walk_st_ops_shadow_vars(btf, ident, map_type, map_type_id);
1150	if (err)
1151		return err;
1152
1153	printf("\t\t} *%s;\n", ident);
1154
1155	return 0;
1156}
1157
1158static int gen_st_ops_shadow(const char *obj_name, struct btf *btf, struct bpf_object *obj)
1159{
1160	int err, st_ops_cnt = 0;
1161	struct bpf_map *map;
1162	char ident[256];
1163
1164	if (!btf)
1165		return 0;
1166
1167	/* Generate the pointers to shadow types of
1168	 * struct_ops maps.
1169	 */
1170	bpf_object__for_each_map(map, obj) {
1171		if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
1172			continue;
1173		if (!get_map_ident(map, ident, sizeof(ident)))
1174			continue;
1175
1176		if (st_ops_cnt == 0) /* first struct_ops map */
1177			printf("\tstruct {\n");
1178		st_ops_cnt++;
1179
1180		err = gen_st_ops_shadow_type(obj_name, btf, ident, map);
1181		if (err)
1182			return err;
1183	}
1184
1185	if (st_ops_cnt)
1186		printf("\t} struct_ops;\n");
1187
1188	return 0;
1189}
1190
1191/* Generate the code to initialize the pointers of shadow types. */
1192static void gen_st_ops_shadow_init(struct btf *btf, struct bpf_object *obj)
1193{
1194	struct bpf_map *map;
1195	char ident[256];
1196
1197	if (!btf)
1198		return;
1199
1200	/* Initialize the pointers to_ops shadow types of
1201	 * struct_ops maps.
1202	 */
1203	bpf_object__for_each_map(map, obj) {
1204		if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
1205			continue;
1206		if (!get_map_ident(map, ident, sizeof(ident)))
1207			continue;
1208		codegen("\
1209			\n\
1210				obj->struct_ops.%1$s = (__typeof__(obj->struct_ops.%1$s))\n\
1211					bpf_map__initial_value(obj->maps.%1$s, NULL);\n\
1212			\n\
1213			", ident);
1214	}
1215}
1216
1217static int do_skeleton(int argc, char **argv)
1218{
1219	char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
1220	size_t map_cnt = 0, prog_cnt = 0, attach_map_cnt = 0, file_sz, mmap_sz;
1221	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
1222	char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
1223	struct bpf_object *obj = NULL;
1224	const char *file;
1225	char ident[256];
1226	struct bpf_program *prog;
1227	int fd, err = -1;
1228	struct bpf_map *map;
1229	struct btf *btf;
1230	struct stat st;
1231
1232	if (!REQ_ARGS(1)) {
1233		usage();
1234		return -1;
1235	}
1236	file = GET_ARG();
1237
1238	while (argc) {
1239		if (!REQ_ARGS(2))
1240			return -1;
1241
1242		if (is_prefix(*argv, "name")) {
1243			NEXT_ARG();
1244
1245			if (obj_name[0] != '\0') {
1246				p_err("object name already specified");
1247				return -1;
1248			}
1249
1250			strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
1251			obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
1252		} else {
1253			p_err("unknown arg %s", *argv);
1254			return -1;
1255		}
1256
1257		NEXT_ARG();
1258	}
1259
1260	if (argc) {
1261		p_err("extra unknown arguments");
1262		return -1;
1263	}
1264
1265	if (stat(file, &st)) {
1266		p_err("failed to stat() %s: %s", file, strerror(errno));
1267		return -1;
1268	}
1269	file_sz = st.st_size;
1270	mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
1271	fd = open(file, O_RDONLY);
1272	if (fd < 0) {
1273		p_err("failed to open() %s: %s", file, strerror(errno));
1274		return -1;
1275	}
1276	obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
1277	if (obj_data == MAP_FAILED) {
1278		obj_data = NULL;
1279		p_err("failed to mmap() %s: %s", file, strerror(errno));
1280		goto out;
1281	}
1282	if (obj_name[0] == '\0')
1283		get_obj_name(obj_name, file);
1284	opts.object_name = obj_name;
1285	if (verifier_logs)
1286		/* log_level1 + log_level2 + stats, but not stable UAPI */
1287		opts.kernel_log_level = 1 + 2 + 4;
1288	obj = bpf_object__open_mem(obj_data, file_sz, &opts);
1289	if (!obj) {
1290		char err_buf[256];
1291
1292		err = -errno;
1293		libbpf_strerror(err, err_buf, sizeof(err_buf));
1294		p_err("failed to open BPF object file: %s", err_buf);
1295		goto out_obj;
1296	}
1297
1298	bpf_object__for_each_map(map, obj) {
1299		if (!get_map_ident(map, ident, sizeof(ident))) {
1300			p_err("ignoring unrecognized internal map '%s'...",
1301			      bpf_map__name(map));
1302			continue;
1303		}
1304
1305		if (bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS)
1306			attach_map_cnt++;
1307
1308		map_cnt++;
1309	}
1310	bpf_object__for_each_program(prog, obj) {
1311		prog_cnt++;
1312	}
1313
1314	get_header_guard(header_guard, obj_name, "SKEL_H");
1315	if (use_loader) {
1316		codegen("\
1317		\n\
1318		/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
1319		/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */		    \n\
1320		#ifndef %2$s						    \n\
1321		#define %2$s						    \n\
1322									    \n\
1323		#include <bpf/skel_internal.h>				    \n\
1324									    \n\
1325		struct %1$s {						    \n\
1326			struct bpf_loader_ctx ctx;			    \n\
1327		",
1328		obj_name, header_guard
1329		);
1330	} else {
1331		codegen("\
1332		\n\
1333		/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
1334									    \n\
1335		/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */		    \n\
1336		#ifndef %2$s						    \n\
1337		#define %2$s						    \n\
1338									    \n\
1339		#include <errno.h>					    \n\
1340		#include <stdlib.h>					    \n\
1341		#include <bpf/libbpf.h>					    \n\
1342									    \n\
1343		#define BPF_SKEL_SUPPORTS_MAP_AUTO_ATTACH 1		    \n\
1344									    \n\
1345		struct %1$s {						    \n\
1346			struct bpf_object_skeleton *skeleton;		    \n\
1347			struct bpf_object *obj;				    \n\
1348		",
1349		obj_name, header_guard
1350		);
1351	}
1352
1353	if (map_cnt) {
1354		printf("\tstruct {\n");
1355		bpf_object__for_each_map(map, obj) {
1356			if (!get_map_ident(map, ident, sizeof(ident)))
1357				continue;
1358			if (use_loader)
1359				printf("\t\tstruct bpf_map_desc %s;\n", ident);
1360			else
1361				printf("\t\tstruct bpf_map *%s;\n", ident);
1362		}
1363		printf("\t} maps;\n");
1364	}
1365
1366	btf = bpf_object__btf(obj);
1367	err = gen_st_ops_shadow(obj_name, btf, obj);
1368	if (err)
1369		goto out;
1370
1371	if (prog_cnt) {
1372		printf("\tstruct {\n");
1373		bpf_object__for_each_program(prog, obj) {
1374			if (use_loader)
1375				printf("\t\tstruct bpf_prog_desc %s;\n",
1376				       bpf_program__name(prog));
1377			else
1378				printf("\t\tstruct bpf_program *%s;\n",
1379				       bpf_program__name(prog));
1380		}
1381		printf("\t} progs;\n");
1382	}
1383
1384	if (prog_cnt + attach_map_cnt) {
1385		printf("\tstruct {\n");
1386		bpf_object__for_each_program(prog, obj) {
1387			if (use_loader)
1388				printf("\t\tint %s_fd;\n",
1389				       bpf_program__name(prog));
1390			else
1391				printf("\t\tstruct bpf_link *%s;\n",
1392				       bpf_program__name(prog));
1393		}
1394
1395		bpf_object__for_each_map(map, obj) {
1396			if (!get_map_ident(map, ident, sizeof(ident)))
1397				continue;
1398			if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
1399				continue;
1400
1401			if (use_loader)
1402				printf("t\tint %s_fd;\n", ident);
1403			else
1404				printf("\t\tstruct bpf_link *%s;\n", ident);
1405		}
1406
1407		printf("\t} links;\n");
1408	}
1409
1410	if (sign_progs) {
1411		codegen("\
1412		\n\
1413			__s32 keyring_id;				   \n\
1414		");
1415	}
1416
1417	if (btf) {
1418		err = codegen_datasecs(obj, obj_name);
1419		if (err)
1420			goto out;
1421	}
1422	if (use_loader) {
1423		err = gen_trace(obj, obj_name, header_guard);
1424		goto out;
1425	}
1426
1427	codegen("\
1428		\n\
1429									    \n\
1430		#ifdef __cplusplus					    \n\
1431			static inline struct %1$s *open(const struct bpf_object_open_opts *opts = nullptr);\n\
1432			static inline struct %1$s *open_and_load();	    \n\
1433			static inline int load(struct %1$s *skel);	    \n\
1434			static inline int attach(struct %1$s *skel);	    \n\
1435			static inline void detach(struct %1$s *skel);	    \n\
1436			static inline void destroy(struct %1$s *skel);	    \n\
1437			static inline const void *elf_bytes(size_t *sz);    \n\
1438		#endif /* __cplusplus */				    \n\
1439		};							    \n\
1440									    \n\
1441		static void						    \n\
1442		%1$s__destroy(struct %1$s *obj)				    \n\
1443		{							    \n\
1444			if (!obj)					    \n\
1445				return;					    \n\
1446			if (obj->skeleton)				    \n\
1447				bpf_object__destroy_skeleton(obj->skeleton);\n\
1448			free(obj);					    \n\
1449		}							    \n\
1450									    \n\
1451		static inline int					    \n\
1452		%1$s__create_skeleton(struct %1$s *obj);		    \n\
1453									    \n\
1454		static inline struct %1$s *				    \n\
1455		%1$s__open_opts(const struct bpf_object_open_opts *opts)    \n\
1456		{							    \n\
1457			struct %1$s *obj;				    \n\
1458			int err;					    \n\
1459									    \n\
1460			obj = (struct %1$s *)calloc(1, sizeof(*obj));	    \n\
1461			if (!obj) {					    \n\
1462				errno = ENOMEM;				    \n\
1463				return NULL;				    \n\
1464			}						    \n\
1465									    \n\
1466			err = %1$s__create_skeleton(obj);		    \n\
1467			if (err)					    \n\
1468				goto err_out;				    \n\
1469									    \n\
1470			err = bpf_object__open_skeleton(obj->skeleton, opts);\n\
1471			if (err)					    \n\
1472				goto err_out;				    \n\
1473									    \n\
1474		", obj_name);
1475
1476	gen_st_ops_shadow_init(btf, obj);
1477
1478	codegen("\
1479		\n\
1480			return obj;					    \n\
1481		err_out:						    \n\
1482			%1$s__destroy(obj);				    \n\
1483			errno = -err;					    \n\
1484			return NULL;					    \n\
1485		}							    \n\
1486									    \n\
1487		static inline struct %1$s *				    \n\
1488		%1$s__open(void)					    \n\
1489		{							    \n\
1490			return %1$s__open_opts(NULL);			    \n\
1491		}							    \n\
1492									    \n\
1493		static inline int					    \n\
1494		%1$s__load(struct %1$s *obj)				    \n\
1495		{							    \n\
1496			return bpf_object__load_skeleton(obj->skeleton);    \n\
1497		}							    \n\
1498									    \n\
1499		static inline struct %1$s *				    \n\
1500		%1$s__open_and_load(void)				    \n\
1501		{							    \n\
1502			struct %1$s *obj;				    \n\
1503			int err;					    \n\
1504									    \n\
1505			obj = %1$s__open();				    \n\
1506			if (!obj)					    \n\
1507				return NULL;				    \n\
1508			err = %1$s__load(obj);				    \n\
1509			if (err) {					    \n\
1510				%1$s__destroy(obj);			    \n\
1511				errno = -err;				    \n\
1512				return NULL;				    \n\
1513			}						    \n\
1514			return obj;					    \n\
1515		}							    \n\
1516									    \n\
1517		static inline int					    \n\
1518		%1$s__attach(struct %1$s *obj)				    \n\
1519		{							    \n\
1520			return bpf_object__attach_skeleton(obj->skeleton);  \n\
1521		}							    \n\
1522									    \n\
1523		static inline void					    \n\
1524		%1$s__detach(struct %1$s *obj)				    \n\
1525		{							    \n\
1526			bpf_object__detach_skeleton(obj->skeleton);	    \n\
1527		}							    \n\
1528		",
1529		obj_name
1530	);
1531
1532	codegen("\
1533		\n\
1534									    \n\
1535		static inline const void *%1$s__elf_bytes(size_t *sz);	    \n\
1536									    \n\
1537		static inline int					    \n\
1538		%1$s__create_skeleton(struct %1$s *obj)			    \n\
1539		{							    \n\
1540			struct bpf_object_skeleton *s;			    \n\
1541			struct bpf_map_skeleton *map __attribute__((unused));\n\
1542			int err;					    \n\
1543									    \n\
1544			s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));\n\
1545			if (!s)	{					    \n\
1546				err = -ENOMEM;				    \n\
1547				goto err;				    \n\
1548			}						    \n\
1549									    \n\
1550			s->sz = sizeof(*s);				    \n\
1551			s->name = \"%1$s\";				    \n\
1552			s->obj = &obj->obj;				    \n\
1553		",
1554		obj_name
1555	);
1556
1557	codegen_maps_skeleton(obj, map_cnt, true /*mmaped*/, true /*links*/);
1558	codegen_progs_skeleton(obj, prog_cnt, true /*populate_links*/);
1559
1560	codegen("\
1561		\n\
1562									    \n\
1563			s->data = %1$s__elf_bytes(&s->data_sz);		    \n\
1564									    \n\
1565			obj->skeleton = s;				    \n\
1566			return 0;					    \n\
1567		err:							    \n\
1568			bpf_object__destroy_skeleton(s);		    \n\
1569			return err;					    \n\
1570		}							    \n\
1571									    \n\
1572		static inline const void *%1$s__elf_bytes(size_t *sz)	    \n\
1573		{							    \n\
1574			static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
1575		",
1576		obj_name
1577	);
1578
1579	/* embed contents of BPF object file */
1580	print_hex(obj_data, file_sz);
1581
1582	codegen("\
1583		\n\
1584		\";							    \n\
1585									    \n\
1586			*sz = sizeof(data) - 1;				    \n\
1587			return (const void *)data;			    \n\
1588		}							    \n\
1589									    \n\
1590		#ifdef __cplusplus					    \n\
1591		struct %1$s *%1$s::open(const struct bpf_object_open_opts *opts) { return %1$s__open_opts(opts); }\n\
1592		struct %1$s *%1$s::open_and_load() { return %1$s__open_and_load(); }	\n\
1593		int %1$s::load(struct %1$s *skel) { return %1$s__load(skel); }		\n\
1594		int %1$s::attach(struct %1$s *skel) { return %1$s__attach(skel); }	\n\
1595		void %1$s::detach(struct %1$s *skel) { %1$s__detach(skel); }		\n\
1596		void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); }		\n\
1597		const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
1598		#endif /* __cplusplus */				    \n\
1599									    \n\
1600		",
1601		obj_name);
1602
1603	codegen_asserts(obj, obj_name);
1604
1605	codegen("\
1606		\n\
1607									    \n\
1608		#endif /* %1$s */					    \n\
1609		",
1610		header_guard);
1611	err = 0;
1612out:
1613	bpf_object__close(obj);
1614out_obj:
1615	if (obj_data)
1616		munmap(obj_data, mmap_sz);
1617	close(fd);
1618	return err;
1619}
1620
1621/* Subskeletons are like skeletons, except they don't own the bpf_object,
1622 * associated maps, links, etc. Instead, they know about the existence of
1623 * variables, maps, programs and are able to find their locations
1624 * _at runtime_ from an already loaded bpf_object.
1625 *
1626 * This allows for library-like BPF objects to have userspace counterparts
1627 * with access to their own items without having to know anything about the
1628 * final BPF object that the library was linked into.
1629 */
1630static int do_subskeleton(int argc, char **argv)
1631{
1632	char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SUBSKEL_H__")];
1633	size_t i, len, file_sz, map_cnt = 0, prog_cnt = 0, mmap_sz, var_cnt = 0, var_idx = 0;
1634	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
1635	char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
1636	struct bpf_object *obj = NULL;
1637	const char *file, *var_name;
1638	char ident[256];
1639	int fd, err = -1, map_type_id;
1640	const struct bpf_map *map;
1641	struct bpf_program *prog;
1642	struct btf *btf;
1643	const struct btf_type *map_type, *var_type;
1644	const struct btf_var_secinfo *var;
1645	struct stat st;
1646
1647	if (!REQ_ARGS(1)) {
1648		usage();
1649		return -1;
1650	}
1651	file = GET_ARG();
1652
1653	while (argc) {
1654		if (!REQ_ARGS(2))
1655			return -1;
1656
1657		if (is_prefix(*argv, "name")) {
1658			NEXT_ARG();
1659
1660			if (obj_name[0] != '\0') {
1661				p_err("object name already specified");
1662				return -1;
1663			}
1664
1665			strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
1666			obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
1667		} else {
1668			p_err("unknown arg %s", *argv);
1669			return -1;
1670		}
1671
1672		NEXT_ARG();
1673	}
1674
1675	if (argc) {
1676		p_err("extra unknown arguments");
1677		return -1;
1678	}
1679
1680	if (use_loader) {
1681		p_err("cannot use loader for subskeletons");
1682		return -1;
1683	}
1684
1685	if (stat(file, &st)) {
1686		p_err("failed to stat() %s: %s", file, strerror(errno));
1687		return -1;
1688	}
1689	file_sz = st.st_size;
1690	mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
1691	fd = open(file, O_RDONLY);
1692	if (fd < 0) {
1693		p_err("failed to open() %s: %s", file, strerror(errno));
1694		return -1;
1695	}
1696	obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
1697	if (obj_data == MAP_FAILED) {
1698		obj_data = NULL;
1699		p_err("failed to mmap() %s: %s", file, strerror(errno));
1700		goto out;
1701	}
1702	if (obj_name[0] == '\0')
1703		get_obj_name(obj_name, file);
1704
1705	/* The empty object name allows us to use bpf_map__name and produce
1706	 * ELF section names out of it. (".data" instead of "obj.data")
1707	 */
1708	opts.object_name = "";
1709	obj = bpf_object__open_mem(obj_data, file_sz, &opts);
1710	if (!obj) {
1711		char err_buf[256];
1712
1713		libbpf_strerror(errno, err_buf, sizeof(err_buf));
1714		p_err("failed to open BPF object file: %s", err_buf);
1715		obj = NULL;
1716		goto out;
1717	}
1718
1719	btf = bpf_object__btf(obj);
1720	if (!btf) {
1721		err = -1;
1722		p_err("need btf type information for %s", obj_name);
1723		goto out;
1724	}
1725
1726	bpf_object__for_each_program(prog, obj) {
1727		prog_cnt++;
1728	}
1729
1730	/* First, count how many variables we have to find.
1731	 * We need this in advance so the subskel can allocate the right
1732	 * amount of storage.
1733	 */
1734	bpf_object__for_each_map(map, obj) {
1735		if (!get_map_ident(map, ident, sizeof(ident)))
1736			continue;
1737
1738		/* Also count all maps that have a name */
1739		map_cnt++;
1740
1741		if (!is_mmapable_map(map, ident, sizeof(ident)))
1742			continue;
1743
1744		map_type_id = bpf_map__btf_value_type_id(map);
1745		if (map_type_id <= 0) {
1746			err = map_type_id;
1747			goto out;
1748		}
1749		map_type = btf__type_by_id(btf, map_type_id);
1750
1751		var = btf_var_secinfos(map_type);
1752		len = btf_vlen(map_type);
1753		for (i = 0; i < len; i++, var++) {
1754			var_type = btf__type_by_id(btf, var->type);
1755
1756			if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
1757				continue;
1758
1759			var_cnt++;
1760		}
1761	}
1762
1763	get_header_guard(header_guard, obj_name, "SUBSKEL_H");
1764	codegen("\
1765	\n\
1766	/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */	    \n\
1767									    \n\
1768	/* THIS FILE IS AUTOGENERATED! */				    \n\
1769	#ifndef %2$s							    \n\
1770	#define %2$s							    \n\
1771									    \n\
1772	#include <errno.h>						    \n\
1773	#include <stdlib.h>						    \n\
1774	#include <bpf/libbpf.h>						    \n\
1775									    \n\
1776	struct %1$s {							    \n\
1777		struct bpf_object *obj;					    \n\
1778		struct bpf_object_subskeleton *subskel;			    \n\
1779	", obj_name, header_guard);
1780
1781	if (map_cnt) {
1782		printf("\tstruct {\n");
1783		bpf_object__for_each_map(map, obj) {
1784			if (!get_map_ident(map, ident, sizeof(ident)))
1785				continue;
1786			printf("\t\tstruct bpf_map *%s;\n", ident);
1787		}
1788		printf("\t} maps;\n");
1789	}
1790
1791	err = gen_st_ops_shadow(obj_name, btf, obj);
1792	if (err)
1793		goto out;
1794
1795	if (prog_cnt) {
1796		printf("\tstruct {\n");
1797		bpf_object__for_each_program(prog, obj) {
1798			printf("\t\tstruct bpf_program *%s;\n",
1799				bpf_program__name(prog));
1800		}
1801		printf("\t} progs;\n");
1802	}
1803
1804	err = codegen_subskel_datasecs(obj, obj_name);
1805	if (err)
1806		goto out;
1807
1808	/* emit code that will allocate enough storage for all symbols */
1809	codegen("\
1810		\n\
1811									    \n\
1812		#ifdef __cplusplus					    \n\
1813			static inline struct %1$s *open(const struct bpf_object *src);\n\
1814			static inline void destroy(struct %1$s *skel);	    \n\
1815		#endif /* __cplusplus */				    \n\
1816		};							    \n\
1817									    \n\
1818		static inline void					    \n\
1819		%1$s__destroy(struct %1$s *skel)			    \n\
1820		{							    \n\
1821			if (!skel)					    \n\
1822				return;					    \n\
1823			if (skel->subskel)				    \n\
1824				bpf_object__destroy_subskeleton(skel->subskel);\n\
1825			free(skel);					    \n\
1826		}							    \n\
1827									    \n\
1828		static inline struct %1$s *				    \n\
1829		%1$s__open(const struct bpf_object *src)		    \n\
1830		{							    \n\
1831			struct %1$s *obj;				    \n\
1832			struct bpf_object_subskeleton *s;		    \n\
1833			struct bpf_map_skeleton *map __attribute__((unused));\n\
1834			int err;					    \n\
1835									    \n\
1836			obj = (struct %1$s *)calloc(1, sizeof(*obj));	    \n\
1837			if (!obj) {					    \n\
1838				err = -ENOMEM;				    \n\
1839				goto err;				    \n\
1840			}						    \n\
1841			s = (struct bpf_object_subskeleton *)calloc(1, sizeof(*s));\n\
1842			if (!s) {					    \n\
1843				err = -ENOMEM;				    \n\
1844				goto err;				    \n\
1845			}						    \n\
1846			s->sz = sizeof(*s);				    \n\
1847			s->obj = src;					    \n\
1848			s->var_skel_sz = sizeof(*s->vars);		    \n\
1849			obj->subskel = s;				    \n\
1850									    \n\
1851			/* vars */					    \n\
1852			s->var_cnt = %2$d;				    \n\
1853			s->vars = (struct bpf_var_skeleton *)calloc(%2$d, sizeof(*s->vars));\n\
1854			if (!s->vars) {					    \n\
1855				err = -ENOMEM;				    \n\
1856				goto err;				    \n\
1857			}						    \n\
1858		",
1859		obj_name, var_cnt
1860	);
1861
1862	/* walk through each symbol and emit the runtime representation */
1863	bpf_object__for_each_map(map, obj) {
1864		if (!is_mmapable_map(map, ident, sizeof(ident)))
1865			continue;
1866
1867		map_type_id = bpf_map__btf_value_type_id(map);
1868		if (map_type_id <= 0)
1869			/* skip over internal maps with no type*/
1870			continue;
1871
1872		map_type = btf__type_by_id(btf, map_type_id);
1873		var = btf_var_secinfos(map_type);
1874		len = btf_vlen(map_type);
1875		for (i = 0; i < len; i++, var++) {
1876			var_type = btf__type_by_id(btf, var->type);
1877			var_name = btf__name_by_offset(btf, var_type->name_off);
1878
1879			if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
1880				continue;
1881
1882			/* Note that we use the dot prefix in .data as the
1883			 * field access operator i.e. maps%s becomes maps.data
1884			 */
1885			codegen("\
1886			\n\
1887									    \n\
1888				s->vars[%3$d].name = \"%1$s\";		    \n\
1889				s->vars[%3$d].map = &obj->maps.%2$s;	    \n\
1890				s->vars[%3$d].addr = (void **) &obj->%2$s.%1$s;\n\
1891			", var_name, ident, var_idx);
1892
1893			var_idx++;
1894		}
1895	}
1896
1897	codegen_maps_skeleton(obj, map_cnt, false /*mmaped*/, false /*links*/);
1898	codegen_progs_skeleton(obj, prog_cnt, false /*links*/);
1899
1900	codegen("\
1901		\n\
1902									    \n\
1903			err = bpf_object__open_subskeleton(s);		    \n\
1904			if (err)					    \n\
1905				goto err;				    \n\
1906									    \n\
1907		");
1908
1909	gen_st_ops_shadow_init(btf, obj);
1910
1911	codegen("\
1912		\n\
1913			return obj;					    \n\
1914		err:							    \n\
1915			%1$s__destroy(obj);				    \n\
1916			errno = -err;					    \n\
1917			return NULL;					    \n\
1918		}							    \n\
1919									    \n\
1920		#ifdef __cplusplus					    \n\
1921		struct %1$s *%1$s::open(const struct bpf_object *src) { return %1$s__open(src); }\n\
1922		void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); }\n\
1923		#endif /* __cplusplus */				    \n\
1924									    \n\
1925		#endif /* %2$s */					    \n\
1926		",
1927		obj_name, header_guard);
1928	err = 0;
1929out:
1930	bpf_object__close(obj);
1931	if (obj_data)
1932		munmap(obj_data, mmap_sz);
1933	close(fd);
1934	return err;
1935}
1936
1937static int do_object(int argc, char **argv)
1938{
1939	struct bpf_linker *linker;
1940	const char *output_file, *file;
1941	int err = 0;
1942
1943	if (!REQ_ARGS(2)) {
1944		usage();
1945		return -1;
1946	}
1947
1948	output_file = GET_ARG();
1949
1950	linker = bpf_linker__new(output_file, NULL);
1951	if (!linker) {
1952		p_err("failed to create BPF linker instance");
1953		return -1;
1954	}
1955
1956	while (argc) {
1957		file = GET_ARG();
1958
1959		err = bpf_linker__add_file(linker, file, NULL);
1960		if (err) {
1961			p_err("failed to link '%s': %s (%d)", file, strerror(errno), errno);
1962			goto out;
1963		}
1964	}
1965
1966	err = bpf_linker__finalize(linker);
1967	if (err) {
1968		p_err("failed to finalize ELF file: %s (%d)", strerror(errno), errno);
1969		goto out;
1970	}
1971
1972	err = 0;
1973out:
1974	bpf_linker__free(linker);
1975	return err;
1976}
1977
1978static int do_help(int argc, char **argv)
1979{
1980	if (json_output) {
1981		jsonw_null(json_wtr);
1982		return 0;
1983	}
1984
1985	fprintf(stderr,
1986		"Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
1987		"       %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
1988		"       %1$s %2$s subskeleton FILE [name OBJECT_NAME]\n"
1989		"       %1$s %2$s min_core_btf INPUT OUTPUT OBJECT [OBJECT...]\n"
1990		"       %1$s %2$s help\n"
1991		"\n"
1992		"       " HELP_SPEC_OPTIONS " |\n"
1993		"                    {-L|--use-loader} | [ {-S|--sign } {-k} <private_key.pem> {-i} <certificate.x509> ]}\n"
1994		"",
1995		bin_name, "gen");
1996
1997	return 0;
1998}
1999
2000static int btf_save_raw(const struct btf *btf, const char *path)
2001{
2002	const void *data;
2003	FILE *f = NULL;
2004	__u32 data_sz;
2005	int err = 0;
2006
2007	data = btf__raw_data(btf, &data_sz);
2008	if (!data)
2009		return -ENOMEM;
2010
2011	f = fopen(path, "wb");
2012	if (!f)
2013		return -errno;
2014
2015	if (fwrite(data, 1, data_sz, f) != data_sz)
2016		err = -errno;
2017
2018	fclose(f);
2019	return err;
2020}
2021
2022struct btfgen_info {
2023	struct btf *src_btf;
2024	struct btf *marked_btf; /* btf structure used to mark used types */
2025};
2026
2027static size_t btfgen_hash_fn(long key, void *ctx)
2028{
2029	return key;
2030}
2031
2032static bool btfgen_equal_fn(long k1, long k2, void *ctx)
2033{
2034	return k1 == k2;
2035}
2036
2037static void btfgen_free_info(struct btfgen_info *info)
2038{
2039	if (!info)
2040		return;
2041
2042	btf__free(info->src_btf);
2043	btf__free(info->marked_btf);
2044
2045	free(info);
2046}
2047
2048static struct btfgen_info *
2049btfgen_new_info(const char *targ_btf_path)
2050{
2051	struct btfgen_info *info;
2052	int err;
2053
2054	info = calloc(1, sizeof(*info));
2055	if (!info)
2056		return NULL;
2057
2058	info->src_btf = btf__parse(targ_btf_path, NULL);
2059	if (!info->src_btf) {
2060		err = -errno;
2061		p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
2062		goto err_out;
2063	}
2064
2065	info->marked_btf = btf__parse(targ_btf_path, NULL);
2066	if (!info->marked_btf) {
2067		err = -errno;
2068		p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
2069		goto err_out;
2070	}
2071
2072	return info;
2073
2074err_out:
2075	btfgen_free_info(info);
2076	errno = -err;
2077	return NULL;
2078}
2079
2080#define MARKED UINT32_MAX
2081
2082static void btfgen_mark_member(struct btfgen_info *info, int type_id, int idx)
2083{
2084	const struct btf_type *t = btf__type_by_id(info->marked_btf, type_id);
2085	struct btf_member *m = btf_members(t) + idx;
2086
2087	m->name_off = MARKED;
2088}
2089
2090static int
2091btfgen_mark_type(struct btfgen_info *info, unsigned int type_id, bool follow_pointers)
2092{
2093	const struct btf_type *btf_type = btf__type_by_id(info->src_btf, type_id);
2094	struct btf_type *cloned_type;
2095	struct btf_param *param;
2096	struct btf_array *array;
2097	int err, i;
2098
2099	if (type_id == 0)
2100		return 0;
2101
2102	/* mark type on cloned BTF as used */
2103	cloned_type = (struct btf_type *) btf__type_by_id(info->marked_btf, type_id);
2104	cloned_type->name_off = MARKED;
2105
2106	/* recursively mark other types needed by it */
2107	switch (btf_kind(btf_type)) {
2108	case BTF_KIND_UNKN:
2109	case BTF_KIND_INT:
2110	case BTF_KIND_FLOAT:
2111	case BTF_KIND_ENUM:
2112	case BTF_KIND_ENUM64:
2113	case BTF_KIND_STRUCT:
2114	case BTF_KIND_UNION:
2115		break;
2116	case BTF_KIND_PTR:
2117		if (follow_pointers) {
2118			err = btfgen_mark_type(info, btf_type->type, follow_pointers);
2119			if (err)
2120				return err;
2121		}
2122		break;
2123	case BTF_KIND_CONST:
2124	case BTF_KIND_RESTRICT:
2125	case BTF_KIND_VOLATILE:
2126	case BTF_KIND_TYPEDEF:
2127		err = btfgen_mark_type(info, btf_type->type, follow_pointers);
2128		if (err)
2129			return err;
2130		break;
2131	case BTF_KIND_ARRAY:
2132		array = btf_array(btf_type);
2133
2134		/* mark array type */
2135		err = btfgen_mark_type(info, array->type, follow_pointers);
2136		/* mark array's index type */
2137		err = err ? : btfgen_mark_type(info, array->index_type, follow_pointers);
2138		if (err)
2139			return err;
2140		break;
2141	case BTF_KIND_FUNC_PROTO:
2142		/* mark ret type */
2143		err = btfgen_mark_type(info, btf_type->type, follow_pointers);
2144		if (err)
2145			return err;
2146
2147		/* mark parameters types */
2148		param = btf_params(btf_type);
2149		for (i = 0; i < btf_vlen(btf_type); i++) {
2150			err = btfgen_mark_type(info, param->type, follow_pointers);
2151			if (err)
2152				return err;
2153			param++;
2154		}
2155		break;
2156	/* tells if some other type needs to be handled */
2157	default:
2158		p_err("unsupported kind: %s (%u)", btf_kind_str(btf_type), type_id);
2159		return -EINVAL;
2160	}
2161
2162	return 0;
2163}
2164
2165static int btfgen_record_field_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2166{
2167	struct btf *btf = info->src_btf;
2168	const struct btf_type *btf_type;
2169	struct btf_member *btf_member;
2170	struct btf_array *array;
2171	unsigned int type_id = targ_spec->root_type_id;
2172	int idx, err;
2173
2174	/* mark root type */
2175	btf_type = btf__type_by_id(btf, type_id);
2176	err = btfgen_mark_type(info, type_id, false);
2177	if (err)
2178		return err;
2179
2180	/* mark types for complex types (arrays, unions, structures) */
2181	for (int i = 1; i < targ_spec->raw_len; i++) {
2182		/* skip typedefs and mods */
2183		while (btf_is_mod(btf_type) || btf_is_typedef(btf_type)) {
2184			type_id = btf_type->type;
2185			btf_type = btf__type_by_id(btf, type_id);
2186		}
2187
2188		switch (btf_kind(btf_type)) {
2189		case BTF_KIND_STRUCT:
2190		case BTF_KIND_UNION:
2191			idx = targ_spec->raw_spec[i];
2192			btf_member = btf_members(btf_type) + idx;
2193
2194			/* mark member */
2195			btfgen_mark_member(info, type_id, idx);
2196
2197			/* mark member's type */
2198			type_id = btf_member->type;
2199			btf_type = btf__type_by_id(btf, type_id);
2200			err = btfgen_mark_type(info, type_id, false);
2201			if (err)
2202				return err;
2203			break;
2204		case BTF_KIND_ARRAY:
2205			array = btf_array(btf_type);
2206			type_id = array->type;
2207			btf_type = btf__type_by_id(btf, type_id);
2208			break;
2209		default:
2210			p_err("unsupported kind: %s (%u)",
2211			      btf_kind_str(btf_type), btf_type->type);
2212			return -EINVAL;
2213		}
2214	}
2215
2216	return 0;
2217}
2218
2219/* Mark types, members, and member types. Compared to btfgen_record_field_relo,
2220 * this function does not rely on the target spec for inferring members, but
2221 * uses the associated BTF.
2222 *
2223 * The `behind_ptr` argument is used to stop marking of composite types reached
2224 * through a pointer. This way, we can keep BTF size in check while providing
2225 * reasonable match semantics.
2226 */
2227static int btfgen_mark_type_match(struct btfgen_info *info, __u32 type_id, bool behind_ptr)
2228{
2229	const struct btf_type *btf_type;
2230	struct btf *btf = info->src_btf;
2231	struct btf_type *cloned_type;
2232	int i, err;
2233
2234	if (type_id == 0)
2235		return 0;
2236
2237	btf_type = btf__type_by_id(btf, type_id);
2238	/* mark type on cloned BTF as used */
2239	cloned_type = (struct btf_type *)btf__type_by_id(info->marked_btf, type_id);
2240	cloned_type->name_off = MARKED;
2241
2242	switch (btf_kind(btf_type)) {
2243	case BTF_KIND_UNKN:
2244	case BTF_KIND_INT:
2245	case BTF_KIND_FLOAT:
2246	case BTF_KIND_ENUM:
2247	case BTF_KIND_ENUM64:
2248		break;
2249	case BTF_KIND_STRUCT:
2250	case BTF_KIND_UNION: {
2251		struct btf_member *m = btf_members(btf_type);
2252		__u16 vlen = btf_vlen(btf_type);
2253
2254		if (behind_ptr)
2255			break;
2256
2257		for (i = 0; i < vlen; i++, m++) {
2258			/* mark member */
2259			btfgen_mark_member(info, type_id, i);
2260
2261			/* mark member's type */
2262			err = btfgen_mark_type_match(info, m->type, false);
2263			if (err)
2264				return err;
2265		}
2266		break;
2267	}
2268	case BTF_KIND_CONST:
2269	case BTF_KIND_FWD:
2270	case BTF_KIND_RESTRICT:
2271	case BTF_KIND_TYPEDEF:
2272	case BTF_KIND_VOLATILE:
2273		return btfgen_mark_type_match(info, btf_type->type, behind_ptr);
2274	case BTF_KIND_PTR:
2275		return btfgen_mark_type_match(info, btf_type->type, true);
2276	case BTF_KIND_ARRAY: {
2277		struct btf_array *array;
2278
2279		array = btf_array(btf_type);
2280		/* mark array type */
2281		err = btfgen_mark_type_match(info, array->type, false);
2282		/* mark array's index type */
2283		err = err ? : btfgen_mark_type_match(info, array->index_type, false);
2284		if (err)
2285			return err;
2286		break;
2287	}
2288	case BTF_KIND_FUNC_PROTO: {
2289		__u16 vlen = btf_vlen(btf_type);
2290		struct btf_param *param;
2291
2292		/* mark ret type */
2293		err = btfgen_mark_type_match(info, btf_type->type, false);
2294		if (err)
2295			return err;
2296
2297		/* mark parameters types */
2298		param = btf_params(btf_type);
2299		for (i = 0; i < vlen; i++) {
2300			err = btfgen_mark_type_match(info, param->type, false);
2301			if (err)
2302				return err;
2303			param++;
2304		}
2305		break;
2306	}
2307	/* tells if some other type needs to be handled */
2308	default:
2309		p_err("unsupported kind: %s (%u)", btf_kind_str(btf_type), type_id);
2310		return -EINVAL;
2311	}
2312
2313	return 0;
2314}
2315
2316/* Mark types, members, and member types. Compared to btfgen_record_field_relo,
2317 * this function does not rely on the target spec for inferring members, but
2318 * uses the associated BTF.
2319 */
2320static int btfgen_record_type_match_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2321{
2322	return btfgen_mark_type_match(info, targ_spec->root_type_id, false);
2323}
2324
2325static int btfgen_record_type_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2326{
2327	return btfgen_mark_type(info, targ_spec->root_type_id, true);
2328}
2329
2330static int btfgen_record_enumval_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2331{
2332	return btfgen_mark_type(info, targ_spec->root_type_id, false);
2333}
2334
2335static int btfgen_record_reloc(struct btfgen_info *info, struct bpf_core_spec *res)
2336{
2337	switch (res->relo_kind) {
2338	case BPF_CORE_FIELD_BYTE_OFFSET:
2339	case BPF_CORE_FIELD_BYTE_SIZE:
2340	case BPF_CORE_FIELD_EXISTS:
2341	case BPF_CORE_FIELD_SIGNED:
2342	case BPF_CORE_FIELD_LSHIFT_U64:
2343	case BPF_CORE_FIELD_RSHIFT_U64:
2344		return btfgen_record_field_relo(info, res);
2345	case BPF_CORE_TYPE_ID_LOCAL: /* BPF_CORE_TYPE_ID_LOCAL doesn't require kernel BTF */
2346		return 0;
2347	case BPF_CORE_TYPE_ID_TARGET:
2348	case BPF_CORE_TYPE_EXISTS:
2349	case BPF_CORE_TYPE_SIZE:
2350		return btfgen_record_type_relo(info, res);
2351	case BPF_CORE_TYPE_MATCHES:
2352		return btfgen_record_type_match_relo(info, res);
2353	case BPF_CORE_ENUMVAL_EXISTS:
2354	case BPF_CORE_ENUMVAL_VALUE:
2355		return btfgen_record_enumval_relo(info, res);
2356	default:
2357		return -EINVAL;
2358	}
2359}
2360
2361static struct bpf_core_cand_list *
2362btfgen_find_cands(const struct btf *local_btf, const struct btf *targ_btf, __u32 local_id)
2363{
2364	const struct btf_type *local_type;
2365	struct bpf_core_cand_list *cands = NULL;
2366	struct bpf_core_cand local_cand = {};
2367	size_t local_essent_len;
2368	const char *local_name;
2369	int err;
2370
2371	local_cand.btf = local_btf;
2372	local_cand.id = local_id;
2373
2374	local_type = btf__type_by_id(local_btf, local_id);
2375	if (!local_type) {
2376		err = -EINVAL;
2377		goto err_out;
2378	}
2379
2380	local_name = btf__name_by_offset(local_btf, local_type->name_off);
2381	if (!local_name) {
2382		err = -EINVAL;
2383		goto err_out;
2384	}
2385	local_essent_len = bpf_core_essential_name_len(local_name);
2386
2387	cands = calloc(1, sizeof(*cands));
2388	if (!cands)
2389		return NULL;
2390
2391	err = bpf_core_add_cands(&local_cand, local_essent_len, targ_btf, "vmlinux", 1, cands);
2392	if (err)
2393		goto err_out;
2394
2395	return cands;
2396
2397err_out:
2398	bpf_core_free_cands(cands);
2399	errno = -err;
2400	return NULL;
2401}
2402
2403/* Record relocation information for a single BPF object */
2404static int btfgen_record_obj(struct btfgen_info *info, const char *obj_path)
2405{
2406	const struct btf_ext_info_sec *sec;
2407	const struct bpf_core_relo *relo;
2408	const struct btf_ext_info *seg;
2409	struct hashmap_entry *entry;
2410	struct hashmap *cand_cache = NULL;
2411	struct btf_ext *btf_ext = NULL;
2412	unsigned int relo_idx;
2413	struct btf *btf = NULL;
2414	size_t i;
2415	int err;
2416
2417	btf = btf__parse(obj_path, &btf_ext);
2418	if (!btf) {
2419		err = -errno;
2420		p_err("failed to parse BPF object '%s': %s", obj_path, strerror(errno));
2421		return err;
2422	}
2423
2424	if (!btf_ext) {
2425		p_err("failed to parse BPF object '%s': section %s not found",
2426		      obj_path, BTF_EXT_ELF_SEC);
2427		err = -EINVAL;
2428		goto out;
2429	}
2430
2431	if (btf_ext->core_relo_info.len == 0) {
2432		err = 0;
2433		goto out;
2434	}
2435
2436	cand_cache = hashmap__new(btfgen_hash_fn, btfgen_equal_fn, NULL);
2437	if (IS_ERR(cand_cache)) {
2438		err = PTR_ERR(cand_cache);
2439		goto out;
2440	}
2441
2442	seg = &btf_ext->core_relo_info;
2443	for_each_btf_ext_sec(seg, sec) {
2444		for_each_btf_ext_rec(seg, sec, relo_idx, relo) {
2445			struct bpf_core_spec specs_scratch[3] = {};
2446			struct bpf_core_relo_res targ_res = {};
2447			struct bpf_core_cand_list *cands = NULL;
2448			const char *sec_name = btf__name_by_offset(btf, sec->sec_name_off);
2449
2450			if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
2451			    !hashmap__find(cand_cache, relo->type_id, &cands)) {
2452				cands = btfgen_find_cands(btf, info->src_btf, relo->type_id);
2453				if (!cands) {
2454					err = -errno;
2455					goto out;
2456				}
2457
2458				err = hashmap__set(cand_cache, relo->type_id, cands,
2459						   NULL, NULL);
2460				if (err)
2461					goto out;
2462			}
2463
2464			err = bpf_core_calc_relo_insn(sec_name, relo, relo_idx, btf, cands,
2465						      specs_scratch, &targ_res);
2466			if (err)
2467				goto out;
2468
2469			/* specs_scratch[2] is the target spec */
2470			err = btfgen_record_reloc(info, &specs_scratch[2]);
2471			if (err)
2472				goto out;
2473		}
2474	}
2475
2476out:
2477	btf__free(btf);
2478	btf_ext__free(btf_ext);
2479
2480	if (!IS_ERR_OR_NULL(cand_cache)) {
2481		hashmap__for_each_entry(cand_cache, entry, i) {
2482			bpf_core_free_cands(entry->pvalue);
2483		}
2484		hashmap__free(cand_cache);
2485	}
2486
2487	return err;
2488}
2489
2490/* Generate BTF from relocation information previously recorded */
2491static struct btf *btfgen_get_btf(struct btfgen_info *info)
2492{
2493	struct btf *btf_new = NULL;
2494	unsigned int *ids = NULL;
2495	unsigned int i, n = btf__type_cnt(info->marked_btf);
2496	int err = 0;
2497
2498	btf_new = btf__new_empty();
2499	if (!btf_new) {
2500		err = -errno;
2501		goto err_out;
2502	}
2503
2504	ids = calloc(n, sizeof(*ids));
2505	if (!ids) {
2506		err = -errno;
2507		goto err_out;
2508	}
2509
2510	/* first pass: add all marked types to btf_new and add their new ids to the ids map */
2511	for (i = 1; i < n; i++) {
2512		const struct btf_type *cloned_type, *type;
2513		const char *name;
2514		int new_id;
2515
2516		cloned_type = btf__type_by_id(info->marked_btf, i);
2517
2518		if (cloned_type->name_off != MARKED)
2519			continue;
2520
2521		type = btf__type_by_id(info->src_btf, i);
2522
2523		/* add members for struct and union */
2524		if (btf_is_composite(type)) {
2525			struct btf_member *cloned_m, *m;
2526			unsigned short vlen;
2527			int idx_src;
2528
2529			name = btf__str_by_offset(info->src_btf, type->name_off);
2530
2531			if (btf_is_struct(type))
2532				err = btf__add_struct(btf_new, name, type->size);
2533			else
2534				err = btf__add_union(btf_new, name, type->size);
2535
2536			if (err < 0)
2537				goto err_out;
2538			new_id = err;
2539
2540			cloned_m = btf_members(cloned_type);
2541			m = btf_members(type);
2542			vlen = btf_vlen(cloned_type);
2543			for (idx_src = 0; idx_src < vlen; idx_src++, cloned_m++, m++) {
2544				/* add only members that are marked as used */
2545				if (cloned_m->name_off != MARKED)
2546					continue;
2547
2548				name = btf__str_by_offset(info->src_btf, m->name_off);
2549				err = btf__add_field(btf_new, name, m->type,
2550						     btf_member_bit_offset(cloned_type, idx_src),
2551						     btf_member_bitfield_size(cloned_type, idx_src));
2552				if (err < 0)
2553					goto err_out;
2554			}
2555		} else {
2556			err = btf__add_type(btf_new, info->src_btf, type);
2557			if (err < 0)
2558				goto err_out;
2559			new_id = err;
2560		}
2561
2562		/* add ID mapping */
2563		ids[i] = new_id;
2564	}
2565
2566	/* second pass: fix up type ids */
2567	for (i = 1; i < btf__type_cnt(btf_new); i++) {
2568		struct btf_type *btf_type = (struct btf_type *) btf__type_by_id(btf_new, i);
2569		struct btf_field_iter it;
2570		__u32 *type_id;
2571
2572		err = btf_field_iter_init(&it, btf_type, BTF_FIELD_ITER_IDS);
2573		if (err)
2574			goto err_out;
2575
2576		while ((type_id = btf_field_iter_next(&it)))
2577			*type_id = ids[*type_id];
2578	}
2579
2580	free(ids);
2581	return btf_new;
2582
2583err_out:
2584	btf__free(btf_new);
2585	free(ids);
2586	errno = -err;
2587	return NULL;
2588}
2589
2590/* Create minimized BTF file for a set of BPF objects.
2591 *
2592 * The BTFGen algorithm is divided in two main parts: (1) collect the
2593 * BTF types that are involved in relocations and (2) generate the BTF
2594 * object using the collected types.
2595 *
2596 * In order to collect the types involved in the relocations, we parse
2597 * the BTF and BTF.ext sections of the BPF objects and use
2598 * bpf_core_calc_relo_insn() to get the target specification, this
2599 * indicates how the types and fields are used in a relocation.
2600 *
2601 * Types are recorded in different ways according to the kind of the
2602 * relocation. For field-based relocations only the members that are
2603 * actually used are saved in order to reduce the size of the generated
2604 * BTF file. For type-based relocations empty struct / unions are
2605 * generated and for enum-based relocations the whole type is saved.
2606 *
2607 * The second part of the algorithm generates the BTF object. It creates
2608 * an empty BTF object and fills it with the types recorded in the
2609 * previous step. This function takes care of only adding the structure
2610 * and union members that were marked as used and it also fixes up the
2611 * type IDs on the generated BTF object.
2612 */
2613static int minimize_btf(const char *src_btf, const char *dst_btf, const char *objspaths[])
2614{
2615	struct btfgen_info *info;
2616	struct btf *btf_new = NULL;
2617	int err, i;
2618
2619	info = btfgen_new_info(src_btf);
2620	if (!info) {
2621		err = -errno;
2622		p_err("failed to allocate info structure: %s", strerror(errno));
2623		goto out;
2624	}
2625
2626	for (i = 0; objspaths[i] != NULL; i++) {
2627		err = btfgen_record_obj(info, objspaths[i]);
2628		if (err) {
2629			p_err("error recording relocations for %s: %s", objspaths[i],
2630			      strerror(errno));
2631			goto out;
2632		}
2633	}
2634
2635	btf_new = btfgen_get_btf(info);
2636	if (!btf_new) {
2637		err = -errno;
2638		p_err("error generating BTF: %s", strerror(errno));
2639		goto out;
2640	}
2641
2642	err = btf_save_raw(btf_new, dst_btf);
2643	if (err) {
2644		p_err("error saving btf file: %s", strerror(errno));
2645		goto out;
2646	}
2647
2648out:
2649	btf__free(btf_new);
2650	btfgen_free_info(info);
2651
2652	return err;
2653}
2654
2655static int do_min_core_btf(int argc, char **argv)
2656{
2657	const char *input, *output, **objs;
2658	int i, err;
2659
2660	if (!REQ_ARGS(3)) {
2661		usage();
2662		return -1;
2663	}
2664
2665	input = GET_ARG();
2666	output = GET_ARG();
2667
2668	objs = (const char **) calloc(argc + 1, sizeof(*objs));
2669	if (!objs) {
2670		p_err("failed to allocate array for object names");
2671		return -ENOMEM;
2672	}
2673
2674	i = 0;
2675	while (argc)
2676		objs[i++] = GET_ARG();
2677
2678	err = minimize_btf(input, output, objs);
2679	free(objs);
2680	return err;
2681}
2682
2683static const struct cmd cmds[] = {
2684	{ "object",		do_object },
2685	{ "skeleton",		do_skeleton },
2686	{ "subskeleton",	do_subskeleton },
2687	{ "min_core_btf",	do_min_core_btf},
2688	{ "help",		do_help },
2689	{ 0 }
2690};
2691
2692int do_gen(int argc, char **argv)
2693{
2694	return cmd_select(cmds, argc, argv, do_help);
2695}
~/ Read-only file preview.