1010#include "disasm_helpers.h"
1111#include "unpriv_helpers.h"
1212#include "cap_helpers.h"
13+ #include "jit_disasm_helpers.h"
1314
1415#define str_has_pfx (str , pfx ) \
1516 (strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
3334#define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv"
3435#define TEST_BTF_PATH "comment:test_btf_path="
3536#define TEST_TAG_ARCH "comment:test_arch="
37+ #define TEST_TAG_JITED_PFX "comment:test_jited="
38+ #define TEST_TAG_JITED_PFX_UNPRIV "comment:test_jited_unpriv="
3639
3740/* Warning: duplicated in bpf_misc.h */
3841#define POINTER_VALUE 0xcafe4all
@@ -68,6 +71,7 @@ struct test_subspec {
6871 bool expect_failure ;
6972 struct expected_msgs expect_msgs ;
7073 struct expected_msgs expect_xlated ;
74+ struct expected_msgs jited ;
7175 int retval ;
7276 bool execute ;
7377};
@@ -124,6 +128,8 @@ static void free_test_spec(struct test_spec *spec)
124128 free_msgs (& spec -> unpriv .expect_msgs );
125129 free_msgs (& spec -> priv .expect_xlated );
126130 free_msgs (& spec -> unpriv .expect_xlated );
131+ free_msgs (& spec -> priv .jited );
132+ free_msgs (& spec -> unpriv .jited );
127133
128134 free (spec -> priv .name );
129135 free (spec -> unpriv .name );
@@ -237,6 +243,21 @@ static int push_msg(const char *substr, struct expected_msgs *msgs)
237243 return __push_msg (substr , false, msgs );
238244}
239245
246+ static int push_disasm_msg (const char * regex_str , bool * on_next_line , struct expected_msgs * msgs )
247+ {
248+ int err ;
249+
250+ if (strcmp (regex_str , "..." ) == 0 ) {
251+ * on_next_line = false;
252+ return 0 ;
253+ }
254+ err = __push_msg (regex_str , * on_next_line , msgs );
255+ if (err )
256+ return err ;
257+ * on_next_line = true;
258+ return 0 ;
259+ }
260+
240261static int parse_int (const char * str , int * val , const char * name )
241262{
242263 char * end ;
@@ -320,6 +341,18 @@ enum arch {
320341 ARCH_RISCV64 = 0x4 ,
321342};
322343
344+ static int get_current_arch (void )
345+ {
346+ #if defined(__x86_64__ )
347+ return ARCH_X86_64 ;
348+ #elif defined(__aarch64__ )
349+ return ARCH_ARM64 ;
350+ #elif defined(__riscv ) && __riscv_xlen == 64
351+ return ARCH_RISCV64 ;
352+ #endif
353+ return 0 ;
354+ }
355+
323356/* Uses btf_decl_tag attributes to describe the expected test
324357 * behavior, see bpf_misc.h for detailed description of each attribute
325358 * and attribute combinations.
@@ -332,9 +365,13 @@ static int parse_test_spec(struct test_loader *tester,
332365 const char * description = NULL ;
333366 bool has_unpriv_result = false;
334367 bool has_unpriv_retval = false;
368+ bool unpriv_jit_on_next_line ;
369+ bool jit_on_next_line ;
370+ bool collect_jit = false;
335371 int func_id , i , err = 0 ;
336372 u32 arch_mask = 0 ;
337373 struct btf * btf ;
374+ enum arch arch ;
338375
339376 memset (spec , 0 , sizeof (* spec ));
340377
@@ -399,6 +436,30 @@ static int parse_test_spec(struct test_loader *tester,
399436 if (err )
400437 goto cleanup ;
401438 spec -> mode_mask |= UNPRIV ;
439+ } else if ((msg = skip_dynamic_pfx (s , TEST_TAG_JITED_PFX ))) {
440+ if (arch_mask == 0 ) {
441+ PRINT_FAIL ("__jited used before __arch_*" );
442+ goto cleanup ;
443+ }
444+ if (collect_jit ) {
445+ err = push_disasm_msg (msg , & jit_on_next_line ,
446+ & spec -> priv .jited );
447+ if (err )
448+ goto cleanup ;
449+ spec -> mode_mask |= PRIV ;
450+ }
451+ } else if ((msg = skip_dynamic_pfx (s , TEST_TAG_JITED_PFX_UNPRIV ))) {
452+ if (arch_mask == 0 ) {
453+ PRINT_FAIL ("__unpriv_jited used before __arch_*" );
454+ goto cleanup ;
455+ }
456+ if (collect_jit ) {
457+ err = push_disasm_msg (msg , & unpriv_jit_on_next_line ,
458+ & spec -> unpriv .jited );
459+ if (err )
460+ goto cleanup ;
461+ spec -> mode_mask |= UNPRIV ;
462+ }
402463 } else if ((msg = skip_dynamic_pfx (s , TEST_TAG_EXPECT_XLATED_PFX ))) {
403464 err = push_msg (msg , & spec -> priv .expect_xlated );
404465 if (err )
@@ -459,16 +520,20 @@ static int parse_test_spec(struct test_loader *tester,
459520 } else if (str_has_pfx (s , TEST_TAG_ARCH )) {
460521 val = s + sizeof (TEST_TAG_ARCH ) - 1 ;
461522 if (strcmp (val , "X86_64" ) == 0 ) {
462- arch_mask | = ARCH_X86_64 ;
523+ arch = ARCH_X86_64 ;
463524 } else if (strcmp (val , "ARM64" ) == 0 ) {
464- arch_mask | = ARCH_ARM64 ;
525+ arch = ARCH_ARM64 ;
465526 } else if (strcmp (val , "RISCV64" ) == 0 ) {
466- arch_mask | = ARCH_RISCV64 ;
527+ arch = ARCH_RISCV64 ;
467528 } else {
468529 PRINT_FAIL ("bad arch spec: '%s'" , val );
469530 err = - EINVAL ;
470531 goto cleanup ;
471532 }
533+ arch_mask |= arch ;
534+ collect_jit = get_current_arch () == arch ;
535+ unpriv_jit_on_next_line = true;
536+ jit_on_next_line = true;
472537 } else if (str_has_pfx (s , TEST_BTF_PATH )) {
473538 spec -> btf_custom_path = s + sizeof (TEST_BTF_PATH ) - 1 ;
474539 }
@@ -521,6 +586,8 @@ static int parse_test_spec(struct test_loader *tester,
521586 clone_msgs (& spec -> priv .expect_msgs , & spec -> unpriv .expect_msgs );
522587 if (spec -> unpriv .expect_xlated .cnt == 0 )
523588 clone_msgs (& spec -> priv .expect_xlated , & spec -> unpriv .expect_xlated );
589+ if (spec -> unpriv .jited .cnt == 0 )
590+ clone_msgs (& spec -> priv .jited , & spec -> unpriv .jited );
524591 }
525592
526593 spec -> valid = true;
@@ -575,16 +642,29 @@ static void emit_xlated(const char *xlated, bool force)
575642 fprintf (stdout , "XLATED:\n=============\n%s=============\n" , xlated );
576643}
577644
645+ static void emit_jited (const char * jited , bool force )
646+ {
647+ if (!force && env .verbosity == VERBOSE_NONE )
648+ return ;
649+ fprintf (stdout , "JITED:\n=============\n%s=============\n" , jited );
650+ }
651+
578652static void validate_msgs (char * log_buf , struct expected_msgs * msgs ,
579653 void (* emit_fn )(const char * buf , bool force ))
580654{
655+ const char * log = log_buf , * prev_match ;
581656 regmatch_t reg_match [1 ];
582- const char * log = log_buf ;
657+ int prev_match_line ;
658+ int match_line ;
583659 int i , j , err ;
584660
661+ prev_match_line = -1 ;
662+ match_line = 0 ;
663+ prev_match = log ;
585664 for (i = 0 ; i < msgs -> cnt ; i ++ ) {
586665 struct expect_msg * msg = & msgs -> patterns [i ];
587- const char * match = NULL ;
666+ const char * match = NULL , * pat_status ;
667+ bool wrong_line = false;
588668
589669 if (!msg -> is_regex ) {
590670 match = strstr (log , msg -> substr );
@@ -598,19 +678,41 @@ static void validate_msgs(char *log_buf, struct expected_msgs *msgs,
598678 }
599679 }
600680
601- if (!match ) {
681+ if (match ) {
682+ for (; prev_match < match ; ++ prev_match )
683+ if (* prev_match == '\n' )
684+ ++ match_line ;
685+ wrong_line = msg -> on_next_line && prev_match_line >= 0 &&
686+ prev_match_line + 1 != match_line ;
687+ }
688+
689+ if (!match || wrong_line ) {
602690 PRINT_FAIL ("expect_msg\n" );
603691 if (env .verbosity == VERBOSE_NONE )
604692 emit_fn (log_buf , true /*force*/ );
605693 for (j = 0 ; j <= i ; j ++ ) {
606694 msg = & msgs -> patterns [j ];
695+ if (j < i )
696+ pat_status = "MATCHED " ;
697+ else if (wrong_line )
698+ pat_status = "WRONG LINE" ;
699+ else
700+ pat_status = "EXPECTED " ;
701+ msg = & msgs -> patterns [j ];
607702 fprintf (stderr , "%s %s: '%s'\n" ,
608- j < i ? "MATCHED " : "EXPECTED" ,
703+ pat_status ,
609704 msg -> is_regex ? " REGEX" : "SUBSTR" ,
610705 msg -> substr );
611706 }
612- return ;
707+ if (wrong_line ) {
708+ fprintf (stderr ,
709+ "expecting match at line %d, actual match is at line %d\n" ,
710+ prev_match_line + 1 , match_line );
711+ }
712+ break ;
613713 }
714+
715+ prev_match_line = match_line ;
614716 }
615717}
616718
@@ -769,20 +871,6 @@ static int get_xlated_program_text(int prog_fd, char *text, size_t text_sz)
769871 return err ;
770872}
771873
772- static bool run_on_current_arch (int arch_mask )
773- {
774- if (arch_mask == 0 )
775- return true;
776- #if defined(__x86_64__ )
777- return arch_mask & ARCH_X86_64 ;
778- #elif defined(__aarch64__ )
779- return arch_mask & ARCH_ARM64 ;
780- #elif defined(__riscv ) && __riscv_xlen == 64
781- return arch_mask & ARCH_RISCV64 ;
782- #endif
783- return false;
784- }
785-
786874/* this function is forced noinline and has short generic name to look better
787875 * in test_progs output (in case of a failure)
788876 */
@@ -807,7 +895,7 @@ void run_subtest(struct test_loader *tester,
807895 if (!test__start_subtest (subspec -> name ))
808896 return ;
809897
810- if (! run_on_current_arch ( spec -> arch_mask )) {
898+ if (( get_current_arch () & spec -> arch_mask ) == 0 ) {
811899 test__skip ();
812900 return ;
813901 }
@@ -884,6 +972,21 @@ void run_subtest(struct test_loader *tester,
884972 validate_msgs (tester -> log_buf , & subspec -> expect_xlated , emit_xlated );
885973 }
886974
975+ if (subspec -> jited .cnt ) {
976+ err = get_jited_program_text (bpf_program__fd (tprog ),
977+ tester -> log_buf , tester -> log_buf_sz );
978+ if (err == - EOPNOTSUPP ) {
979+ printf ("%s:SKIP: jited programs disassembly is not supported,\n" , __func__ );
980+ printf ("%s:SKIP: tests are built w/o LLVM development libs\n" , __func__ );
981+ test__skip ();
982+ goto tobj_cleanup ;
983+ }
984+ if (!ASSERT_EQ (err , 0 , "get_jited_program_text" ))
985+ goto tobj_cleanup ;
986+ emit_jited (tester -> log_buf , false /*force*/ );
987+ validate_msgs (tester -> log_buf , & subspec -> jited , emit_jited );
988+ }
989+
887990 if (should_do_test_run (spec , subspec )) {
888991 /* For some reason test_verifier executes programs
889992 * with all capabilities restored. Do the same here.
0 commit comments