2020#include "test_global_func17.skel.h"
2121#include "test_global_func_ctx_args.skel.h"
2222
23+ #include "bpf/libbpf_internal.h"
24+ #include "btf_helpers.h"
25+
26+ static void check_ctx_arg_type (const struct btf * btf , const struct btf_param * p )
27+ {
28+ const struct btf_type * t ;
29+ const char * s ;
30+
31+ t = btf__type_by_id (btf , p -> type );
32+ if (!ASSERT_EQ (btf_kind (t ), BTF_KIND_PTR , "ptr_t" ))
33+ return ;
34+
35+ s = btf_type_raw_dump (btf , t -> type );
36+ if (!ASSERT_HAS_SUBSTR (s , "STRUCT 'bpf_perf_event_data' size=0 vlen=0" ,
37+ "ctx_struct_t" ))
38+ return ;
39+ }
40+
41+ static void subtest_ctx_arg_rewrite (void )
42+ {
43+ struct test_global_func_ctx_args * skel = NULL ;
44+ struct bpf_prog_info info ;
45+ char func_info_buf [1024 ] __attribute__((aligned (8 )));
46+ struct bpf_func_info_min * rec ;
47+ struct btf * btf = NULL ;
48+ __u32 info_len = sizeof (info );
49+ int err , fd , i ;
50+
51+ skel = test_global_func_ctx_args__open ();
52+ if (!ASSERT_OK_PTR (skel , "skel_open" ))
53+ return ;
54+
55+ bpf_program__set_autoload (skel -> progs .arg_tag_ctx_perf , true);
56+
57+ err = test_global_func_ctx_args__load (skel );
58+ if (!ASSERT_OK (err , "skel_load" ))
59+ goto out ;
60+
61+ memset (& info , 0 , sizeof (info ));
62+ info .func_info = ptr_to_u64 (& func_info_buf );
63+ info .nr_func_info = 3 ;
64+ info .func_info_rec_size = sizeof (struct bpf_func_info_min );
65+
66+ fd = bpf_program__fd (skel -> progs .arg_tag_ctx_perf );
67+ err = bpf_prog_get_info_by_fd (fd , & info , & info_len );
68+ if (!ASSERT_OK (err , "prog_info" ))
69+ goto out ;
70+
71+ if (!ASSERT_EQ (info .nr_func_info , 3 , "nr_func_info" ))
72+ goto out ;
73+
74+ btf = btf__load_from_kernel_by_id (info .btf_id );
75+ if (!ASSERT_OK_PTR (btf , "obj_kern_btf" ))
76+ goto out ;
77+
78+ rec = (struct bpf_func_info_min * )func_info_buf ;
79+ for (i = 0 ; i < info .nr_func_info ; i ++ , rec = (void * )rec + info .func_info_rec_size ) {
80+ const struct btf_type * fn_t , * proto_t ;
81+ const char * name ;
82+
83+ if (rec -> insn_off == 0 )
84+ continue ; /* main prog, skip */
85+
86+ fn_t = btf__type_by_id (btf , rec -> type_id );
87+ if (!ASSERT_OK_PTR (fn_t , "fn_type" ))
88+ goto out ;
89+ if (!ASSERT_EQ (btf_kind (fn_t ), BTF_KIND_FUNC , "fn_type_kind" ))
90+ goto out ;
91+ proto_t = btf__type_by_id (btf , fn_t -> type );
92+ if (!ASSERT_OK_PTR (proto_t , "proto_type" ))
93+ goto out ;
94+
95+ name = btf__name_by_offset (btf , fn_t -> name_off );
96+ if (strcmp (name , "subprog_ctx_tag" ) == 0 ) {
97+ /* int subprog_ctx_tag(void *ctx __arg_ctx) */
98+ if (!ASSERT_EQ (btf_vlen (proto_t ), 1 , "arg_cnt" ))
99+ goto out ;
100+
101+ /* arg 0 is PTR -> STRUCT bpf_perf_event_data */
102+ check_ctx_arg_type (btf , & btf_params (proto_t )[0 ]);
103+ } else if (strcmp (name , "subprog_multi_ctx_tags" ) == 0 ) {
104+ /* int subprog_multi_ctx_tags(void *ctx1 __arg_ctx,
105+ * struct my_struct *mem,
106+ * void *ctx2 __arg_ctx)
107+ */
108+ if (!ASSERT_EQ (btf_vlen (proto_t ), 3 , "arg_cnt" ))
109+ goto out ;
110+
111+ /* arg 0 is PTR -> STRUCT bpf_perf_event_data */
112+ check_ctx_arg_type (btf , & btf_params (proto_t )[0 ]);
113+ /* arg 2 is PTR -> STRUCT bpf_perf_event_data */
114+ check_ctx_arg_type (btf , & btf_params (proto_t )[2 ]);
115+ } else {
116+ ASSERT_FAIL ("unexpected subprog %s" , name );
117+ goto out ;
118+ }
119+ }
120+
121+ out :
122+ btf__free (btf );
123+ test_global_func_ctx_args__destroy (skel );
124+ }
125+
23126void test_test_global_funcs (void )
24127{
25128 RUN_TESTS (test_global_func1 );
@@ -40,4 +143,7 @@ void test_test_global_funcs(void)
40143 RUN_TESTS (test_global_func16 );
41144 RUN_TESTS (test_global_func17 );
42145 RUN_TESTS (test_global_func_ctx_args );
146+
147+ if (test__start_subtest ("ctx_arg_rewrite" ))
148+ subtest_ctx_arg_rewrite ();
43149}
0 commit comments