cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

btf_helpers.c (6405B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2020 Facebook */
      3#include <stdio.h>
      4#include <errno.h>
      5#include <bpf/btf.h>
      6#include <bpf/libbpf.h>
      7#include "test_progs.h"
      8
      9static const char * const btf_kind_str_mapping[] = {
     10	[BTF_KIND_UNKN]		= "UNKNOWN",
     11	[BTF_KIND_INT]		= "INT",
     12	[BTF_KIND_PTR]		= "PTR",
     13	[BTF_KIND_ARRAY]	= "ARRAY",
     14	[BTF_KIND_STRUCT]	= "STRUCT",
     15	[BTF_KIND_UNION]	= "UNION",
     16	[BTF_KIND_ENUM]		= "ENUM",
     17	[BTF_KIND_FWD]		= "FWD",
     18	[BTF_KIND_TYPEDEF]	= "TYPEDEF",
     19	[BTF_KIND_VOLATILE]	= "VOLATILE",
     20	[BTF_KIND_CONST]	= "CONST",
     21	[BTF_KIND_RESTRICT]	= "RESTRICT",
     22	[BTF_KIND_FUNC]		= "FUNC",
     23	[BTF_KIND_FUNC_PROTO]	= "FUNC_PROTO",
     24	[BTF_KIND_VAR]		= "VAR",
     25	[BTF_KIND_DATASEC]	= "DATASEC",
     26	[BTF_KIND_FLOAT]	= "FLOAT",
     27	[BTF_KIND_DECL_TAG]	= "DECL_TAG",
     28	[BTF_KIND_TYPE_TAG]	= "TYPE_TAG",
     29};
     30
     31static const char *btf_kind_str(__u16 kind)
     32{
     33	if (kind > BTF_KIND_TYPE_TAG)
     34		return "UNKNOWN";
     35	return btf_kind_str_mapping[kind];
     36}
     37
     38static const char *btf_int_enc_str(__u8 encoding)
     39{
     40	switch (encoding) {
     41	case 0:
     42		return "(none)";
     43	case BTF_INT_SIGNED:
     44		return "SIGNED";
     45	case BTF_INT_CHAR:
     46		return "CHAR";
     47	case BTF_INT_BOOL:
     48		return "BOOL";
     49	default:
     50		return "UNKN";
     51	}
     52}
     53
     54static const char *btf_var_linkage_str(__u32 linkage)
     55{
     56	switch (linkage) {
     57	case BTF_VAR_STATIC:
     58		return "static";
     59	case BTF_VAR_GLOBAL_ALLOCATED:
     60		return "global-alloc";
     61	default:
     62		return "(unknown)";
     63	}
     64}
     65
     66static const char *btf_func_linkage_str(const struct btf_type *t)
     67{
     68	switch (btf_vlen(t)) {
     69	case BTF_FUNC_STATIC:
     70		return "static";
     71	case BTF_FUNC_GLOBAL:
     72		return "global";
     73	case BTF_FUNC_EXTERN:
     74		return "extern";
     75	default:
     76		return "(unknown)";
     77	}
     78}
     79
     80static const char *btf_str(const struct btf *btf, __u32 off)
     81{
     82	if (!off)
     83		return "(anon)";
     84	return btf__str_by_offset(btf, off) ?: "(invalid)";
     85}
     86
     87int fprintf_btf_type_raw(FILE *out, const struct btf *btf, __u32 id)
     88{
     89	const struct btf_type *t;
     90	int kind, i;
     91	__u32 vlen;
     92
     93	t = btf__type_by_id(btf, id);
     94	if (!t)
     95		return -EINVAL;
     96
     97	vlen = btf_vlen(t);
     98	kind = btf_kind(t);
     99
    100	fprintf(out, "[%u] %s '%s'", id, btf_kind_str(kind), btf_str(btf, t->name_off));
    101
    102	switch (kind) {
    103	case BTF_KIND_INT:
    104		fprintf(out, " size=%u bits_offset=%u nr_bits=%u encoding=%s",
    105			t->size, btf_int_offset(t), btf_int_bits(t),
    106			btf_int_enc_str(btf_int_encoding(t)));
    107		break;
    108	case BTF_KIND_PTR:
    109	case BTF_KIND_CONST:
    110	case BTF_KIND_VOLATILE:
    111	case BTF_KIND_RESTRICT:
    112	case BTF_KIND_TYPEDEF:
    113	case BTF_KIND_TYPE_TAG:
    114		fprintf(out, " type_id=%u", t->type);
    115		break;
    116	case BTF_KIND_ARRAY: {
    117		const struct btf_array *arr = btf_array(t);
    118
    119		fprintf(out, " type_id=%u index_type_id=%u nr_elems=%u",
    120			arr->type, arr->index_type, arr->nelems);
    121		break;
    122	}
    123	case BTF_KIND_STRUCT:
    124	case BTF_KIND_UNION: {
    125		const struct btf_member *m = btf_members(t);
    126
    127		fprintf(out, " size=%u vlen=%u", t->size, vlen);
    128		for (i = 0; i < vlen; i++, m++) {
    129			__u32 bit_off, bit_sz;
    130
    131			bit_off = btf_member_bit_offset(t, i);
    132			bit_sz = btf_member_bitfield_size(t, i);
    133			fprintf(out, "\n\t'%s' type_id=%u bits_offset=%u",
    134				btf_str(btf, m->name_off), m->type, bit_off);
    135			if (bit_sz)
    136				fprintf(out, " bitfield_size=%u", bit_sz);
    137		}
    138		break;
    139	}
    140	case BTF_KIND_ENUM: {
    141		const struct btf_enum *v = btf_enum(t);
    142
    143		fprintf(out, " size=%u vlen=%u", t->size, vlen);
    144		for (i = 0; i < vlen; i++, v++) {
    145			fprintf(out, "\n\t'%s' val=%u",
    146				btf_str(btf, v->name_off), v->val);
    147		}
    148		break;
    149	}
    150	case BTF_KIND_FWD:
    151		fprintf(out, " fwd_kind=%s", btf_kflag(t) ? "union" : "struct");
    152		break;
    153	case BTF_KIND_FUNC:
    154		fprintf(out, " type_id=%u linkage=%s", t->type, btf_func_linkage_str(t));
    155		break;
    156	case BTF_KIND_FUNC_PROTO: {
    157		const struct btf_param *p = btf_params(t);
    158
    159		fprintf(out, " ret_type_id=%u vlen=%u", t->type, vlen);
    160		for (i = 0; i < vlen; i++, p++) {
    161			fprintf(out, "\n\t'%s' type_id=%u",
    162				btf_str(btf, p->name_off), p->type);
    163		}
    164		break;
    165	}
    166	case BTF_KIND_VAR:
    167		fprintf(out, " type_id=%u, linkage=%s",
    168			t->type, btf_var_linkage_str(btf_var(t)->linkage));
    169		break;
    170	case BTF_KIND_DATASEC: {
    171		const struct btf_var_secinfo *v = btf_var_secinfos(t);
    172
    173		fprintf(out, " size=%u vlen=%u", t->size, vlen);
    174		for (i = 0; i < vlen; i++, v++) {
    175			fprintf(out, "\n\ttype_id=%u offset=%u size=%u",
    176				v->type, v->offset, v->size);
    177		}
    178		break;
    179	}
    180	case BTF_KIND_FLOAT:
    181		fprintf(out, " size=%u", t->size);
    182		break;
    183	case BTF_KIND_DECL_TAG:
    184		fprintf(out, " type_id=%u component_idx=%d",
    185			t->type, btf_decl_tag(t)->component_idx);
    186		break;
    187	default:
    188		break;
    189	}
    190
    191	return 0;
    192}
    193
    194/* Print raw BTF type dump into a local buffer and return string pointer back.
    195 * Buffer *will* be overwritten by subsequent btf_type_raw_dump() calls
    196 */
    197const char *btf_type_raw_dump(const struct btf *btf, int type_id)
    198{
    199	static char buf[16 * 1024];
    200	FILE *buf_file;
    201
    202	buf_file = fmemopen(buf, sizeof(buf) - 1, "w");
    203	if (!buf_file) {
    204		fprintf(stderr, "Failed to open memstream: %d\n", errno);
    205		return NULL;
    206	}
    207
    208	fprintf_btf_type_raw(buf_file, btf, type_id);
    209	fflush(buf_file);
    210	fclose(buf_file);
    211
    212	return buf;
    213}
    214
    215int btf_validate_raw(struct btf *btf, int nr_types, const char *exp_types[])
    216{
    217	int i;
    218	bool ok = true;
    219
    220	ASSERT_EQ(btf__type_cnt(btf) - 1, nr_types, "btf_nr_types");
    221
    222	for (i = 1; i <= nr_types; i++) {
    223		if (!ASSERT_STREQ(btf_type_raw_dump(btf, i), exp_types[i - 1], "raw_dump"))
    224			ok = false;
    225	}
    226
    227	return ok;
    228}
    229
    230static void btf_dump_printf(void *ctx, const char *fmt, va_list args)
    231{
    232	vfprintf(ctx, fmt, args);
    233}
    234
    235/* Print BTF-to-C dump into a local buffer and return string pointer back.
    236 * Buffer *will* be overwritten by subsequent btf_type_raw_dump() calls
    237 */
    238const char *btf_type_c_dump(const struct btf *btf)
    239{
    240	static char buf[16 * 1024];
    241	FILE *buf_file;
    242	struct btf_dump *d = NULL;
    243	int err, i;
    244
    245	buf_file = fmemopen(buf, sizeof(buf) - 1, "w");
    246	if (!buf_file) {
    247		fprintf(stderr, "Failed to open memstream: %d\n", errno);
    248		return NULL;
    249	}
    250
    251	d = btf_dump__new(btf, btf_dump_printf, buf_file, NULL);
    252	if (libbpf_get_error(d)) {
    253		fprintf(stderr, "Failed to create btf_dump instance: %ld\n", libbpf_get_error(d));
    254		goto err_out;
    255	}
    256
    257	for (i = 1; i < btf__type_cnt(btf); i++) {
    258		err = btf_dump__dump_type(d, i);
    259		if (err) {
    260			fprintf(stderr, "Failed to dump type [%d]: %d\n", i, err);
    261			goto err_out;
    262		}
    263	}
    264
    265	btf_dump__free(d);
    266	fflush(buf_file);
    267	fclose(buf_file);
    268	return buf;
    269err_out:
    270	btf_dump__free(d);
    271	fclose(buf_file);
    272	return NULL;
    273}