@@ -25,6 +25,7 @@ unsigned short test_usdt0_semaphore SEC(".probes");
2525unsigned short test_usdt3_semaphore SEC (".probes" );
2626unsigned short test_usdt12_semaphore SEC (".probes" );
2727
28+
2829static void __always_inline trigger_func (int x ) {
2930 long y = 42 ;
3031
@@ -40,12 +41,72 @@ static void __always_inline trigger_func(int x) {
4041 }
4142}
4243
44+ #if defined(__x86_64__ ) || defined(__i386__ )
45+ /*
46+ * SIB (Scale-Index-Base) addressing format:
47+ * "size@(base_reg, index_reg, scale)"
48+ * - 'size' is the size in bytes of the array element, and its sign indicates
49+ * whether the type is signed (negative) or unsigned (positive).
50+ * - 'base_reg' is the register holding the base address, normally rdx or edx
51+ * - 'index_reg' is the register holding the index, normally rax or eax
52+ * - 'scale' is the scaling factor (typically 1, 2, 4, or 8), which matches the
53+ * size of the element type.
54+ *
55+ * For example, for an array of 'short' (signed 2-byte elements), the SIB spec would be:
56+ * - size: -2 (negative because 'short' is signed)
57+ * - scale: 2 (since sizeof(short) == 2)
58+ * The resulting SIB format: "-2@(%%rdx,%%rax,2)" for x86_64, "-2@(%%edx,%%eax,2)" for i386
59+ */
60+ static volatile short array [] = {-1 , -2 , -3 , -4 };
61+
62+ #if defined(__x86_64__ )
63+ #define USDT_SIB_ARG_SPEC -2@(%%rdx,%%rax,2)
64+ #else
65+ #define USDT_SIB_ARG_SPEC -2@(%%edx,%%eax,2)
66+ #endif
67+
68+ unsigned short test_usdt_sib_semaphore SEC (".probes" );
69+
70+ static void trigger_sib_spec (void )
71+ {
72+ /*
73+ * Force SIB addressing with inline assembly.
74+ *
75+ * You must compile with -std=gnu99 or -std=c99 to use the
76+ * STAP_PROBE_ASM macro.
77+ *
78+ * The STAP_PROBE_ASM macro generates a quoted string that gets
79+ * inserted between the surrounding assembly instructions. In this
80+ * case, USDT_SIB_ARG_SPEC is embedded directly into the instruction
81+ * stream, creating a probe point between the asm statement boundaries.
82+ * It works fine with gcc/clang.
83+ *
84+ * Register constraints:
85+ * - "d"(array): Binds the 'array' variable to %rdx or %edx register
86+ * - "a"(0): Binds the constant 0 to %rax or %eax register
87+ * These ensure that when USDT_SIB_ARG_SPEC references %%rdx(%edx) and
88+ * %%rax(%eax), they contain the expected values for SIB addressing.
89+ *
90+ * The "memory" clobber prevents the compiler from reordering memory
91+ * accesses around the probe point, ensuring that the probe behavior
92+ * is predictable and consistent.
93+ */
94+ asm volatile (
95+ STAP_PROBE_ASM (test , usdt_sib , USDT_SIB_ARG_SPEC )
96+ :
97+ : "d" (array ), "a" (0 )
98+ : "memory "
99+ );
100+ }
101+ #endif
102+
43103static void subtest_basic_usdt (void )
44104{
45105 LIBBPF_OPTS (bpf_usdt_opts , opts );
46106 struct test_usdt * skel ;
47107 struct test_usdt__bss * bss ;
48108 int err , i ;
109+ const __u64 expected_cookie = 0xcafedeadbeeffeed ;
49110
50111 skel = test_usdt__open_and_load ();
51112 if (!ASSERT_OK_PTR (skel , "skel_open" ))
@@ -59,20 +120,29 @@ static void subtest_basic_usdt(void)
59120 goto cleanup ;
60121
61122 /* usdt0 won't be auto-attached */
62- opts .usdt_cookie = 0xcafedeadbeeffeed ;
123+ opts .usdt_cookie = expected_cookie ;
63124 skel -> links .usdt0 = bpf_program__attach_usdt (skel -> progs .usdt0 ,
64125 0 /*self*/ , "/proc/self/exe" ,
65126 "test" , "usdt0" , & opts );
66127 if (!ASSERT_OK_PTR (skel -> links .usdt0 , "usdt0_link" ))
67128 goto cleanup ;
68129
130+ #if defined(__x86_64__ ) || defined(__i386__ )
131+ opts .usdt_cookie = expected_cookie ;
132+ skel -> links .usdt_sib = bpf_program__attach_usdt (skel -> progs .usdt_sib ,
133+ 0 /*self*/ , "/proc/self/exe" ,
134+ "test" , "usdt_sib" , & opts );
135+ if (!ASSERT_OK_PTR (skel -> links .usdt_sib , "usdt_sib_link" ))
136+ goto cleanup ;
137+ #endif
138+
69139 trigger_func (1 );
70140
71141 ASSERT_EQ (bss -> usdt0_called , 1 , "usdt0_called" );
72142 ASSERT_EQ (bss -> usdt3_called , 1 , "usdt3_called" );
73143 ASSERT_EQ (bss -> usdt12_called , 1 , "usdt12_called" );
74144
75- ASSERT_EQ (bss -> usdt0_cookie , 0xcafedeadbeeffeed , "usdt0_cookie" );
145+ ASSERT_EQ (bss -> usdt0_cookie , expected_cookie , "usdt0_cookie" );
76146 ASSERT_EQ (bss -> usdt0_arg_cnt , 0 , "usdt0_arg_cnt" );
77147 ASSERT_EQ (bss -> usdt0_arg_ret , - ENOENT , "usdt0_arg_ret" );
78148 ASSERT_EQ (bss -> usdt0_arg_size , - ENOENT , "usdt0_arg_size" );
@@ -156,6 +226,16 @@ static void subtest_basic_usdt(void)
156226 ASSERT_EQ (bss -> usdt3_args [1 ], 42 , "usdt3_arg2" );
157227 ASSERT_EQ (bss -> usdt3_args [2 ], (uintptr_t )& bla , "usdt3_arg3" );
158228
229+ #if defined(__x86_64__ ) || defined(__i386__ )
230+ trigger_sib_spec ();
231+ ASSERT_EQ (bss -> usdt_sib_called , 1 , "usdt_sib_called" );
232+ ASSERT_EQ (bss -> usdt_sib_cookie , expected_cookie , "usdt_sib_cookie" );
233+ ASSERT_EQ (bss -> usdt_sib_arg_cnt , 1 , "usdt_sib_arg_cnt" );
234+ ASSERT_EQ (bss -> usdt_sib_arg , nums [0 ], "usdt_sib_arg" );
235+ ASSERT_EQ (bss -> usdt_sib_arg_ret , 0 , "usdt_sib_arg_ret" );
236+ ASSERT_EQ (bss -> usdt_sib_arg_size , sizeof (nums [0 ]), "usdt_sib_arg_size" );
237+ #endif
238+
159239cleanup :
160240 test_usdt__destroy (skel );
161241}
0 commit comments