@@ -209,15 +209,36 @@ 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 btf * btf , const char * map_ident )
213+ {
214+ int n = btf__type_cnt (btf ), i ;
215+ char sec_ident [256 ];
216+
217+ for (i = 1 ; i < n ; i ++ ) {
218+ const struct btf_type * t = btf__type_by_id (btf , i );
219+ const char * name ;
220+
221+ if (!btf_is_datasec (t ))
222+ continue ;
223+
224+ name = btf__str_by_offset (btf , t -> name_off );
225+ if (!get_datasec_ident (name , sec_ident , sizeof (sec_ident )))
226+ continue ;
227+
228+ if (strcmp (sec_ident , map_ident ) == 0 )
229+ return t ;
230+ }
231+ return NULL ;
232+ }
233+
212234static int codegen_datasecs (struct bpf_object * obj , const char * obj_name )
213235{
214236 struct btf * btf = bpf_object__btf (obj );
215- int n = btf__type_cnt (btf );
216237 struct btf_dump * d ;
217238 struct bpf_map * map ;
218239 const struct btf_type * sec ;
219- char sec_ident [ 256 ], map_ident [256 ];
220- int i , err = 0 ;
240+ char map_ident [256 ];
241+ int err = 0 ;
221242
222243 d = btf_dump__new (btf , codegen_btf_dump_printf , NULL , NULL );
223244 err = libbpf_get_error (d );
@@ -234,23 +255,7 @@ static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
234255 if (!get_map_ident (map , map_ident , sizeof (map_ident )))
235256 continue ;
236257
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- }
258+ sec = find_type_for_map (btf , map_ident );
254259
255260 /* In some cases (e.g., sections like .rodata.cst16 containing
256261 * compiler allocated string constants only) there will be
@@ -363,6 +368,73 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
363368 return map_sz ;
364369}
365370
371+ /* Emit type size asserts for all top-level fields in memory-mapped internal maps. */
372+ static void codegen_asserts (struct bpf_object * obj , const char * obj_name )
373+ {
374+ struct btf * btf = bpf_object__btf (obj );
375+ struct bpf_map * map ;
376+ struct btf_var_secinfo * sec_var ;
377+ int i , vlen ;
378+ const struct btf_type * sec ;
379+ char map_ident [256 ], var_ident [256 ];
380+
381+ codegen ("\
382+ \n\
383+ __attribute__((unused)) static void \n\
384+ %1$s__assert(struct %1$s *s) \n\
385+ { \n\
386+ #ifdef __cplusplus \n\
387+ #define _Static_assert static_assert \n\
388+ #endif \n\
389+ " , obj_name );
390+
391+ bpf_object__for_each_map (map , obj ) {
392+ if (!bpf_map__is_internal (map ))
393+ continue ;
394+ if (!(bpf_map__map_flags (map ) & BPF_F_MMAPABLE ))
395+ continue ;
396+ if (!get_map_ident (map , map_ident , sizeof (map_ident )))
397+ continue ;
398+
399+ sec = find_type_for_map (btf , map_ident );
400+ if (!sec ) {
401+ /* best effort, couldn't find the type for this map */
402+ continue ;
403+ }
404+
405+ sec_var = btf_var_secinfos (sec );
406+ vlen = btf_vlen (sec );
407+
408+ for (i = 0 ; i < vlen ; i ++ , sec_var ++ ) {
409+ const struct btf_type * var = btf__type_by_id (btf , sec_var -> type );
410+ const char * var_name = btf__name_by_offset (btf , var -> name_off );
411+ long var_size ;
412+
413+ /* static variables are not exposed through BPF skeleton */
414+ if (btf_var (var )-> linkage == BTF_VAR_STATIC )
415+ continue ;
416+
417+ var_size = btf__resolve_size (btf , var -> type );
418+ if (var_size < 0 )
419+ continue ;
420+
421+ var_ident [0 ] = '\0' ;
422+ strncat (var_ident , var_name , sizeof (var_ident ) - 1 );
423+ sanitize_identifier (var_ident );
424+
425+ printf ("\t_Static_assert(sizeof(s->%s->%s) == %ld, \"unexpected size of '%s'\");\n" ,
426+ map_ident , var_ident , var_size , var_ident );
427+ }
428+ }
429+ codegen ("\
430+ \n\
431+ #ifdef __cplusplus \n\
432+ #undef _Static_assert \n\
433+ #endif \n\
434+ } \n\
435+ " );
436+ }
437+
366438static void codegen_attach_detach (struct bpf_object * obj , const char * obj_name )
367439{
368440 struct bpf_program * prog ;
@@ -639,8 +711,11 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
639711 } \n\
640712 return skel; \n\
641713 } \n\
714+ \n\
642715 " , obj_name );
643716
717+ codegen_asserts (obj , obj_name );
718+
644719 codegen ("\
645720 \n\
646721 \n\
@@ -1046,9 +1121,17 @@ static int do_skeleton(int argc, char **argv)
10461121 const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
10471122 #endif /* __cplusplus */ \n\
10481123 \n\
1049- #endif /* %2$s */ \n\
10501124 " ,
1051- obj_name , header_guard );
1125+ obj_name );
1126+
1127+ codegen_asserts (obj , obj_name );
1128+
1129+ codegen ("\
1130+ \n\
1131+ \n\
1132+ #endif /* %1$s */ \n\
1133+ " ,
1134+ header_guard );
10521135 err = 0 ;
10531136out :
10541137 bpf_object__close (obj );
0 commit comments