@@ -209,15 +209,38 @@ static int codegen_datasec_def(struct bpf_object *obj,
209209 return 0 ;
210210}
211211
212+ static const struct btf_type * find_type_for_map (struct bpf_object * obj ,
213+ const char * map_ident )
214+ {
215+ struct btf * btf = bpf_object__btf (obj );
216+ int n = btf__type_cnt (btf ), i ;
217+ char sec_ident [256 ];
218+
219+ for (i = 1 ; i < n ; i ++ ) {
220+ const struct btf_type * t = btf__type_by_id (btf , i );
221+ const char * name ;
222+
223+ if (!btf_is_datasec (t ))
224+ continue ;
225+
226+ name = btf__str_by_offset (btf , t -> name_off );
227+ if (!get_datasec_ident (name , sec_ident , sizeof (sec_ident )))
228+ continue ;
229+
230+ if (strcmp (sec_ident , map_ident ) == 0 )
231+ return t ;
232+ }
233+ return NULL ;
234+ }
235+
212236static int codegen_datasecs (struct bpf_object * obj , const char * obj_name )
213237{
214238 struct btf * btf = bpf_object__btf (obj );
215- int n = btf__type_cnt (btf );
216239 struct btf_dump * d ;
217240 struct bpf_map * map ;
218241 const struct btf_type * sec ;
219- char sec_ident [ 256 ], map_ident [256 ];
220- int i , err = 0 ;
242+ char map_ident [256 ];
243+ int err = 0 ;
221244
222245 d = btf_dump__new (btf , codegen_btf_dump_printf , NULL , NULL );
223246 err = libbpf_get_error (d );
@@ -234,23 +257,7 @@ static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
234257 if (!get_map_ident (map , map_ident , sizeof (map_ident )))
235258 continue ;
236259
237- sec = NULL ;
238- for (i = 1 ; i < n ; i ++ ) {
239- const struct btf_type * t = btf__type_by_id (btf , i );
240- const char * name ;
241-
242- if (!btf_is_datasec (t ))
243- continue ;
244-
245- name = btf__str_by_offset (btf , t -> name_off );
246- if (!get_datasec_ident (name , sec_ident , sizeof (sec_ident )))
247- continue ;
248-
249- if (strcmp (sec_ident , map_ident ) == 0 ) {
250- sec = t ;
251- break ;
252- }
253- }
260+ sec = find_type_for_map (obj , map_ident );
254261
255262 /* In some cases (e.g., sections like .rodata.cst16 containing
256263 * compiler allocated string constants only) there will be
@@ -363,6 +370,78 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
363370 return map_sz ;
364371}
365372
373+ /* Emit type size asserts for all top-level fields in memory-mapped internal maps.
374+ */
375+ static void codegen_asserts (struct bpf_object * obj , const char * obj_name )
376+ {
377+ struct btf * btf = bpf_object__btf (obj );
378+ struct bpf_map * map ;
379+ struct btf_var_secinfo * sec_var ;
380+ int i , vlen ;
381+ const struct btf_type * sec ;
382+ char map_ident [256 ], var_ident [256 ];
383+
384+ codegen ("\
385+ \n\
386+ \n\
387+ #ifdef __cplusplus \n\
388+ #define _Static_assert static_assert \n\
389+ #endif \n\
390+ \n\
391+ __attribute__((unused)) static void \n\
392+ %1$s__type_asserts(struct %1$s *s) \n\
393+ { \n\
394+ " , obj_name );
395+
396+ bpf_object__for_each_map (map , obj ) {
397+ if (!bpf_map__is_internal (map ))
398+ continue ;
399+ if (!(bpf_map__map_flags (map ) & BPF_F_MMAPABLE ))
400+ continue ;
401+ if (!get_map_ident (map , map_ident , sizeof (map_ident )))
402+ continue ;
403+
404+ sec = find_type_for_map (obj , map_ident );
405+ if (!sec ) {
406+ /* best effort, couldn't find the type for this map */
407+ continue ;
408+ }
409+
410+ sec_var = btf_var_secinfos (sec );
411+ vlen = btf_vlen (sec );
412+
413+ for (i = 0 ; i < vlen ; i ++ , sec_var ++ ) {
414+ const struct btf_type * var = btf__type_by_id (btf , sec_var -> type );
415+ const char * var_name = btf__name_by_offset (btf , var -> name_off );
416+ __u32 var_type_id = var -> type ;
417+ __s64 var_size = btf__resolve_size (btf , var_type_id );
418+
419+ if (var_size < 0 )
420+ continue ;
421+
422+ /* static variables are not exposed through BPF skeleton */
423+ if (btf_var (var )-> linkage == BTF_VAR_STATIC )
424+ continue ;
425+
426+ var_ident [0 ] = '\0' ;
427+ strncat (var_ident , var_name , sizeof (var_ident ) - 1 );
428+ sanitize_identifier (var_ident );
429+
430+ printf ("\t_Static_assert(sizeof(s->%1$s->%2$s) == %3$lld, \"unexpected size of '%2$s'\");\n" ,
431+ map_ident , var_ident , var_size );
432+ }
433+ }
434+ codegen ("\
435+ \n\
436+ } \n\
437+ \n\
438+ #ifdef __cplusplus \n\
439+ #undef _Static_assert \n\
440+ #endif \n\
441+ " );
442+ }
443+
444+
366445static void codegen_attach_detach (struct bpf_object * obj , const char * obj_name )
367446{
368447 struct bpf_program * prog ;
@@ -641,6 +720,8 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
641720 } \n\
642721 " , obj_name );
643722
723+ codegen_asserts (obj , obj_name );
724+
644725 codegen ("\
645726 \n\
646727 \n\
@@ -1046,9 +1127,17 @@ static int do_skeleton(int argc, char **argv)
10461127 const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
10471128 #endif /* __cplusplus */ \n\
10481129 \n\
1049- #endif /* %2$s */ \n\
10501130 " ,
1051- obj_name , header_guard );
1131+ obj_name );
1132+
1133+ codegen_asserts (obj , obj_name );
1134+
1135+ codegen ("\
1136+ \n\
1137+ \n\
1138+ #endif /* %1$s */ \n\
1139+ " ,
1140+ header_guard );
10521141 err = 0 ;
10531142out :
10541143 bpf_object__close (obj );
0 commit comments