brintos

brintos / linux-shallow public Read only

0
0
Text · 21.9 KiB · ca84726 Raw
621 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2024, Oracle and/or its affiliates. */3 4#include <test_progs.h>5#include <bpf/btf.h>6#include "btf_helpers.h"7 8/* Fabricate base, split BTF with references to base types needed; then create9 * split BTF with distilled base BTF and ensure expectations are met:10 *  - only referenced base types from split BTF are present11 *  - struct/union/enum are represented as empty unless anonymous, when they12 *    are represented in full in split BTF13 */14static void test_distilled_base(void)15{16	struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;17 18	btf1 = btf__new_empty();19	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))20		return;21 22	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);	/* [1] int */23	btf__add_ptr(btf1, 1);				/* [2] ptr to int */24	btf__add_struct(btf1, "s1", 8);			/* [3] struct s1 { */25	btf__add_field(btf1, "f1", 2, 0, 0);		/*      int *f1; */26							/* } */27	btf__add_struct(btf1, "", 12);			/* [4] struct { */28	btf__add_field(btf1, "f1", 1, 0, 0);		/*	int f1; */29	btf__add_field(btf1, "f2", 3, 32, 0);		/*	struct s1 f2; */30							/* } */31	btf__add_int(btf1, "unsigned int", 4, 0);	/* [5] unsigned int */32	btf__add_union(btf1, "u1", 12);			/* [6] union u1 { */33	btf__add_field(btf1, "f1", 1, 0, 0);		/*	int f1; */34	btf__add_field(btf1, "f2", 2, 0, 0);		/*	int *f2; */35							/* } */36	btf__add_union(btf1, "", 4);			/* [7] union { */37	btf__add_field(btf1, "f1", 1, 0, 0);		/*	int f1; */38							/* } */39	btf__add_enum(btf1, "e1", 4);			/* [8] enum e1 { */40	btf__add_enum_value(btf1, "v1", 1);		/*	v1 = 1; */41							/* } */42	btf__add_enum(btf1, "", 4);			/* [9] enum { */43	btf__add_enum_value(btf1, "av1", 2);		/*	av1 = 2; */44							/* } */45	btf__add_enum64(btf1, "e641", 8, true);		/* [10] enum64 { */46	btf__add_enum64_value(btf1, "v1", 1024);	/*	v1 = 1024; */47							/* } */48	btf__add_enum64(btf1, "", 8, true);		/* [11] enum64 { */49	btf__add_enum64_value(btf1, "v1", 1025);	/*	v1 = 1025; */50							/* } */51	btf__add_struct(btf1, "unneeded", 4);		/* [12] struct unneeded { */52	btf__add_field(btf1, "f1", 1, 0, 0);		/*	int f1; */53							/* } */54	btf__add_struct(btf1, "embedded", 4);		/* [13] struct embedded { */55	btf__add_field(btf1, "f1", 1, 0, 0);		/*	int f1; */56							/* } */57	btf__add_func_proto(btf1, 1);			/* [14] int (*)(int *p1); */58	btf__add_func_param(btf1, "p1", 1);59 60	btf__add_array(btf1, 1, 1, 3);			/* [15] int [3]; */61 62	btf__add_struct(btf1, "from_proto", 4);		/* [16] struct from_proto { */63	btf__add_field(btf1, "f1", 1, 0, 0);		/*	int f1; */64							/* } */65	btf__add_union(btf1, "u1", 4);			/* [17] union u1 { */66	btf__add_field(btf1, "f1", 1, 0, 0);		/*	 int f1; */67							/* } */68	VALIDATE_RAW_BTF(69		btf1,70		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",71		"[2] PTR '(anon)' type_id=1",72		"[3] STRUCT 's1' size=8 vlen=1\n"73		"\t'f1' type_id=2 bits_offset=0",74		"[4] STRUCT '(anon)' size=12 vlen=2\n"75		"\t'f1' type_id=1 bits_offset=0\n"76		"\t'f2' type_id=3 bits_offset=32",77		"[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",78		"[6] UNION 'u1' size=12 vlen=2\n"79		"\t'f1' type_id=1 bits_offset=0\n"80		"\t'f2' type_id=2 bits_offset=0",81		"[7] UNION '(anon)' size=4 vlen=1\n"82		"\t'f1' type_id=1 bits_offset=0",83		"[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"84		"\t'v1' val=1",85		"[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"86		"\t'av1' val=2",87		"[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"88		"\t'v1' val=1024",89		"[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"90		"\t'v1' val=1025",91		"[12] STRUCT 'unneeded' size=4 vlen=1\n"92		"\t'f1' type_id=1 bits_offset=0",93		"[13] STRUCT 'embedded' size=4 vlen=1\n"94		"\t'f1' type_id=1 bits_offset=0",95		"[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"96		"\t'p1' type_id=1",97		"[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",98		"[16] STRUCT 'from_proto' size=4 vlen=1\n"99		"\t'f1' type_id=1 bits_offset=0",100		"[17] UNION 'u1' size=4 vlen=1\n"101		"\t'f1' type_id=1 bits_offset=0");102 103	btf2 = btf__new_empty_split(btf1);104	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))105		goto cleanup;106 107	btf__add_ptr(btf2, 3);				/* [18] ptr to struct s1 */108	/* add ptr to struct anon */109	btf__add_ptr(btf2, 4);				/* [19] ptr to struct (anon) */110	btf__add_const(btf2, 6);			/* [20] const union u1 */111	btf__add_restrict(btf2, 7);			/* [21] restrict union (anon) */112	btf__add_volatile(btf2, 8);			/* [22] volatile enum e1 */113	btf__add_typedef(btf2, "et", 9);		/* [23] typedef enum (anon) */114	btf__add_const(btf2, 10);			/* [24] const enum64 e641 */115	btf__add_ptr(btf2, 11);				/* [25] restrict enum64 (anon) */116	btf__add_struct(btf2, "with_embedded", 4);	/* [26] struct with_embedded { */117	btf__add_field(btf2, "f1", 13, 0, 0);		/*	struct embedded f1; */118							/* } */119	btf__add_func(btf2, "fn", BTF_FUNC_STATIC, 14);	/* [27] int fn(int p1); */120	btf__add_typedef(btf2, "arraytype", 15);	/* [28] typedef int[3] foo; */121	btf__add_func_proto(btf2, 1);			/* [29] int (*)(struct from proto p1); */122	btf__add_func_param(btf2, "p1", 16);123 124	VALIDATE_RAW_BTF(125		btf2,126		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",127		"[2] PTR '(anon)' type_id=1",128		"[3] STRUCT 's1' size=8 vlen=1\n"129		"\t'f1' type_id=2 bits_offset=0",130		"[4] STRUCT '(anon)' size=12 vlen=2\n"131		"\t'f1' type_id=1 bits_offset=0\n"132		"\t'f2' type_id=3 bits_offset=32",133		"[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",134		"[6] UNION 'u1' size=12 vlen=2\n"135		"\t'f1' type_id=1 bits_offset=0\n"136		"\t'f2' type_id=2 bits_offset=0",137		"[7] UNION '(anon)' size=4 vlen=1\n"138		"\t'f1' type_id=1 bits_offset=0",139		"[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"140		"\t'v1' val=1",141		"[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"142		"\t'av1' val=2",143		"[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"144		"\t'v1' val=1024",145		"[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"146		"\t'v1' val=1025",147		"[12] STRUCT 'unneeded' size=4 vlen=1\n"148		"\t'f1' type_id=1 bits_offset=0",149		"[13] STRUCT 'embedded' size=4 vlen=1\n"150		"\t'f1' type_id=1 bits_offset=0",151		"[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"152		"\t'p1' type_id=1",153		"[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",154		"[16] STRUCT 'from_proto' size=4 vlen=1\n"155		"\t'f1' type_id=1 bits_offset=0",156		"[17] UNION 'u1' size=4 vlen=1\n"157		"\t'f1' type_id=1 bits_offset=0",158		"[18] PTR '(anon)' type_id=3",159		"[19] PTR '(anon)' type_id=4",160		"[20] CONST '(anon)' type_id=6",161		"[21] RESTRICT '(anon)' type_id=7",162		"[22] VOLATILE '(anon)' type_id=8",163		"[23] TYPEDEF 'et' type_id=9",164		"[24] CONST '(anon)' type_id=10",165		"[25] PTR '(anon)' type_id=11",166		"[26] STRUCT 'with_embedded' size=4 vlen=1\n"167		"\t'f1' type_id=13 bits_offset=0",168		"[27] FUNC 'fn' type_id=14 linkage=static",169		"[28] TYPEDEF 'arraytype' type_id=15",170		"[29] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"171		"\t'p1' type_id=16");172 173	if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),174		       "distilled_base") ||175	    !ASSERT_OK_PTR(btf3, "distilled_base") ||176	    !ASSERT_OK_PTR(btf4, "distilled_split") ||177	    !ASSERT_EQ(8, btf__type_cnt(btf3), "distilled_base_type_cnt"))178		goto cleanup;179 180	VALIDATE_RAW_BTF(181		btf4,182		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",183		"[2] STRUCT 's1' size=8 vlen=0",184		"[3] UNION 'u1' size=12 vlen=0",185		"[4] ENUM 'e1' encoding=UNSIGNED size=4 vlen=0",186		"[5] ENUM 'e641' encoding=UNSIGNED size=8 vlen=0",187		"[6] STRUCT 'embedded' size=4 vlen=0",188		"[7] STRUCT 'from_proto' size=4 vlen=0",189		/* split BTF; these types should match split BTF above from 17-28, with190		 * updated type id references191		 */192		"[8] PTR '(anon)' type_id=2",193		"[9] PTR '(anon)' type_id=20",194		"[10] CONST '(anon)' type_id=3",195		"[11] RESTRICT '(anon)' type_id=21",196		"[12] VOLATILE '(anon)' type_id=4",197		"[13] TYPEDEF 'et' type_id=22",198		"[14] CONST '(anon)' type_id=5",199		"[15] PTR '(anon)' type_id=23",200		"[16] STRUCT 'with_embedded' size=4 vlen=1\n"201		"\t'f1' type_id=6 bits_offset=0",202		"[17] FUNC 'fn' type_id=24 linkage=static",203		"[18] TYPEDEF 'arraytype' type_id=25",204		"[19] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"205		"\t'p1' type_id=7",206		/* split BTF types added from original base BTF below */207		"[20] STRUCT '(anon)' size=12 vlen=2\n"208		"\t'f1' type_id=1 bits_offset=0\n"209		"\t'f2' type_id=2 bits_offset=32",210		"[21] UNION '(anon)' size=4 vlen=1\n"211		"\t'f1' type_id=1 bits_offset=0",212		"[22] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"213		"\t'av1' val=2",214		"[23] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"215		"\t'v1' val=1025",216		"[24] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"217		"\t'p1' type_id=1",218		"[25] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3");219 220	if (!ASSERT_EQ(btf__relocate(btf4, btf1), 0, "relocate_split"))221		goto cleanup;222 223	VALIDATE_RAW_BTF(224		btf4,225		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",226		"[2] PTR '(anon)' type_id=1",227		"[3] STRUCT 's1' size=8 vlen=1\n"228		"\t'f1' type_id=2 bits_offset=0",229		"[4] STRUCT '(anon)' size=12 vlen=2\n"230		"\t'f1' type_id=1 bits_offset=0\n"231		"\t'f2' type_id=3 bits_offset=32",232		"[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",233		"[6] UNION 'u1' size=12 vlen=2\n"234		"\t'f1' type_id=1 bits_offset=0\n"235		"\t'f2' type_id=2 bits_offset=0",236		"[7] UNION '(anon)' size=4 vlen=1\n"237		"\t'f1' type_id=1 bits_offset=0",238		"[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"239		"\t'v1' val=1",240		"[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"241		"\t'av1' val=2",242		"[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"243		"\t'v1' val=1024",244		"[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"245		"\t'v1' val=1025",246		"[12] STRUCT 'unneeded' size=4 vlen=1\n"247		"\t'f1' type_id=1 bits_offset=0",248		"[13] STRUCT 'embedded' size=4 vlen=1\n"249		"\t'f1' type_id=1 bits_offset=0",250		"[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"251		"\t'p1' type_id=1",252		"[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",253		"[16] STRUCT 'from_proto' size=4 vlen=1\n"254		"\t'f1' type_id=1 bits_offset=0",255		"[17] UNION 'u1' size=4 vlen=1\n"256		"\t'f1' type_id=1 bits_offset=0",257		"[18] PTR '(anon)' type_id=3",258		"[19] PTR '(anon)' type_id=30",259		"[20] CONST '(anon)' type_id=6",260		"[21] RESTRICT '(anon)' type_id=31",261		"[22] VOLATILE '(anon)' type_id=8",262		"[23] TYPEDEF 'et' type_id=32",263		"[24] CONST '(anon)' type_id=10",264		"[25] PTR '(anon)' type_id=33",265		"[26] STRUCT 'with_embedded' size=4 vlen=1\n"266		"\t'f1' type_id=13 bits_offset=0",267		"[27] FUNC 'fn' type_id=34 linkage=static",268		"[28] TYPEDEF 'arraytype' type_id=35",269		"[29] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"270		"\t'p1' type_id=16",271		/* below here are (duplicate) anon base types added by distill272		 * process to split BTF.273		 */274		"[30] STRUCT '(anon)' size=12 vlen=2\n"275		"\t'f1' type_id=1 bits_offset=0\n"276		"\t'f2' type_id=3 bits_offset=32",277		"[31] UNION '(anon)' size=4 vlen=1\n"278		"\t'f1' type_id=1 bits_offset=0",279		"[32] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"280		"\t'av1' val=2",281		"[33] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"282		"\t'v1' val=1025",283		"[34] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"284		"\t'p1' type_id=1",285		"[35] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3");286 287cleanup:288	btf__free(btf4);289	btf__free(btf3);290	btf__free(btf2);291	btf__free(btf1);292}293 294/* ensure we can cope with multiple types with the same name in295 * distilled base BTF.  In this case because sizes are different,296 * we can still disambiguate them.297 */298static void test_distilled_base_multi(void)299{300	struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;301 302	btf1 = btf__new_empty();303	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))304		return;305	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */306	btf__add_int(btf1, "int", 8, BTF_INT_SIGNED);	/* [2] int */307	VALIDATE_RAW_BTF(308		btf1,309		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",310		"[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");311	btf2 = btf__new_empty_split(btf1);312	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))313		goto cleanup;314	btf__add_ptr(btf2, 1);315	btf__add_const(btf2, 2);316	VALIDATE_RAW_BTF(317		btf2,318		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",319		"[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",320		"[3] PTR '(anon)' type_id=1",321		"[4] CONST '(anon)' type_id=2");322	if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),323		       "distilled_base") ||324	    !ASSERT_OK_PTR(btf3, "distilled_base") ||325	    !ASSERT_OK_PTR(btf4, "distilled_split") ||326	    !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))327		goto cleanup;328	VALIDATE_RAW_BTF(329		btf3,330		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",331		"[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");332	if (!ASSERT_EQ(btf__relocate(btf4, btf1), 0, "relocate_split"))333		goto cleanup;334 335	VALIDATE_RAW_BTF(336		btf4,337		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",338		"[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",339		"[3] PTR '(anon)' type_id=1",340		"[4] CONST '(anon)' type_id=2");341 342cleanup:343	btf__free(btf4);344	btf__free(btf3);345	btf__free(btf2);346	btf__free(btf1);347}348 349/* If a needed type is not present in the base BTF we wish to relocate350 * with, btf__relocate() should error our.351 */352static void test_distilled_base_missing_err(void)353{354	struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;355 356	btf1 = btf__new_empty();357	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))358		return;359	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */360	btf__add_int(btf1, "int", 8, BTF_INT_SIGNED);   /* [2] int */361	VALIDATE_RAW_BTF(362		btf1,363		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",364		"[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");365	btf2 = btf__new_empty_split(btf1);366	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))367		goto cleanup;368	btf__add_ptr(btf2, 1);369	btf__add_const(btf2, 2);370	VALIDATE_RAW_BTF(371		btf2,372		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",373		"[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",374		"[3] PTR '(anon)' type_id=1",375		"[4] CONST '(anon)' type_id=2");376	if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),377		       "distilled_base") ||378	    !ASSERT_OK_PTR(btf3, "distilled_base") ||379	    !ASSERT_OK_PTR(btf4, "distilled_split") ||380	    !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))381		goto cleanup;382	VALIDATE_RAW_BTF(383		btf3,384		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",385		"[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");386	btf5 = btf__new_empty();387	if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf"))388		return;389	btf__add_int(btf5, "int", 4, BTF_INT_SIGNED);   /* [1] int */390	VALIDATE_RAW_BTF(391		btf5,392		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");393	ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");394 395cleanup:396	btf__free(btf5);397	btf__free(btf4);398	btf__free(btf3);399	btf__free(btf2);400	btf__free(btf1);401}402 403/* With 2 types of same size in distilled base BTF, relocation should404 * fail as we have no means to choose between them.405 */406static void test_distilled_base_multi_err(void)407{408	struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;409 410	btf1 = btf__new_empty();411	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))412		return;413	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */414	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [2] int */415	VALIDATE_RAW_BTF(416		btf1,417		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",418		"[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");419	btf2 = btf__new_empty_split(btf1);420	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))421		goto cleanup;422	btf__add_ptr(btf2, 1);423	btf__add_const(btf2, 2);424	VALIDATE_RAW_BTF(425		btf2,426		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",427		"[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",428		"[3] PTR '(anon)' type_id=1",429		"[4] CONST '(anon)' type_id=2");430	if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),431		       "distilled_base") ||432	    !ASSERT_OK_PTR(btf3, "distilled_base") ||433	    !ASSERT_OK_PTR(btf4, "distilled_split") ||434	    !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))435		goto cleanup;436	VALIDATE_RAW_BTF(437		btf3,438		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",439		"[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");440	ASSERT_EQ(btf__relocate(btf4, btf1), -EINVAL, "relocate_split");441cleanup:442	btf__free(btf4);443	btf__free(btf3);444	btf__free(btf2);445	btf__free(btf1);446}447 448/* With 2 types of same size in base BTF, relocation should449 * fail as we have no means to choose between them.450 */451static void test_distilled_base_multi_err2(void)452{453	struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;454 455	btf1 = btf__new_empty();456	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))457		return;458	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */459	VALIDATE_RAW_BTF(460		btf1,461		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");462	btf2 = btf__new_empty_split(btf1);463	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))464		goto cleanup;465	btf__add_ptr(btf2, 1);466	VALIDATE_RAW_BTF(467		btf2,468		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",469		"[2] PTR '(anon)' type_id=1");470	if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),471		       "distilled_base") ||472	    !ASSERT_OK_PTR(btf3, "distilled_base") ||473	    !ASSERT_OK_PTR(btf4, "distilled_split") ||474	    !ASSERT_EQ(2, btf__type_cnt(btf3), "distilled_base_type_cnt"))475		goto cleanup;476	VALIDATE_RAW_BTF(477		btf3,478		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");479	btf5 = btf__new_empty();480	if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf"))481		return;482	btf__add_int(btf5, "int", 4, BTF_INT_SIGNED);   /* [1] int */483	btf__add_int(btf5, "int", 4, BTF_INT_SIGNED);   /* [2] int */484	VALIDATE_RAW_BTF(485		btf5,486		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",487		"[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");488	ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");489cleanup:490	btf__free(btf5);491	btf__free(btf4);492	btf__free(btf3);493	btf__free(btf2);494	btf__free(btf1);495}496 497/* create split reference BTF from vmlinux + split BTF with a few type references;498 * ensure the resultant split reference BTF is as expected, containing only types499 * needed to disambiguate references from split BTF.500 */501static void test_distilled_base_vmlinux(void)502{503	struct btf *split_btf = NULL, *vmlinux_btf = btf__load_vmlinux_btf();504	struct btf *split_dist = NULL, *base_dist = NULL;505	__s32 int_id, myint_id;506 507	if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux"))508		return;509	int_id = btf__find_by_name_kind(vmlinux_btf, "int", BTF_KIND_INT);510	if (!ASSERT_GT(int_id, 0, "find_int"))511		goto cleanup;512	split_btf = btf__new_empty_split(vmlinux_btf);513	if (!ASSERT_OK_PTR(split_btf, "new_split"))514		goto cleanup;515	myint_id = btf__add_typedef(split_btf, "myint", int_id);516	btf__add_ptr(split_btf, myint_id);517 518	if (!ASSERT_EQ(btf__distill_base(split_btf, &base_dist, &split_dist), 0,519		       "distill_vmlinux_base"))520		goto cleanup;521 522	if (!ASSERT_OK_PTR(split_dist, "split_distilled") ||523	    !ASSERT_OK_PTR(base_dist, "base_dist"))524		goto cleanup;525	VALIDATE_RAW_BTF(526		split_dist,527		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",528		"[2] TYPEDEF 'myint' type_id=1",529		"[3] PTR '(anon)' type_id=2");530 531cleanup:532	btf__free(split_dist);533	btf__free(base_dist);534	btf__free(split_btf);535	btf__free(vmlinux_btf);536}537 538/* Split and new base BTFs should inherit endianness from source BTF. */539static void test_distilled_endianness(void)540{541	struct btf *base = NULL, *split = NULL, *new_base = NULL, *new_split = NULL;542	struct btf *new_base1 = NULL, *new_split1 = NULL;543	enum btf_endianness inverse_endianness;544	const void *raw_data;545	__u32 size;546 547	base = btf__new_empty();548	if (!ASSERT_OK_PTR(base, "empty_main_btf"))549		return;550	inverse_endianness = btf__endianness(base) == BTF_LITTLE_ENDIAN ? BTF_BIG_ENDIAN551									: BTF_LITTLE_ENDIAN;552	btf__set_endianness(base, inverse_endianness);553	btf__add_int(base, "int", 4, BTF_INT_SIGNED);   /* [1] int */554	VALIDATE_RAW_BTF(555		base,556		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");557	split = btf__new_empty_split(base);558	if (!ASSERT_OK_PTR(split, "empty_split_btf"))559		goto cleanup;560	btf__add_ptr(split, 1);561	VALIDATE_RAW_BTF(562		split,563		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",564		"[2] PTR '(anon)' type_id=1");565	if (!ASSERT_EQ(0, btf__distill_base(split, &new_base, &new_split),566		       "distilled_base") ||567	    !ASSERT_OK_PTR(new_base, "distilled_base") ||568	    !ASSERT_OK_PTR(new_split, "distilled_split") ||569	    !ASSERT_EQ(2, btf__type_cnt(new_base), "distilled_base_type_cnt"))570		goto cleanup;571	VALIDATE_RAW_BTF(572		new_split,573		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",574		"[2] PTR '(anon)' type_id=1");575 576	raw_data = btf__raw_data(new_base, &size);577	if (!ASSERT_OK_PTR(raw_data, "btf__raw_data #1"))578		goto cleanup;579	new_base1 = btf__new(raw_data, size);580	if (!ASSERT_OK_PTR(new_base1, "new_base1 = btf__new()"))581		goto cleanup;582	raw_data = btf__raw_data(new_split, &size);583	if (!ASSERT_OK_PTR(raw_data, "btf__raw_data #2"))584		goto cleanup;585	new_split1 = btf__new_split(raw_data, size, new_base1);586	if (!ASSERT_OK_PTR(new_split1, "new_split1 = btf__new()"))587		goto cleanup;588 589	ASSERT_EQ(btf__endianness(new_base1), inverse_endianness, "new_base1 endianness");590	ASSERT_EQ(btf__endianness(new_split1), inverse_endianness, "new_split1 endianness");591	VALIDATE_RAW_BTF(592		new_split1,593		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",594		"[2] PTR '(anon)' type_id=1");595cleanup:596	btf__free(new_split1);597	btf__free(new_base1);598	btf__free(new_split);599	btf__free(new_base);600	btf__free(split);601	btf__free(base);602}603 604void test_btf_distill(void)605{606	if (test__start_subtest("distilled_base"))607		test_distilled_base();608	if (test__start_subtest("distilled_base_multi"))609		test_distilled_base_multi();610	if (test__start_subtest("distilled_base_missing_err"))611		test_distilled_base_missing_err();612	if (test__start_subtest("distilled_base_multi_err"))613		test_distilled_base_multi_err();614	if (test__start_subtest("distilled_base_multi_err2"))615		test_distilled_base_multi_err2();616	if (test__start_subtest("distilled_base_vmlinux"))617		test_distilled_base_vmlinux();618	if (test__start_subtest("distilled_endianness"))619		test_distilled_endianness();620}621