@@ -40,12 +40,72 @@ static void __always_inline trigger_func(int x) {
40
40
}
41
41
}
42
42
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
+
43
102
static void subtest_basic_usdt (void )
44
103
{
45
104
LIBBPF_OPTS (bpf_usdt_opts , opts );
46
105
struct test_usdt * skel ;
47
106
struct test_usdt__bss * bss ;
48
107
int err , i ;
108
+ const __u64 expected_cookie = 0xcafedeadbeeffeed ;
49
109
50
110
skel = test_usdt__open_and_load ();
51
111
if (!ASSERT_OK_PTR (skel , "skel_open" ))
@@ -59,20 +119,29 @@ static void subtest_basic_usdt(void)
59
119
goto cleanup ;
60
120
61
121
/* usdt0 won't be auto-attached */
62
- opts .usdt_cookie = 0xcafedeadbeeffeed ;
122
+ opts .usdt_cookie = expected_cookie ;
63
123
skel -> links .usdt0 = bpf_program__attach_usdt (skel -> progs .usdt0 ,
64
124
0 /*self*/ , "/proc/self/exe" ,
65
125
"test" , "usdt0" , & opts );
66
126
if (!ASSERT_OK_PTR (skel -> links .usdt0 , "usdt0_link" ))
67
127
goto cleanup ;
68
128
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
+
69
138
trigger_func (1 );
70
139
71
140
ASSERT_EQ (bss -> usdt0_called , 1 , "usdt0_called" );
72
141
ASSERT_EQ (bss -> usdt3_called , 1 , "usdt3_called" );
73
142
ASSERT_EQ (bss -> usdt12_called , 1 , "usdt12_called" );
74
143
75
- ASSERT_EQ (bss -> usdt0_cookie , 0xcafedeadbeeffeed , "usdt0_cookie" );
144
+ ASSERT_EQ (bss -> usdt0_cookie , expected_cookie , "usdt0_cookie" );
76
145
ASSERT_EQ (bss -> usdt0_arg_cnt , 0 , "usdt0_arg_cnt" );
77
146
ASSERT_EQ (bss -> usdt0_arg_ret , - ENOENT , "usdt0_arg_ret" );
78
147
ASSERT_EQ (bss -> usdt0_arg_size , - ENOENT , "usdt0_arg_size" );
@@ -156,6 +225,16 @@ static void subtest_basic_usdt(void)
156
225
ASSERT_EQ (bss -> usdt3_args [1 ], 42 , "usdt3_arg2" );
157
226
ASSERT_EQ (bss -> usdt3_args [2 ], (uintptr_t )& bla , "usdt3_arg3" );
158
227
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
+
159
238
cleanup :
160
239
test_usdt__destroy (skel );
161
240
}
0 commit comments