@@ -209,15 +209,36 @@ static int codegen_datasec_def(struct bpf_object *obj,
209
209
return 0 ;
210
210
}
211
211
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
+
212
234
static int codegen_datasecs (struct bpf_object * obj , const char * obj_name )
213
235
{
214
236
struct btf * btf = bpf_object__btf (obj );
215
- int n = btf__type_cnt (btf );
216
237
struct btf_dump * d ;
217
238
struct bpf_map * map ;
218
239
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 ;
221
242
222
243
d = btf_dump__new (btf , codegen_btf_dump_printf , NULL , NULL );
223
244
err = libbpf_get_error (d );
@@ -234,23 +255,7 @@ static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
234
255
if (!get_map_ident (map , map_ident , sizeof (map_ident )))
235
256
continue ;
236
257
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 );
254
259
255
260
/* In some cases (e.g., sections like .rodata.cst16 containing
256
261
* compiler allocated string constants only) there will be
@@ -363,6 +368,73 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
363
368
return map_sz ;
364
369
}
365
370
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
+
366
438
static void codegen_attach_detach (struct bpf_object * obj , const char * obj_name )
367
439
{
368
440
struct bpf_program * prog ;
@@ -639,8 +711,11 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
639
711
} \n\
640
712
return skel; \n\
641
713
} \n\
714
+ \n\
642
715
" , obj_name );
643
716
717
+ codegen_asserts (obj , obj_name );
718
+
644
719
codegen ("\
645
720
\n\
646
721
\n\
@@ -1046,9 +1121,17 @@ static int do_skeleton(int argc, char **argv)
1046
1121
const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
1047
1122
#endif /* __cplusplus */ \n\
1048
1123
\n\
1049
- #endif /* %2$s */ \n\
1050
1124
" ,
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 );
1052
1135
err = 0 ;
1053
1136
out :
1054
1137
bpf_object__close (obj );
0 commit comments