@@ -112,6 +112,11 @@ void libbpf_print(enum libbpf_print_level level, const char *format, ...)
112112# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
113113#endif
114114
115+ static inline __u64 ptr_to_u64 (const void * ptr )
116+ {
117+ return (__u64 ) (unsigned long ) ptr ;
118+ }
119+
115120struct bpf_capabilities {
116121 /* v4.14: kernel support for program & map names. */
117122 __u32 name :1 ;
@@ -2997,3 +3002,249 @@ bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
29973002 ring_buffer_write_tail (header , data_tail );
29983003 return ret ;
29993004}
3005+
3006+ struct bpf_prog_info_array_desc {
3007+ int array_offset ; /* e.g. offset of jited_prog_insns */
3008+ int count_offset ; /* e.g. offset of jited_prog_len */
3009+ int size_offset ; /* > 0: offset of rec size,
3010+ * < 0: fix size of -size_offset
3011+ */
3012+ };
3013+
3014+ static struct bpf_prog_info_array_desc bpf_prog_info_array_desc [] = {
3015+ [BPF_PROG_INFO_JITED_INSNS ] = {
3016+ offsetof(struct bpf_prog_info , jited_prog_insns ),
3017+ offsetof(struct bpf_prog_info , jited_prog_len ),
3018+ -1 ,
3019+ },
3020+ [BPF_PROG_INFO_XLATED_INSNS ] = {
3021+ offsetof(struct bpf_prog_info , xlated_prog_insns ),
3022+ offsetof(struct bpf_prog_info , xlated_prog_len ),
3023+ -1 ,
3024+ },
3025+ [BPF_PROG_INFO_MAP_IDS ] = {
3026+ offsetof(struct bpf_prog_info , map_ids ),
3027+ offsetof(struct bpf_prog_info , nr_map_ids ),
3028+ - (int )sizeof (__u32 ),
3029+ },
3030+ [BPF_PROG_INFO_JITED_KSYMS ] = {
3031+ offsetof(struct bpf_prog_info , jited_ksyms ),
3032+ offsetof(struct bpf_prog_info , nr_jited_ksyms ),
3033+ - (int )sizeof (__u64 ),
3034+ },
3035+ [BPF_PROG_INFO_JITED_FUNC_LENS ] = {
3036+ offsetof(struct bpf_prog_info , jited_func_lens ),
3037+ offsetof(struct bpf_prog_info , nr_jited_func_lens ),
3038+ - (int )sizeof (__u32 ),
3039+ },
3040+ [BPF_PROG_INFO_FUNC_INFO ] = {
3041+ offsetof(struct bpf_prog_info , func_info ),
3042+ offsetof(struct bpf_prog_info , nr_func_info ),
3043+ offsetof(struct bpf_prog_info , func_info_rec_size ),
3044+ },
3045+ [BPF_PROG_INFO_LINE_INFO ] = {
3046+ offsetof(struct bpf_prog_info , line_info ),
3047+ offsetof(struct bpf_prog_info , nr_line_info ),
3048+ offsetof(struct bpf_prog_info , line_info_rec_size ),
3049+ },
3050+ [BPF_PROG_INFO_JITED_LINE_INFO ] = {
3051+ offsetof(struct bpf_prog_info , jited_line_info ),
3052+ offsetof(struct bpf_prog_info , nr_jited_line_info ),
3053+ offsetof(struct bpf_prog_info , jited_line_info_rec_size ),
3054+ },
3055+ [BPF_PROG_INFO_PROG_TAGS ] = {
3056+ offsetof(struct bpf_prog_info , prog_tags ),
3057+ offsetof(struct bpf_prog_info , nr_prog_tags ),
3058+ - (int )sizeof (__u8 ) * BPF_TAG_SIZE ,
3059+ },
3060+
3061+ };
3062+
3063+ static __u32 bpf_prog_info_read_offset_u32 (struct bpf_prog_info * info , int offset )
3064+ {
3065+ __u32 * array = (__u32 * )info ;
3066+
3067+ if (offset >= 0 )
3068+ return array [offset / sizeof (__u32 )];
3069+ return - (int )offset ;
3070+ }
3071+
3072+ static __u64 bpf_prog_info_read_offset_u64 (struct bpf_prog_info * info , int offset )
3073+ {
3074+ __u64 * array = (__u64 * )info ;
3075+
3076+ if (offset >= 0 )
3077+ return array [offset / sizeof (__u64 )];
3078+ return - (int )offset ;
3079+ }
3080+
3081+ static void bpf_prog_info_set_offset_u32 (struct bpf_prog_info * info , int offset ,
3082+ __u32 val )
3083+ {
3084+ __u32 * array = (__u32 * )info ;
3085+
3086+ if (offset >= 0 )
3087+ array [offset / sizeof (__u32 )] = val ;
3088+ }
3089+
3090+ static void bpf_prog_info_set_offset_u64 (struct bpf_prog_info * info , int offset ,
3091+ __u64 val )
3092+ {
3093+ __u64 * array = (__u64 * )info ;
3094+
3095+ if (offset >= 0 )
3096+ array [offset / sizeof (__u64 )] = val ;
3097+ }
3098+
3099+ struct bpf_prog_info_linear *
3100+ bpf_program__get_prog_info_linear (int fd , __u64 arrays )
3101+ {
3102+ struct bpf_prog_info_linear * info_linear ;
3103+ struct bpf_prog_info info = {};
3104+ __u32 info_len = sizeof (info );
3105+ __u32 data_len = 0 ;
3106+ int i , err ;
3107+ void * ptr ;
3108+
3109+ if (arrays >> BPF_PROG_INFO_LAST_ARRAY )
3110+ return ERR_PTR (- EINVAL );
3111+
3112+ /* step 1: get array dimensions */
3113+ err = bpf_obj_get_info_by_fd (fd , & info , & info_len );
3114+ if (err ) {
3115+ pr_debug ("can't get prog info: %s" , strerror (errno ));
3116+ return ERR_PTR (- EFAULT );
3117+ }
3118+
3119+ /* step 2: calculate total size of all arrays */
3120+ for (i = BPF_PROG_INFO_FIRST_ARRAY ; i < BPF_PROG_INFO_LAST_ARRAY ; ++ i ) {
3121+ bool include_array = (arrays & (1UL << i )) > 0 ;
3122+ struct bpf_prog_info_array_desc * desc ;
3123+ __u32 count , size ;
3124+
3125+ desc = bpf_prog_info_array_desc + i ;
3126+
3127+ /* kernel is too old to support this field */
3128+ if (info_len < desc -> array_offset + sizeof (__u32 ) ||
3129+ info_len < desc -> count_offset + sizeof (__u32 ) ||
3130+ (desc -> size_offset > 0 && info_len < desc -> size_offset ))
3131+ include_array = false;
3132+
3133+ if (!include_array ) {
3134+ arrays &= ~(1UL << i ); /* clear the bit */
3135+ continue ;
3136+ }
3137+
3138+ count = bpf_prog_info_read_offset_u32 (& info , desc -> count_offset );
3139+ size = bpf_prog_info_read_offset_u32 (& info , desc -> size_offset );
3140+
3141+ data_len += count * size ;
3142+ }
3143+
3144+ /* step 3: allocate continuous memory */
3145+ data_len = roundup (data_len , sizeof (__u64 ));
3146+ info_linear = malloc (sizeof (struct bpf_prog_info_linear ) + data_len );
3147+ if (!info_linear )
3148+ return ERR_PTR (- ENOMEM );
3149+
3150+ /* step 4: fill data to info_linear->info */
3151+ info_linear -> arrays = arrays ;
3152+ memset (& info_linear -> info , 0 , sizeof (info ));
3153+ ptr = info_linear -> data ;
3154+
3155+ for (i = BPF_PROG_INFO_FIRST_ARRAY ; i < BPF_PROG_INFO_LAST_ARRAY ; ++ i ) {
3156+ struct bpf_prog_info_array_desc * desc ;
3157+ __u32 count , size ;
3158+
3159+ if ((arrays & (1UL << i )) == 0 )
3160+ continue ;
3161+
3162+ desc = bpf_prog_info_array_desc + i ;
3163+ count = bpf_prog_info_read_offset_u32 (& info , desc -> count_offset );
3164+ size = bpf_prog_info_read_offset_u32 (& info , desc -> size_offset );
3165+ bpf_prog_info_set_offset_u32 (& info_linear -> info ,
3166+ desc -> count_offset , count );
3167+ bpf_prog_info_set_offset_u32 (& info_linear -> info ,
3168+ desc -> size_offset , size );
3169+ bpf_prog_info_set_offset_u64 (& info_linear -> info ,
3170+ desc -> array_offset ,
3171+ ptr_to_u64 (ptr ));
3172+ ptr += count * size ;
3173+ }
3174+
3175+ /* step 5: call syscall again to get required arrays */
3176+ err = bpf_obj_get_info_by_fd (fd , & info_linear -> info , & info_len );
3177+ if (err ) {
3178+ pr_debug ("can't get prog info: %s" , strerror (errno ));
3179+ free (info_linear );
3180+ return ERR_PTR (- EFAULT );
3181+ }
3182+
3183+ /* step 6: verify the data */
3184+ for (i = BPF_PROG_INFO_FIRST_ARRAY ; i < BPF_PROG_INFO_LAST_ARRAY ; ++ i ) {
3185+ struct bpf_prog_info_array_desc * desc ;
3186+ __u32 v1 , v2 ;
3187+
3188+ if ((arrays & (1UL << i )) == 0 )
3189+ continue ;
3190+
3191+ desc = bpf_prog_info_array_desc + i ;
3192+ v1 = bpf_prog_info_read_offset_u32 (& info , desc -> count_offset );
3193+ v2 = bpf_prog_info_read_offset_u32 (& info_linear -> info ,
3194+ desc -> count_offset );
3195+ if (v1 != v2 )
3196+ pr_warning ("%s: mismatch in element count\n" , __func__ );
3197+
3198+ v1 = bpf_prog_info_read_offset_u32 (& info , desc -> size_offset );
3199+ v2 = bpf_prog_info_read_offset_u32 (& info_linear -> info ,
3200+ desc -> size_offset );
3201+ if (v1 != v2 )
3202+ pr_warning ("%s: mismatch in rec size\n" , __func__ );
3203+ }
3204+
3205+ /* step 7: update info_len and data_len */
3206+ info_linear -> info_len = sizeof (struct bpf_prog_info );
3207+ info_linear -> data_len = data_len ;
3208+
3209+ return info_linear ;
3210+ }
3211+
3212+ void bpf_program__bpil_addr_to_offs (struct bpf_prog_info_linear * info_linear )
3213+ {
3214+ int i ;
3215+
3216+ for (i = BPF_PROG_INFO_FIRST_ARRAY ; i < BPF_PROG_INFO_LAST_ARRAY ; ++ i ) {
3217+ struct bpf_prog_info_array_desc * desc ;
3218+ __u64 addr , offs ;
3219+
3220+ if ((info_linear -> arrays & (1UL << i )) == 0 )
3221+ continue ;
3222+
3223+ desc = bpf_prog_info_array_desc + i ;
3224+ addr = bpf_prog_info_read_offset_u64 (& info_linear -> info ,
3225+ desc -> array_offset );
3226+ offs = addr - ptr_to_u64 (info_linear -> data );
3227+ bpf_prog_info_set_offset_u64 (& info_linear -> info ,
3228+ desc -> array_offset , offs );
3229+ }
3230+ }
3231+
3232+ void bpf_program__bpil_offs_to_addr (struct bpf_prog_info_linear * info_linear )
3233+ {
3234+ int i ;
3235+
3236+ for (i = BPF_PROG_INFO_FIRST_ARRAY ; i < BPF_PROG_INFO_LAST_ARRAY ; ++ i ) {
3237+ struct bpf_prog_info_array_desc * desc ;
3238+ __u64 addr , offs ;
3239+
3240+ if ((info_linear -> arrays & (1UL << i )) == 0 )
3241+ continue ;
3242+
3243+ desc = bpf_prog_info_array_desc + i ;
3244+ offs = bpf_prog_info_read_offset_u64 (& info_linear -> info ,
3245+ desc -> array_offset );
3246+ addr = offs + ptr_to_u64 (info_linear -> data );
3247+ bpf_prog_info_set_offset_u64 (& info_linear -> info ,
3248+ desc -> array_offset , addr );
3249+ }
3250+ }
0 commit comments