@@ -40,12 +40,72 @@ static void __always_inline trigger_func(int x) {
4040 }
4141}
4242
43+ #if defined(__x86_64__ ) || defined(__i386__ )
44+ /*
45+ * SIB (Scale-Index-Base) addressing format: "size@(base_reg, index_reg, scale)"
46+ * - 'size' is the size in bytes of the array element, and its sign indicates
47+ * whether the type is signed (negative) or unsigned (positive).
48+ * - 'base_reg' is the register holding the base address, normally rdx or edx
49+ * - 'index_reg' is the register holding the index, normally rax or eax
50+ * - 'scale' is the scaling factor (typically 1, 2, 4, or 8), which matches the
51+ * size of the element type.
52+ *
53+ * For example, for an array of 'short' (signed 2-byte elements), the SIB spec would be:
54+ * - size: -2 (negative because 'short' is signed)
55+ * - scale: 2 (since sizeof(short) == 2)
56+ *
57+ * The resulting SIB format: "-2@(%%rdx,%%rax,2)" for x86_64, "-2@(%%edx,%%eax,2)" for i386
58+ */
59+ static volatile short array [] = {-1 , -2 , -3 , -4 };
60+
61+ #if defined(__x86_64__ )
62+ #define USDT_SIB_ARG_SPEC -2@(%%rdx,%%rax,2)
63+ #else
64+ #define USDT_SIB_ARG_SPEC -2@(%%edx,%%eax,2)
65+ #endif
66+
67+ unsigned short test_usdt_sib_semaphore SEC (".probes" );
68+
69+ static void trigger_sib_spec (void )
70+ {
71+ /*
72+ * Force SIB addressing with inline assembly.
73+ *
74+ * You must compile with -std=gnu99 or -std=c99 to use the
75+ * STAP_PROBE_ASM macro.
76+ *
77+ * The STAP_PROBE_ASM macro generates a quoted string that gets
78+ * inserted between the surrounding assembly instructions. In this
79+ * case, USDT_SIB_ARG_SPEC is embedded directly into the instruction
80+ * stream, creating a probe point between the asm statement boundaries.
81+ * It works fine with gcc/clang.
82+ *
83+ * Register constraints:
84+ * - "d"(array): Binds the 'array' variable to %rdx or %edx register
85+ * - "a"(0): Binds the constant 0 to %rax or %eax register
86+ * These ensure that when USDT_SIB_ARG_SPEC references %%rdx(%edx) and
87+ * %%rax(%eax), they contain the expected values for SIB addressing.
88+ *
89+ * The "memory" clobber prevents the compiler from reordering memory
90+ * accesses around the probe point, ensuring that the probe behavior
91+ * is predictable and consistent.
92+ */
93+ asm volatile (
94+ STAP_PROBE_ASM (test , usdt_sib , USDT_SIB_ARG_SPEC )
95+ :
96+ : "d" (array ), "a" (0 )
97+ : "memory "
98+ );
99+ }
100+ #endif
101+
43102static void subtest_basic_usdt (void )
44103{
45104 LIBBPF_OPTS (bpf_usdt_opts , opts );
46105 struct test_usdt * skel ;
47106 struct test_usdt__bss * bss ;
48107 int err , i ;
108+ const __u64 expected_cookie = 0xcafedeadbeeffeed ;
49109
50110 skel = test_usdt__open_and_load ();
51111 if (!ASSERT_OK_PTR (skel , "skel_open" ))
@@ -59,20 +119,29 @@ static void subtest_basic_usdt(void)
59119 goto cleanup ;
60120
61121 /* usdt0 won't be auto-attached */
62- opts .usdt_cookie = 0xcafedeadbeeffeed ;
122+ opts .usdt_cookie = expected_cookie ;
63123 skel -> links .usdt0 = bpf_program__attach_usdt (skel -> progs .usdt0 ,
64124 0 /*self*/ , "/proc/self/exe" ,
65125 "test" , "usdt0" , & opts );
66126 if (!ASSERT_OK_PTR (skel -> links .usdt0 , "usdt0_link" ))
67127 goto cleanup ;
68128
129+ #if defined(__x86_64__ ) || defined(__i386__ )
130+ opts .usdt_cookie = expected_cookie ;
131+ skel -> links .usdt_sib = bpf_program__attach_usdt (skel -> progs .usdt_sib ,
132+ 0 /*self*/ , "/proc/self/exe" ,
133+ "test" , "usdt_sib" , & opts );
134+ if (!ASSERT_OK_PTR (skel -> links .usdt_sib , "usdt_sib_link" ))
135+ goto cleanup ;
136+ #endif
137+
69138 trigger_func (1 );
70139
71140 ASSERT_EQ (bss -> usdt0_called , 1 , "usdt0_called" );
72141 ASSERT_EQ (bss -> usdt3_called , 1 , "usdt3_called" );
73142 ASSERT_EQ (bss -> usdt12_called , 1 , "usdt12_called" );
74143
75- ASSERT_EQ (bss -> usdt0_cookie , 0xcafedeadbeeffeed , "usdt0_cookie" );
144+ ASSERT_EQ (bss -> usdt0_cookie , expected_cookie , "usdt0_cookie" );
76145 ASSERT_EQ (bss -> usdt0_arg_cnt , 0 , "usdt0_arg_cnt" );
77146 ASSERT_EQ (bss -> usdt0_arg_ret , - ENOENT , "usdt0_arg_ret" );
78147 ASSERT_EQ (bss -> usdt0_arg_size , - ENOENT , "usdt0_arg_size" );
@@ -156,6 +225,16 @@ static void subtest_basic_usdt(void)
156225 ASSERT_EQ (bss -> usdt3_args [1 ], 42 , "usdt3_arg2" );
157226 ASSERT_EQ (bss -> usdt3_args [2 ], (uintptr_t )& bla , "usdt3_arg3" );
158227
228+ #if defined(__x86_64__ ) || defined(__i386__ )
229+ trigger_sib_spec ();
230+ ASSERT_EQ (bss -> usdt_sib_called , 1 , "usdt_sib_called" );
231+ ASSERT_EQ (bss -> usdt_sib_cookie , expected_cookie , "usdt_sib_cookie" );
232+ ASSERT_EQ (bss -> usdt_sib_arg_cnt , 1 , "usdt_sib_arg_cnt" );
233+ ASSERT_EQ (bss -> usdt_sib_arg , nums [0 ], "usdt_sib_arg" );
234+ ASSERT_EQ (bss -> usdt_sib_arg_ret , 0 , "usdt_sib_arg_ret" );
235+ ASSERT_EQ (bss -> usdt_sib_arg_size , sizeof (nums [0 ]), "usdt_sib_arg_size" );
236+ #endif
237+
159238cleanup :
160239 test_usdt__destroy (skel );
161240}
0 commit comments