/* Fabricate base, split BTF with references to base types needed; then create * split BTF with distilled base BTF and ensure expectations are met: * - only referenced base types from split BTF are present * - struct/union/enum are represented as empty unless anonymous, when they * are represented in full in split BTF
*/ staticvoid test_distilled_base(void)
{ struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
btf1 = btf__new_empty(); if (!ASSERT_OK_PTR(btf1, "empty_main_btf")) return;
/* ensure we can cope with multiple types with the same name in * distilled base BTF. In this case because sizes are different, * we can still disambiguate them.
*/ staticvoid test_distilled_base_multi(void)
{ struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
btf1 = btf__new_empty(); if (!ASSERT_OK_PTR(btf1, "empty_main_btf")) return;
btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
btf__add_int(btf1, "int", 8, BTF_INT_SIGNED); /* [2] int */
VALIDATE_RAW_BTF(
btf1, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
btf2 = btf__new_empty_split(btf1); if (!ASSERT_OK_PTR(btf2, "empty_split_btf")) goto cleanup;
btf__add_ptr(btf2, 1);
btf__add_const(btf2, 2);
VALIDATE_RAW_BTF(
btf2, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED", "[3] PTR '(anon)' type_id=1", "[4] CONST '(anon)' type_id=2"); if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4), "distilled_base") ||
!ASSERT_OK_PTR(btf3, "distilled_base") ||
!ASSERT_OK_PTR(btf4, "distilled_split") ||
!ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt")) goto cleanup;
VALIDATE_RAW_BTF(
btf3, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED"); if (!ASSERT_EQ(btf__relocate(btf4, btf1), 0, "relocate_split")) goto cleanup;
VALIDATE_RAW_BTF(
btf4, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED", "[3] PTR '(anon)' type_id=1", "[4] CONST '(anon)' type_id=2");
/* If a needed type is not present in the base BTF we wish to relocate * with, btf__relocate() should error our.
*/ staticvoid test_distilled_base_missing_err(void)
{ struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;
btf1 = btf__new_empty(); if (!ASSERT_OK_PTR(btf1, "empty_main_btf")) return;
btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
btf__add_int(btf1, "int", 8, BTF_INT_SIGNED); /* [2] int */
VALIDATE_RAW_BTF(
btf1, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
btf2 = btf__new_empty_split(btf1); if (!ASSERT_OK_PTR(btf2, "empty_split_btf")) goto cleanup;
btf__add_ptr(btf2, 1);
btf__add_const(btf2, 2);
VALIDATE_RAW_BTF(
btf2, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED", "[3] PTR '(anon)' type_id=1", "[4] CONST '(anon)' type_id=2"); if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4), "distilled_base") ||
!ASSERT_OK_PTR(btf3, "distilled_base") ||
!ASSERT_OK_PTR(btf4, "distilled_split") ||
!ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt")) goto cleanup;
VALIDATE_RAW_BTF(
btf3, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
btf5 = btf__new_empty(); if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf")) goto cleanup;
btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [1] int */
VALIDATE_RAW_BTF(
btf5, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");
/* With 2 types of same size in distilled base BTF, relocation should * fail as we have no means to choose between them.
*/ staticvoid test_distilled_base_multi_err(void)
{ struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
btf1 = btf__new_empty(); if (!ASSERT_OK_PTR(btf1, "empty_main_btf")) return;
btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [2] int */
VALIDATE_RAW_BTF(
btf1, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
btf2 = btf__new_empty_split(btf1); if (!ASSERT_OK_PTR(btf2, "empty_split_btf")) goto cleanup;
btf__add_ptr(btf2, 1);
btf__add_const(btf2, 2);
VALIDATE_RAW_BTF(
btf2, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[3] PTR '(anon)' type_id=1", "[4] CONST '(anon)' type_id=2"); if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4), "distilled_base") ||
!ASSERT_OK_PTR(btf3, "distilled_base") ||
!ASSERT_OK_PTR(btf4, "distilled_split") ||
!ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt")) goto cleanup;
VALIDATE_RAW_BTF(
btf3, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
ASSERT_EQ(btf__relocate(btf4, btf1), -EINVAL, "relocate_split");
cleanup:
btf__free(btf4);
btf__free(btf3);
btf__free(btf2);
btf__free(btf1);
}
/* With 2 types of same size in base BTF, relocation should * fail as we have no means to choose between them.
*/ staticvoid test_distilled_base_multi_err2(void)
{ struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;
btf1 = btf__new_empty(); if (!ASSERT_OK_PTR(btf1, "empty_main_btf")) return;
btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
VALIDATE_RAW_BTF(
btf1, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
btf2 = btf__new_empty_split(btf1); if (!ASSERT_OK_PTR(btf2, "empty_split_btf")) goto cleanup;
btf__add_ptr(btf2, 1);
VALIDATE_RAW_BTF(
btf2, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] PTR '(anon)' type_id=1"); if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4), "distilled_base") ||
!ASSERT_OK_PTR(btf3, "distilled_base") ||
!ASSERT_OK_PTR(btf4, "distilled_split") ||
!ASSERT_EQ(2, btf__type_cnt(btf3), "distilled_base_type_cnt")) goto cleanup;
VALIDATE_RAW_BTF(
btf3, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
btf5 = btf__new_empty(); if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf")) goto cleanup;
btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [1] int */
btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [2] int */
VALIDATE_RAW_BTF(
btf5, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");
cleanup:
btf__free(btf5);
btf__free(btf4);
btf__free(btf3);
btf__free(btf2);
btf__free(btf1);
}
/* create split reference BTF from vmlinux + split BTF with a few type references; * ensure the resultant split reference BTF is as expected, containing only types * needed to disambiguate references from split BTF.
*/ staticvoid test_distilled_base_vmlinux(void)
{ struct btf *split_btf = NULL, *vmlinux_btf = btf__load_vmlinux_btf(); struct btf *split_dist = NULL, *base_dist = NULL;
__s32 int_id, myint_id;
if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux")) return;
int_id = btf__find_by_name_kind(vmlinux_btf, "int", BTF_KIND_INT); if (!ASSERT_GT(int_id, 0, "find_int")) goto cleanup;
split_btf = btf__new_empty_split(vmlinux_btf); if (!ASSERT_OK_PTR(split_btf, "new_split")) goto cleanup;
myint_id = btf__add_typedef(split_btf, "myint", int_id);
btf__add_ptr(split_btf, myint_id);
if (!ASSERT_EQ(btf__distill_base(split_btf, &base_dist, &split_dist), 0, "distill_vmlinux_base")) goto cleanup;
if (!ASSERT_OK_PTR(split_dist, "split_distilled") ||
!ASSERT_OK_PTR(base_dist, "base_dist")) goto cleanup;
VALIDATE_RAW_BTF(
split_dist, "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", "[2] TYPEDEF 'myint' type_id=1", "[3] PTR '(anon)' type_id=2");
/* If a needed composite type, which is the member of composite type * in the split BTF, has a different size in the base BTF we wish to * relocate with, btf__relocate() should error out.
*/ staticvoid test_distilled_base_embedded_err(void)
{ struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;
btf1 = btf__new_empty(); if (!ASSERT_OK_PTR(btf1, "empty_main_btf")) return;
btf5 = btf__new_empty(); if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf")) goto cleanup;
btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [1] int */ /* struct with the same name but different size */
btf__add_struct(btf5, "s1", 8); /* [2] struct s1 { */
btf__add_field(btf5, "f1", 1, 0, 0); /* int f1; */ /* } */
void test_btf_distill(void)
{ if (test__start_subtest("distilled_base"))
test_distilled_base(); if (test__start_subtest("distilled_base_multi"))
test_distilled_base_multi(); if (test__start_subtest("distilled_base_missing_err"))
test_distilled_base_missing_err(); if (test__start_subtest("distilled_base_multi_err"))
test_distilled_base_multi_err(); if (test__start_subtest("distilled_base_multi_err2"))
test_distilled_base_multi_err2(); if (test__start_subtest("distilled_base_embedded_err"))
test_distilled_base_embedded_err(); if (test__start_subtest("distilled_base_vmlinux"))
test_distilled_base_vmlinux(); if (test__start_subtest("distilled_endianness"))
test_distilled_endianness();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.