@@ -181,6 +181,12 @@ struct var_preset {
181181 bool applied ;
182182};
183183
184+ enum dump_mode {
185+ DUMP_NONE = 0 ,
186+ DUMP_XLATED = 1 ,
187+ DUMP_JITED = 2 ,
188+ };
189+
184190static struct env {
185191 char * * filenames ;
186192 int filename_cnt ;
@@ -227,6 +233,7 @@ static struct env {
227233 char orig_cgroup [PATH_MAX ];
228234 char stat_cgroup [PATH_MAX ];
229235 int memory_peak_fd ;
236+ __u32 dump_mode ;
230237} env ;
231238
232239static int libbpf_print_fn (enum libbpf_print_level level , const char * format , va_list args )
@@ -271,6 +278,7 @@ const char argp_program_doc[] =
271278enum {
272279 OPT_LOG_FIXED = 1000 ,
273280 OPT_LOG_SIZE = 1001 ,
281+ OPT_DUMP = 1002 ,
274282};
275283
276284static const struct argp_option opts [] = {
@@ -295,10 +303,12 @@ static const struct argp_option opts[] = {
295303 "Force BPF verifier failure on register invariant violation (BPF_F_TEST_REG_INVARIANTS program flag)" },
296304 { "top-src-lines" , 'S' , "N" , 0 , "Emit N most frequent source code lines" },
297305 { "set-global-vars" , 'G' , "GLOBAL" , 0 , "Set global variables provided in the expression, for example \"var1 = 1\"" },
306+ { "dump" , OPT_DUMP , "DUMP_MODE" , OPTION_ARG_OPTIONAL , "Print BPF program dump (xlated, jited)" },
298307 {},
299308};
300309
301310static int parse_stats (const char * stats_str , struct stat_specs * specs );
311+ static int parse_dump_mode (char * mode_str , __u32 * dump_mode );
302312static int append_filter (struct filter * * filters , int * cnt , const char * str );
303313static int append_filter_file (const char * path );
304314static int append_var_preset (struct var_preset * * presets , int * cnt , const char * expr );
@@ -427,6 +437,11 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
427437 return err ;
428438 }
429439 break ;
440+ case OPT_DUMP :
441+ err = parse_dump_mode (arg , & env .dump_mode );
442+ if (err )
443+ return err ;
444+ break ;
430445 default :
431446 return ARGP_ERR_UNKNOWN ;
432447 }
@@ -956,6 +971,32 @@ static int parse_stats(const char *stats_str, struct stat_specs *specs)
956971 return 0 ;
957972}
958973
974+ static int parse_dump_mode (char * mode_str , __u32 * dump_mode )
975+ {
976+ char * state = NULL , * cur ;
977+ int cnt = 0 ;
978+
979+ if (!mode_str ) {
980+ env .dump_mode = DUMP_XLATED ;
981+ return 0 ;
982+ }
983+
984+ for (cur = mode_str ; * cur ; ++ cur )
985+ * cur = tolower (* cur );
986+
987+ while ((cur = strtok_r (cnt ++ ? NULL : mode_str , "," , & state ))) {
988+ if (strcmp (cur , "jited" ) == 0 ) {
989+ env .dump_mode |= DUMP_JITED ;
990+ } else if (strcmp (cur , "xlated" ) == 0 ) {
991+ env .dump_mode |= DUMP_XLATED ;
992+ } else {
993+ fprintf (stderr , "Unrecognized dump mode '%s'\n" , cur );
994+ return - EINVAL ;
995+ }
996+ }
997+ return 0 ;
998+ }
999+
9591000static void free_verif_stats (struct verif_stats * stats , size_t stat_cnt )
9601001{
9611002 int i ;
@@ -1554,6 +1595,35 @@ static int parse_rvalue(const char *val, struct rvalue *rvalue)
15541595 return 0 ;
15551596}
15561597
1598+ static void dump (__u32 prog_id , const char * file_name , const char * prog_name )
1599+ {
1600+ char command [64 ], buf [1024 ];
1601+ enum dump_mode modes [2 ] = { DUMP_XLATED , DUMP_JITED };
1602+ const char * mode_lower [2 ] = { "xlated" , "jited" };
1603+ const char * mode_upper [2 ] = { "XLATED" , "JITED" };
1604+ FILE * fp ;
1605+ int i ;
1606+
1607+ for (i = 0 ; i < ARRAY_SIZE (modes ); ++ i ) {
1608+ if (!(env .dump_mode & modes [i ]))
1609+ continue ;
1610+ snprintf (command , sizeof (command ), "bpftool prog dump %s id %u" ,
1611+ mode_lower [i ], prog_id );
1612+
1613+ fp = popen (command , "r" );
1614+ if (!fp ) {
1615+ fprintf (stderr , "Can't run bpftool\n" );
1616+ return ;
1617+ }
1618+
1619+ printf ("%s/%s DUMP %s:\n" , file_name , prog_name , mode_upper [i ]);
1620+ while (fgets (buf , sizeof (buf ), fp ))
1621+ printf ("%s" , buf );
1622+ printf ("\n" );
1623+ pclose (fp );
1624+ }
1625+ }
1626+
15571627static int process_prog (const char * filename , struct bpf_object * obj , struct bpf_program * prog )
15581628{
15591629 const char * base_filename = basename (strdupa (filename ));
@@ -1630,8 +1700,11 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
16301700
16311701 memset (& info , 0 , info_len );
16321702 fd = bpf_program__fd (prog );
1633- if (fd > 0 && bpf_prog_get_info_by_fd (fd , & info , & info_len ) == 0 )
1703+ if (fd > 0 && bpf_prog_get_info_by_fd (fd , & info , & info_len ) == 0 ) {
16341704 stats -> stats [JITED_SIZE ] = info .jited_prog_len ;
1705+ if (env .dump_mode != DUMP_NONE )
1706+ dump (info .id , base_filename , prog_name );
1707+ }
16351708
16361709 parse_verif_log (buf , buf_sz , stats );
16371710
0 commit comments