brintos

brintos / linux-shallow public Read only

0
0
Text · 13.9 KiB · d9024c7 Raw
454 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2020 Facebook */3#include <test_progs.h>4#include <bpf/btf.h>5#include "btf_helpers.h"6 7static void test_split_simple() {8	const struct btf_type *t;9	struct btf *btf1, *btf2;10	int str_off, err;11 12	btf1 = btf__new_empty();13	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))14		return;15 16	btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */17 18	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);	/* [1] int */19	btf__add_ptr(btf1, 1);				/* [2] ptr to int */20	btf__add_struct(btf1, "s1", 4);			/* [3] struct s1 { */21	btf__add_field(btf1, "f1", 1, 0, 0);		/*      int f1; */22							/* } */23 24	VALIDATE_RAW_BTF(25		btf1,26		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",27		"[2] PTR '(anon)' type_id=1",28		"[3] STRUCT 's1' size=4 vlen=1\n"29		"\t'f1' type_id=1 bits_offset=0");30 31	ASSERT_STREQ(btf_type_c_dump(btf1), "\32struct s1 {\n\33	int f1;\n\34};\n\n", "c_dump");35 36	btf2 = btf__new_empty_split(btf1);37	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))38		goto cleanup;39 40	/* pointer size should be "inherited" from main BTF */41	ASSERT_EQ(btf__pointer_size(btf2), 8, "inherit_ptr_sz");42 43	str_off = btf__find_str(btf2, "int");44	ASSERT_NEQ(str_off, -ENOENT, "str_int_missing");45 46	t = btf__type_by_id(btf2, 1);47	if (!ASSERT_OK_PTR(t, "int_type"))48		goto cleanup;49	ASSERT_EQ(btf_is_int(t), true, "int_kind");50	ASSERT_STREQ(btf__str_by_offset(btf2, t->name_off), "int", "int_name");51 52	btf__add_struct(btf2, "s2", 16);		/* [4] struct s2 {	*/53	btf__add_field(btf2, "f1", 6, 0, 0);		/*      struct s1 f1;	*/54	btf__add_field(btf2, "f2", 5, 32, 0);		/*      int f2;		*/55	btf__add_field(btf2, "f3", 2, 64, 0);		/*      int *f3;	*/56							/* } */57 58	/* duplicated int */59	btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);	/* [5] int */60 61	/* duplicated struct s1 */62	btf__add_struct(btf2, "s1", 4);			/* [6] struct s1 { */63	btf__add_field(btf2, "f1", 5, 0, 0);		/*      int f1; */64							/* } */65 66	VALIDATE_RAW_BTF(67		btf2,68		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",69		"[2] PTR '(anon)' type_id=1",70		"[3] STRUCT 's1' size=4 vlen=1\n"71		"\t'f1' type_id=1 bits_offset=0",72		"[4] STRUCT 's2' size=16 vlen=3\n"73		"\t'f1' type_id=6 bits_offset=0\n"74		"\t'f2' type_id=5 bits_offset=32\n"75		"\t'f3' type_id=2 bits_offset=64",76		"[5] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",77		"[6] STRUCT 's1' size=4 vlen=1\n"78		"\t'f1' type_id=5 bits_offset=0");79 80	ASSERT_STREQ(btf_type_c_dump(btf2), "\81struct s1 {\n\82	int f1;\n\83};\n\84\n\85struct s1___2 {\n\86	int f1;\n\87};\n\88\n\89struct s2 {\n\90	struct s1___2 f1;\n\91	int f2;\n\92	int *f3;\n\93};\n\n", "c_dump");94 95	err = btf__dedup(btf2, NULL);96	if (!ASSERT_OK(err, "btf_dedup"))97		goto cleanup;98 99	VALIDATE_RAW_BTF(100		btf2,101		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",102		"[2] PTR '(anon)' type_id=1",103		"[3] STRUCT 's1' size=4 vlen=1\n"104		"\t'f1' type_id=1 bits_offset=0",105		"[4] STRUCT 's2' size=16 vlen=3\n"106		"\t'f1' type_id=3 bits_offset=0\n"107		"\t'f2' type_id=1 bits_offset=32\n"108		"\t'f3' type_id=2 bits_offset=64");109 110	ASSERT_STREQ(btf_type_c_dump(btf2), "\111struct s1 {\n\112	int f1;\n\113};\n\114\n\115struct s2 {\n\116	struct s1 f1;\n\117	int f2;\n\118	int *f3;\n\119};\n\n", "c_dump");120 121cleanup:122	btf__free(btf2);123	btf__free(btf1);124}125 126static void test_split_fwd_resolve() {127	struct btf *btf1, *btf2;128	int err;129 130	btf1 = btf__new_empty();131	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))132		return;133 134	btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */135 136	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);	/* [1] int */137	btf__add_ptr(btf1, 4);				/* [2] ptr to struct s1 */138	btf__add_ptr(btf1, 5);				/* [3] ptr to struct s2 */139	btf__add_struct(btf1, "s1", 16);		/* [4] struct s1 { */140	btf__add_field(btf1, "f1", 2, 0, 0);		/*      struct s1 *f1; */141	btf__add_field(btf1, "f2", 3, 64, 0);		/*      struct s2 *f2; */142							/* } */143	btf__add_struct(btf1, "s2", 4);			/* [5] struct s2 { */144	btf__add_field(btf1, "f1", 1, 0, 0);		/*      int f1; */145							/* } */146	/* keep this not a part of type the graph to test btf_dedup_resolve_fwds */147	btf__add_struct(btf1, "s3", 4);                 /* [6] struct s3 { */148	btf__add_field(btf1, "f1", 1, 0, 0);		/*      int f1; */149							/* } */150 151	VALIDATE_RAW_BTF(152		btf1,153		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",154		"[2] PTR '(anon)' type_id=4",155		"[3] PTR '(anon)' type_id=5",156		"[4] STRUCT 's1' size=16 vlen=2\n"157		"\t'f1' type_id=2 bits_offset=0\n"158		"\t'f2' type_id=3 bits_offset=64",159		"[5] STRUCT 's2' size=4 vlen=1\n"160		"\t'f1' type_id=1 bits_offset=0",161		"[6] STRUCT 's3' size=4 vlen=1\n"162		"\t'f1' type_id=1 bits_offset=0");163 164	btf2 = btf__new_empty_split(btf1);165	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))166		goto cleanup;167 168	btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);	/* [7] int */169	btf__add_ptr(btf2, 11);				/* [8] ptr to struct s1 */170	btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);	/* [9] fwd for struct s2 */171	btf__add_ptr(btf2, 9);				/* [10] ptr to fwd struct s2 */172	btf__add_struct(btf2, "s1", 16);		/* [11] struct s1 { */173	btf__add_field(btf2, "f1", 8, 0, 0);		/*      struct s1 *f1; */174	btf__add_field(btf2, "f2", 10, 64, 0);		/*      struct s2 *f2; */175							/* } */176	btf__add_fwd(btf2, "s3", BTF_FWD_STRUCT);	/* [12] fwd for struct s3 */177	btf__add_ptr(btf2, 12);				/* [13] ptr to struct s1 */178 179	VALIDATE_RAW_BTF(180		btf2,181		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",182		"[2] PTR '(anon)' type_id=4",183		"[3] PTR '(anon)' type_id=5",184		"[4] STRUCT 's1' size=16 vlen=2\n"185		"\t'f1' type_id=2 bits_offset=0\n"186		"\t'f2' type_id=3 bits_offset=64",187		"[5] STRUCT 's2' size=4 vlen=1\n"188		"\t'f1' type_id=1 bits_offset=0",189		"[6] STRUCT 's3' size=4 vlen=1\n"190		"\t'f1' type_id=1 bits_offset=0",191		"[7] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",192		"[8] PTR '(anon)' type_id=11",193		"[9] FWD 's2' fwd_kind=struct",194		"[10] PTR '(anon)' type_id=9",195		"[11] STRUCT 's1' size=16 vlen=2\n"196		"\t'f1' type_id=8 bits_offset=0\n"197		"\t'f2' type_id=10 bits_offset=64",198		"[12] FWD 's3' fwd_kind=struct",199		"[13] PTR '(anon)' type_id=12");200 201	err = btf__dedup(btf2, NULL);202	if (!ASSERT_OK(err, "btf_dedup"))203		goto cleanup;204 205	VALIDATE_RAW_BTF(206		btf2,207		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",208		"[2] PTR '(anon)' type_id=4",209		"[3] PTR '(anon)' type_id=5",210		"[4] STRUCT 's1' size=16 vlen=2\n"211		"\t'f1' type_id=2 bits_offset=0\n"212		"\t'f2' type_id=3 bits_offset=64",213		"[5] STRUCT 's2' size=4 vlen=1\n"214		"\t'f1' type_id=1 bits_offset=0",215		"[6] STRUCT 's3' size=4 vlen=1\n"216		"\t'f1' type_id=1 bits_offset=0",217		"[7] PTR '(anon)' type_id=6");218 219cleanup:220	btf__free(btf2);221	btf__free(btf1);222}223 224static void test_split_struct_duped() {225	struct btf *btf1, *btf2;226	int err;227 228	btf1 = btf__new_empty();229	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))230		return;231 232	btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */233 234	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);	/* [1] int */235	btf__add_ptr(btf1, 5);				/* [2] ptr to struct s1 */236	btf__add_fwd(btf1, "s2", BTF_FWD_STRUCT);	/* [3] fwd for struct s2 */237	btf__add_ptr(btf1, 3);				/* [4] ptr to fwd struct s2 */238	btf__add_struct(btf1, "s1", 16);		/* [5] struct s1 { */239	btf__add_field(btf1, "f1", 2, 0, 0);		/*      struct s1 *f1; */240	btf__add_field(btf1, "f2", 4, 64, 0);		/*      struct s2 *f2; */241							/* } */242 243	VALIDATE_RAW_BTF(244		btf1,245		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",246		"[2] PTR '(anon)' type_id=5",247		"[3] FWD 's2' fwd_kind=struct",248		"[4] PTR '(anon)' type_id=3",249		"[5] STRUCT 's1' size=16 vlen=2\n"250		"\t'f1' type_id=2 bits_offset=0\n"251		"\t'f2' type_id=4 bits_offset=64");252 253	btf2 = btf__new_empty_split(btf1);254	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))255		goto cleanup;256 257	btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);	/* [6] int */258	btf__add_ptr(btf2, 10);				/* [7] ptr to struct s1 */259	btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);	/* [8] fwd for struct s2 */260	btf__add_ptr(btf2, 11);				/* [9] ptr to struct s2 */261	btf__add_struct(btf2, "s1", 16);		/* [10] struct s1 { */262	btf__add_field(btf2, "f1", 7, 0, 0);		/*      struct s1 *f1; */263	btf__add_field(btf2, "f2", 9, 64, 0);		/*      struct s2 *f2; */264							/* } */265	btf__add_struct(btf2, "s2", 40);		/* [11] struct s2 {	*/266	btf__add_field(btf2, "f1", 7, 0, 0);		/*      struct s1 *f1;	*/267	btf__add_field(btf2, "f2", 9, 64, 0);		/*      struct s2 *f2;	*/268	btf__add_field(btf2, "f3", 6, 128, 0);		/*      int f3;		*/269	btf__add_field(btf2, "f4", 10, 192, 0);		/*      struct s1 f4;	*/270							/* } */271	btf__add_ptr(btf2, 8);				/* [12] ptr to fwd struct s2 */272	btf__add_struct(btf2, "s3", 8);			/* [13] struct s3 { */273	btf__add_field(btf2, "f1", 12, 0, 0);		/*      struct s2 *f1; (fwd) */274							/* } */275 276	VALIDATE_RAW_BTF(277		btf2,278		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",279		"[2] PTR '(anon)' type_id=5",280		"[3] FWD 's2' fwd_kind=struct",281		"[4] PTR '(anon)' type_id=3",282		"[5] STRUCT 's1' size=16 vlen=2\n"283		"\t'f1' type_id=2 bits_offset=0\n"284		"\t'f2' type_id=4 bits_offset=64",285		"[6] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",286		"[7] PTR '(anon)' type_id=10",287		"[8] FWD 's2' fwd_kind=struct",288		"[9] PTR '(anon)' type_id=11",289		"[10] STRUCT 's1' size=16 vlen=2\n"290		"\t'f1' type_id=7 bits_offset=0\n"291		"\t'f2' type_id=9 bits_offset=64",292		"[11] STRUCT 's2' size=40 vlen=4\n"293		"\t'f1' type_id=7 bits_offset=0\n"294		"\t'f2' type_id=9 bits_offset=64\n"295		"\t'f3' type_id=6 bits_offset=128\n"296		"\t'f4' type_id=10 bits_offset=192",297		"[12] PTR '(anon)' type_id=8",298		"[13] STRUCT 's3' size=8 vlen=1\n"299		"\t'f1' type_id=12 bits_offset=0");300 301	err = btf__dedup(btf2, NULL);302	if (!ASSERT_OK(err, "btf_dedup"))303		goto cleanup;304 305	VALIDATE_RAW_BTF(306		btf2,307		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",308		"[2] PTR '(anon)' type_id=5",309		"[3] FWD 's2' fwd_kind=struct",310		"[4] PTR '(anon)' type_id=3",311		"[5] STRUCT 's1' size=16 vlen=2\n"312		"\t'f1' type_id=2 bits_offset=0\n"313		"\t'f2' type_id=4 bits_offset=64",314		"[6] PTR '(anon)' type_id=8",315		"[7] PTR '(anon)' type_id=9",316		"[8] STRUCT 's1' size=16 vlen=2\n"317		"\t'f1' type_id=6 bits_offset=0\n"318		"\t'f2' type_id=7 bits_offset=64",319		"[9] STRUCT 's2' size=40 vlen=4\n"320		"\t'f1' type_id=6 bits_offset=0\n"321		"\t'f2' type_id=7 bits_offset=64\n"322		"\t'f3' type_id=1 bits_offset=128\n"323		"\t'f4' type_id=8 bits_offset=192",324		"[10] STRUCT 's3' size=8 vlen=1\n"325		"\t'f1' type_id=7 bits_offset=0");326 327cleanup:328	btf__free(btf2);329	btf__free(btf1);330}331 332static void btf_add_dup_struct_in_cu(struct btf *btf, int start_id)333{334#define ID(n) (start_id + n)335	btf__set_pointer_size(btf, 8); /* enforce 64-bit arch */336 337	btf__add_int(btf, "int", 4, BTF_INT_SIGNED);    /* [1] int */338 339	btf__add_struct(btf, "s", 8);                   /* [2] struct s { */340	btf__add_field(btf, "a", ID(3), 0, 0);          /*      struct anon a; */341	btf__add_field(btf, "b", ID(4), 0, 0);          /*      struct anon b; */342							/* } */343 344	btf__add_struct(btf, "(anon)", 8);              /* [3] struct anon { */345	btf__add_field(btf, "f1", ID(1), 0, 0);         /*      int f1; */346	btf__add_field(btf, "f2", ID(1), 32, 0);        /*      int f2; */347							/* } */348 349	btf__add_struct(btf, "(anon)", 8);              /* [4] struct anon { */350	btf__add_field(btf, "f1", ID(1), 0, 0);         /*      int f1; */351	btf__add_field(btf, "f2", ID(1), 32, 0);        /*      int f2; */352							/* } */353#undef ID354}355 356static void test_split_dup_struct_in_cu()357{358	struct btf *btf1, *btf2 = NULL;359	int err;360 361	/* generate the base data.. */362	btf1 = btf__new_empty();363	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))364		return;365 366	btf_add_dup_struct_in_cu(btf1, 0);367 368	VALIDATE_RAW_BTF(369			btf1,370			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",371			"[2] STRUCT 's' size=8 vlen=2\n"372			"\t'a' type_id=3 bits_offset=0\n"373			"\t'b' type_id=4 bits_offset=0",374			"[3] STRUCT '(anon)' size=8 vlen=2\n"375			"\t'f1' type_id=1 bits_offset=0\n"376			"\t'f2' type_id=1 bits_offset=32",377			"[4] STRUCT '(anon)' size=8 vlen=2\n"378			"\t'f1' type_id=1 bits_offset=0\n"379			"\t'f2' type_id=1 bits_offset=32");380 381	/* ..dedup them... */382	err = btf__dedup(btf1, NULL);383	if (!ASSERT_OK(err, "btf_dedup"))384		goto cleanup;385 386	VALIDATE_RAW_BTF(387			btf1,388			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",389			"[2] STRUCT 's' size=8 vlen=2\n"390			"\t'a' type_id=3 bits_offset=0\n"391			"\t'b' type_id=3 bits_offset=0",392			"[3] STRUCT '(anon)' size=8 vlen=2\n"393			"\t'f1' type_id=1 bits_offset=0\n"394			"\t'f2' type_id=1 bits_offset=32");395 396	/* and add the same data on top of it */397	btf2 = btf__new_empty_split(btf1);398	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))399		goto cleanup;400 401	btf_add_dup_struct_in_cu(btf2, 3);402 403	VALIDATE_RAW_BTF(404			btf2,405			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",406			"[2] STRUCT 's' size=8 vlen=2\n"407			"\t'a' type_id=3 bits_offset=0\n"408			"\t'b' type_id=3 bits_offset=0",409			"[3] STRUCT '(anon)' size=8 vlen=2\n"410			"\t'f1' type_id=1 bits_offset=0\n"411			"\t'f2' type_id=1 bits_offset=32",412			"[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",413			"[5] STRUCT 's' size=8 vlen=2\n"414			"\t'a' type_id=6 bits_offset=0\n"415			"\t'b' type_id=7 bits_offset=0",416			"[6] STRUCT '(anon)' size=8 vlen=2\n"417			"\t'f1' type_id=4 bits_offset=0\n"418			"\t'f2' type_id=4 bits_offset=32",419			"[7] STRUCT '(anon)' size=8 vlen=2\n"420			"\t'f1' type_id=4 bits_offset=0\n"421			"\t'f2' type_id=4 bits_offset=32");422 423	err = btf__dedup(btf2, NULL);424	if (!ASSERT_OK(err, "btf_dedup"))425		goto cleanup;426 427	/* after dedup it should match the original data */428	VALIDATE_RAW_BTF(429			btf2,430			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",431			"[2] STRUCT 's' size=8 vlen=2\n"432			"\t'a' type_id=3 bits_offset=0\n"433			"\t'b' type_id=3 bits_offset=0",434			"[3] STRUCT '(anon)' size=8 vlen=2\n"435			"\t'f1' type_id=1 bits_offset=0\n"436			"\t'f2' type_id=1 bits_offset=32");437 438cleanup:439	btf__free(btf2);440	btf__free(btf1);441}442 443void test_btf_dedup_split()444{445	if (test__start_subtest("split_simple"))446		test_split_simple();447	if (test__start_subtest("split_struct_duped"))448		test_split_struct_duped();449	if (test__start_subtest("split_fwd_resolve"))450		test_split_fwd_resolve();451	if (test__start_subtest("split_dup_struct_in_cu"))452		test_split_dup_struct_in_cu();453}454