@@ -247,6 +247,89 @@ static void subtest_basic_usdt(bool optimized)
247247#undef TRIGGER
248248}
249249
250+ #ifdef __x86_64
251+ extern void usdt_1 (void );
252+ extern void usdt_2 (void );
253+
254+ /* nop, nop5 */
255+ static unsigned char nop1_nop5_combo [6 ] = { 0x90 , 0x0f , 0x1f , 0x44 , 0x00 , 0x00 };
256+ static unsigned char nop1 [6 ] = { 0x90 };
257+
258+ static void * find_instr (void * fn , unsigned char * instr , size_t cnt )
259+ {
260+ int i ;
261+
262+ for (i = 0 ; i < 10 ; i ++ ) {
263+ if (!memcmp (instr , fn + i , cnt ))
264+ return fn + i ;
265+ }
266+ return NULL ;
267+ }
268+
269+ static void subtest_optimized_attach (void )
270+ {
271+ struct test_usdt * skel ;
272+ __u8 * addr_1 , * addr_2 ;
273+
274+ /* usdt_1 probe has single nop instruction */
275+ addr_1 = find_instr (usdt_1 , nop1_nop5_combo , 6 );
276+ if (!ASSERT_NULL (addr_1 , "usdt_1_find_nop1_nop5_combo" ))
277+ return ;
278+
279+ addr_1 = find_instr (usdt_1 , nop1 , 1 );
280+ if (!ASSERT_OK_PTR (addr_1 , "usdt_1_find_nop1" ))
281+ return ;
282+
283+ /* usdt_2 probe has nop,nop5 instructions combo */
284+ addr_2 = find_instr (usdt_2 , nop1_nop5_combo , 6 );
285+ if (!ASSERT_OK_PTR (addr_2 , "usdt_2_find_nop1_nop5_combo" ))
286+ return ;
287+
288+ skel = test_usdt__open_and_load ();
289+ if (!ASSERT_OK_PTR (skel , "test_usdt__open_and_load" ))
290+ return ;
291+
292+ /*
293+ * Attach program on top of usdt_1 which is single nop probe,
294+ * so the probe won't get optimized.
295+ */
296+ skel -> links .usdt_executed = bpf_program__attach_usdt (skel -> progs .usdt_executed ,
297+ 0 /*self*/ , "/proc/self/exe" ,
298+ "optimized_attach" , "usdt_1" , NULL );
299+ if (!ASSERT_OK_PTR (skel -> links .usdt_executed , "bpf_program__attach_usdt" ))
300+ goto cleanup ;
301+
302+ usdt_1 ();
303+ usdt_1 ();
304+
305+ /* nop is on addr_1 address */
306+ ASSERT_EQ (* addr_1 , 0xcc , "int3" );
307+ ASSERT_EQ (skel -> bss -> executed , 2 , "executed" );
308+
309+ bpf_link__destroy (skel -> links .usdt_executed );
310+
311+ /*
312+ * Attach program on top of usdt_2 which is probe defined on top
313+ * of nop1,nop5 combo, so the probe gets optimized on top of nop5.
314+ */
315+ skel -> links .usdt_executed = bpf_program__attach_usdt (skel -> progs .usdt_executed ,
316+ 0 /*self*/ , "/proc/self/exe" ,
317+ "optimized_attach" , "usdt_2" , NULL );
318+ if (!ASSERT_OK_PTR (skel -> links .usdt_executed , "bpf_program__attach_usdt" ))
319+ goto cleanup ;
320+
321+ usdt_2 ();
322+ usdt_2 ();
323+
324+ /* nop5 is on addr_2 + 1 address */
325+ ASSERT_EQ (* (addr_2 + 1 ), 0xe8 , "call" );
326+ ASSERT_EQ (skel -> bss -> executed , 4 , "executed" );
327+
328+ cleanup :
329+ test_usdt__destroy (skel );
330+ }
331+ #endif
332+
250333unsigned short test_usdt_100_semaphore SEC (".probes" );
251334unsigned short test_usdt_300_semaphore SEC (".probes" );
252335unsigned short test_usdt_400_semaphore SEC (".probes" );
@@ -516,6 +599,8 @@ void test_usdt(void)
516599#ifdef __x86_64__
517600 if (test__start_subtest ("basic_optimized" ))
518601 subtest_basic_usdt (true);
602+ if (test__start_subtest ("optimized_attach" ))
603+ subtest_optimized_attach ();
519604#endif
520605 if (test__start_subtest ("multispec" ))
521606 subtest_multispec_usdt ();
0 commit comments