@@ -43,6 +43,13 @@ struct btf_ext {
43
43
__u32 func_info_len ;
44
44
};
45
45
46
+ struct btf_sec_func_info {
47
+ __u32 sec_name_off ;
48
+ __u32 num_func_info ;
49
+ /* Followed by num_func_info number of bpf func_info records */
50
+ __u8 data [0 ];
51
+ };
52
+
46
53
/* The minimum bpf_func_info checked by the loader */
47
54
struct bpf_func_info_min {
48
55
__u32 insn_off ;
@@ -479,41 +486,66 @@ int btf__get_from_id(__u32 id, struct btf **btf)
479
486
return err ;
480
487
}
481
488
482
- static int btf_ext_validate_func_info (const void * finfo , __u32 size ,
483
- btf_print_fn_t err_log )
489
+ static int btf_ext_copy_func_info (struct btf_ext * btf_ext ,
490
+ __u8 * data , __u32 data_size ,
491
+ btf_print_fn_t err_log )
484
492
{
485
- int sec_hdrlen = sizeof (struct btf_sec_func_info );
486
- __u32 size_left , num_records , record_size ;
493
+ const struct btf_ext_header * hdr = (struct btf_ext_header * )data ;
487
494
const struct btf_sec_func_info * sinfo ;
488
- __u64 total_record_size ;
495
+ __u32 info_left , record_size ;
496
+ /* The start of the info sec (including the __u32 record_size). */
497
+ const void * info ;
498
+
499
+ /* data and data_size do not include btf_ext_header from now on */
500
+ data = data + hdr -> hdr_len ;
501
+ data_size -= hdr -> hdr_len ;
502
+
503
+ if (hdr -> func_info_off & 0x03 ) {
504
+ elog ("BTF.ext func_info section is not aligned to 4 bytes\n" );
505
+ return - EINVAL ;
506
+ }
507
+
508
+ if (data_size < hdr -> func_info_off ||
509
+ hdr -> func_info_len > data_size - hdr -> func_info_off ) {
510
+ elog ("func_info section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n" ,
511
+ hdr -> func_info_off , hdr -> func_info_len );
512
+ return - EINVAL ;
513
+ }
514
+
515
+ info = data + hdr -> func_info_off ;
516
+ info_left = hdr -> func_info_len ;
489
517
490
518
/* At least a func_info record size */
491
- if (size < sizeof (__u32 )) {
519
+ if (info_left < sizeof (__u32 )) {
492
520
elog ("BTF.ext func_info record size not found" );
493
521
return - EINVAL ;
494
522
}
495
523
496
- /* The record size needs to meet below minimum standard */
497
- record_size = * (__u32 * )finfo ;
524
+ /* The record size needs to meet the minimum standard */
525
+ record_size = * (__u32 * )info ;
498
526
if (record_size < sizeof (struct bpf_func_info_min ) ||
499
- record_size % sizeof ( __u32 ) ) {
527
+ record_size & 0x03 ) {
500
528
elog ("BTF.ext func_info invalid record size" );
501
529
return - EINVAL ;
502
530
}
503
531
504
- sinfo = finfo + sizeof (__u32 );
505
- size_left = size - sizeof (__u32 );
532
+ sinfo = info + sizeof (__u32 );
533
+ info_left -= sizeof (__u32 );
506
534
507
535
/* If no func_info records, return failure now so .BTF.ext
508
536
* won't be used.
509
537
*/
510
- if (!size_left ) {
538
+ if (!info_left ) {
511
539
elog ("BTF.ext no func info records" );
512
540
return - EINVAL ;
513
541
}
514
542
515
- while (size_left ) {
516
- if (size_left < sec_hdrlen ) {
543
+ while (info_left ) {
544
+ unsigned int sec_hdrlen = sizeof (struct btf_sec_func_info );
545
+ __u64 total_record_size ;
546
+ __u32 num_records ;
547
+
548
+ if (info_left < sec_hdrlen ) {
517
549
elog ("BTF.ext func_info header not found" );
518
550
return - EINVAL ;
519
551
}
@@ -526,24 +558,30 @@ static int btf_ext_validate_func_info(const void *finfo, __u32 size,
526
558
527
559
total_record_size = sec_hdrlen +
528
560
(__u64 )num_records * record_size ;
529
- if (size_left < total_record_size ) {
561
+ if (info_left < total_record_size ) {
530
562
elog ("incorrect BTF.ext num_func_info" );
531
563
return - EINVAL ;
532
564
}
533
565
534
- size_left -= total_record_size ;
566
+ info_left -= total_record_size ;
535
567
sinfo = (void * )sinfo + total_record_size ;
536
568
}
537
569
570
+ btf_ext -> func_info_len = hdr -> func_info_len - sizeof (__u32 );
571
+ btf_ext -> func_info_rec_size = record_size ;
572
+ btf_ext -> func_info = malloc (btf_ext -> func_info_len );
573
+ if (!btf_ext -> func_info )
574
+ return - ENOMEM ;
575
+ memcpy (btf_ext -> func_info , info + sizeof (__u32 ),
576
+ btf_ext -> func_info_len );
577
+
538
578
return 0 ;
539
579
}
540
580
541
581
static int btf_ext_parse_hdr (__u8 * data , __u32 data_size ,
542
582
btf_print_fn_t err_log )
543
583
{
544
584
const struct btf_ext_header * hdr = (struct btf_ext_header * )data ;
545
- __u32 meta_left , last_func_info_pos ;
546
- void * finfo ;
547
585
548
586
if (data_size < offsetof(struct btf_ext_header , func_info_off ) ||
549
587
data_size < hdr -> hdr_len ) {
@@ -566,34 +604,12 @@ static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,
566
604
return - ENOTSUP ;
567
605
}
568
606
569
- meta_left = data_size - hdr -> hdr_len ;
570
- if (!meta_left ) {
607
+ if (data_size == hdr -> hdr_len ) {
571
608
elog ("BTF.ext has no data\n" );
572
609
return - EINVAL ;
573
610
}
574
611
575
- if (meta_left < hdr -> func_info_off ) {
576
- elog ("Invalid BTF.ext func_info section offset:%u\n" ,
577
- hdr -> func_info_off );
578
- return - EINVAL ;
579
- }
580
-
581
- if (hdr -> func_info_off & 0x03 ) {
582
- elog ("BTF.ext func_info section is not aligned to 4 bytes\n" );
583
- return - EINVAL ;
584
- }
585
-
586
- last_func_info_pos = hdr -> hdr_len + hdr -> func_info_off +
587
- hdr -> func_info_len ;
588
- if (last_func_info_pos > data_size ) {
589
- elog ("Invalid BTF.ext func_info section size:%u\n" ,
590
- hdr -> func_info_len );
591
- return - EINVAL ;
592
- }
593
-
594
- finfo = data + hdr -> hdr_len + hdr -> func_info_off ;
595
- return btf_ext_validate_func_info (finfo , hdr -> func_info_len ,
596
- err_log );
612
+ return 0 ;
597
613
}
598
614
599
615
void btf_ext__free (struct btf_ext * btf_ext )
@@ -607,10 +623,7 @@ void btf_ext__free(struct btf_ext *btf_ext)
607
623
608
624
struct btf_ext * btf_ext__new (__u8 * data , __u32 size , btf_print_fn_t err_log )
609
625
{
610
- const struct btf_ext_header * hdr ;
611
626
struct btf_ext * btf_ext ;
612
- void * org_fdata , * fdata ;
613
- __u32 hdrlen , size_u32 ;
614
627
int err ;
615
628
616
629
err = btf_ext_parse_hdr (data , size , err_log );
@@ -621,81 +634,18 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
621
634
if (!btf_ext )
622
635
return ERR_PTR (- ENOMEM );
623
636
624
- hdr = (const struct btf_ext_header * )data ;
625
- hdrlen = hdr -> hdr_len ;
626
- size_u32 = sizeof (__u32 );
627
- fdata = malloc (hdr -> func_info_len - size_u32 );
628
- if (!fdata ) {
629
- free (btf_ext );
630
- return ERR_PTR (- ENOMEM );
637
+ err = btf_ext_copy_func_info (btf_ext , data , size , err_log );
638
+ if (err ) {
639
+ btf_ext__free (btf_ext );
640
+ return ERR_PTR (err );
631
641
}
632
642
633
- /* remember record size and copy rest of func_info data */
634
- org_fdata = data + hdrlen + hdr -> func_info_off ;
635
- btf_ext -> func_info_rec_size = * (__u32 * )org_fdata ;
636
- memcpy (fdata , org_fdata + size_u32 , hdr -> func_info_len - size_u32 );
637
- btf_ext -> func_info = fdata ;
638
- btf_ext -> func_info_len = hdr -> func_info_len - size_u32 ;
639
-
640
643
return btf_ext ;
641
644
}
642
645
643
- int btf_ext__reloc_init (struct btf * btf , struct btf_ext * btf_ext ,
644
- const char * sec_name , void * * func_info ,
645
- __u32 * func_info_rec_size , __u32 * func_info_len )
646
- {
647
- __u32 sec_hdrlen = sizeof (struct btf_sec_func_info );
648
- __u32 i , record_size , records_len ;
649
- struct btf_sec_func_info * sinfo ;
650
- const char * info_sec_name ;
651
- __s64 remain_len ;
652
- void * data ;
653
-
654
- record_size = btf_ext -> func_info_rec_size ;
655
- sinfo = btf_ext -> func_info ;
656
- remain_len = btf_ext -> func_info_len ;
657
-
658
- while (remain_len > 0 ) {
659
- records_len = sinfo -> num_func_info * record_size ;
660
- info_sec_name = btf__name_by_offset (btf , sinfo -> sec_name_off );
661
- if (strcmp (info_sec_name , sec_name )) {
662
- remain_len -= sec_hdrlen + records_len ;
663
- sinfo = (void * )sinfo + sec_hdrlen + records_len ;
664
- continue ;
665
- }
666
-
667
- data = malloc (records_len );
668
- if (!data )
669
- return - ENOMEM ;
670
-
671
- memcpy (data , sinfo -> data , records_len );
672
-
673
- /* adjust the insn_off, the data in .BTF.ext is
674
- * the actual byte offset, and the kernel expects
675
- * the offset in term of bpf_insn.
676
- *
677
- * adjust the insn offset only, the rest data will
678
- * be passed to kernel.
679
- */
680
- for (i = 0 ; i < sinfo -> num_func_info ; i ++ ) {
681
- struct bpf_func_info_min * record ;
682
-
683
- record = data + i * record_size ;
684
- record -> insn_off /= sizeof (struct bpf_insn );
685
- }
686
-
687
- * func_info = data ;
688
- * func_info_len = records_len ;
689
- * func_info_rec_size = record_size ;
690
- return 0 ;
691
- }
692
-
693
- return - EINVAL ;
694
- }
695
-
696
- int btf_ext__reloc (struct btf * btf , struct btf_ext * btf_ext ,
697
- const char * sec_name , __u32 insns_cnt ,
698
- void * * func_info , __u32 * func_info_len )
646
+ int btf_ext__reloc_func_info (struct btf * btf , struct btf_ext * btf_ext ,
647
+ const char * sec_name , __u32 insns_cnt ,
648
+ void * * func_info , __u32 * cnt )
699
649
{
700
650
__u32 sec_hdrlen = sizeof (struct btf_sec_func_info );
701
651
__u32 i , record_size , existing_flen , records_len ;
@@ -716,7 +666,7 @@ int btf_ext__reloc(struct btf *btf, struct btf_ext *btf_ext,
716
666
continue ;
717
667
}
718
668
719
- existing_flen = * func_info_len ;
669
+ existing_flen = ( * cnt ) * record_size ;
720
670
data = realloc (* func_info , existing_flen + records_len );
721
671
if (!data )
722
672
return - ENOMEM ;
@@ -734,9 +684,14 @@ int btf_ext__reloc(struct btf *btf, struct btf_ext *btf_ext,
734
684
insns_cnt ;
735
685
}
736
686
* func_info = data ;
737
- * func_info_len = existing_flen + records_len ;
687
+ * cnt += sinfo -> num_func_info ;
738
688
return 0 ;
739
689
}
740
690
741
- return - EINVAL ;
691
+ return - ENOENT ;
692
+ }
693
+
694
+ __u32 btf_ext__func_info_rec_size (const struct btf_ext * btf_ext )
695
+ {
696
+ return btf_ext -> func_info_rec_size ;
742
697
}
0 commit comments