@@ -209,15 +209,38 @@ 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 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
+
212
236
static int codegen_datasecs (struct bpf_object * obj , const char * obj_name )
213
237
{
214
238
struct btf * btf = bpf_object__btf (obj );
215
- int n = btf__type_cnt (btf );
216
239
struct btf_dump * d ;
217
240
struct bpf_map * map ;
218
241
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 ;
221
244
222
245
d = btf_dump__new (btf , codegen_btf_dump_printf , NULL , NULL );
223
246
err = libbpf_get_error (d );
@@ -234,23 +257,7 @@ static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
234
257
if (!get_map_ident (map , map_ident , sizeof (map_ident )))
235
258
continue ;
236
259
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 );
254
261
255
262
/* In some cases (e.g., sections like .rodata.cst16 containing
256
263
* compiler allocated string constants only) there will be
@@ -363,6 +370,78 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
363
370
return map_sz ;
364
371
}
365
372
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
+
366
445
static void codegen_attach_detach (struct bpf_object * obj , const char * obj_name )
367
446
{
368
447
struct bpf_program * prog ;
@@ -641,6 +720,8 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
641
720
} \n\
642
721
" , obj_name );
643
722
723
+ codegen_asserts (obj , obj_name );
724
+
644
725
codegen ("\
645
726
\n\
646
727
\n\
@@ -1046,9 +1127,17 @@ static int do_skeleton(int argc, char **argv)
1046
1127
const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
1047
1128
#endif /* __cplusplus */ \n\
1048
1129
\n\
1049
- #endif /* %2$s */ \n\
1050
1130
" ,
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 );
1052
1141
err = 0 ;
1053
1142
out :
1054
1143
bpf_object__close (obj );
0 commit comments