@@ -70,6 +70,7 @@ enum subsection {
70
70
enum loglevel loglevel = NORMAL ;
71
71
72
72
bool KLP_ARCH ;
73
+ bool multi_pfe ;
73
74
74
75
/*******************
75
76
* Data structures
@@ -3129,7 +3130,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
3129
3130
if (sym -> bind == STB_LOCAL && symbol .global )
3130
3131
ERROR ("can't find local symbol '%s' in symbol table" , sym -> name );
3131
3132
3132
- log_debug ("lookup for %s: obj=%s sympos=%lu size=%lu" ,
3133
+ log_debug ("lookup for %s: obj=%s sympos=%lu size=%lu\n " ,
3133
3134
sym -> name , symbol .objname , symbol .sympos ,
3134
3135
symbol .size );
3135
3136
@@ -3500,7 +3501,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
3500
3501
ERROR ("can't find symbol '%s' in symbol table" ,
3501
3502
rela -> sym -> name );
3502
3503
3503
- log_debug ("lookup for %s: obj=%s sympos=%lu" ,
3504
+ log_debug ("lookup for %s: obj=%s sympos=%lu\n " ,
3504
3505
rela -> sym -> name , symbol .objname ,
3505
3506
symbol .sympos );
3506
3507
@@ -3654,29 +3655,51 @@ static void kpatch_alloc_mcount_sections(struct kpatch_elf *kelf, struct kpatch_
3654
3655
{
3655
3656
int nr ;
3656
3657
struct symbol * sym ;
3658
+ int text_idx = 0 ;
3657
3659
3658
3660
nr = 0 ;
3659
- list_for_each_entry (sym , & kelfout -> symbols , list )
3661
+ list_for_each_entry (sym , & kelfout -> symbols , list ) {
3660
3662
if (sym -> type == STT_FUNC && sym -> status != SAME &&
3661
- sym -> has_func_profiling )
3663
+ sym -> has_func_profiling ) {
3664
+ text_idx = sym -> sec -> index ;
3662
3665
nr ++ ;
3666
+ }
3667
+ }
3663
3668
3664
3669
/* create text/rela section pair */
3665
3670
switch (kelf -> arch ) {
3666
3671
case AARCH64 : {
3667
- struct section * sec , * tmp ;
3668
-
3669
- sec = create_section_pair (kelfout , "__patchable_function_entries" , sizeof (void * ), nr );
3672
+ struct section * sec ;
3673
+ int entries = multi_pfe ? 1 : nr ;
3674
+ int copies = multi_pfe ? nr : 1 ;
3675
+ int flags = 0 , rflags = 0 ;
3670
3676
3671
3677
/*
3672
3678
* Depending on the compiler the __patchable_function_entries section
3673
3679
* can be ordered or not, copy this flag to the section we created to
3674
3680
* avoid:
3675
3681
* ld: __patchable_function_entries has both ordered [...] and unordered [...] sections
3676
3682
*/
3677
- tmp = find_section_by_name (& kelf -> sections , "__patchable_function_entries" );
3678
- sec -> sh .sh_flags |= (tmp -> sh .sh_flags & SHF_LINK_ORDER );
3679
- sec -> sh .sh_link = 1 ;
3683
+ sec = find_section_by_name (& kelf -> sections , "__patchable_function_entries" );
3684
+ if (sec ) {
3685
+ flags = (sec -> sh .sh_flags & (SHF_LINK_ORDER |SHF_WRITE ));
3686
+ if (sec -> rela )
3687
+ rflags = (sec -> rela -> sh .sh_flags & (SHF_LINK_ORDER |SHF_WRITE ));
3688
+ }
3689
+
3690
+ for (nr = 0 ; nr < copies ; nr ++ ) {
3691
+ sec = create_section_pair (kelfout ,
3692
+ "__patchable_function_entries" ,
3693
+ sizeof (void * ), entries );
3694
+
3695
+ sec -> sh .sh_flags |= flags ;
3696
+ if (sec -> rela )
3697
+ sec -> rela -> sh .sh_flags |= rflags ;
3698
+ if (multi_pfe )
3699
+ sec -> sh .sh_link = 0 ; /* set later */
3700
+ else
3701
+ sec -> sh .sh_link = text_idx ;
3702
+ }
3680
3703
break ;
3681
3704
}
3682
3705
case PPC64 :
@@ -3705,11 +3728,14 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
3705
3728
struct symbol * sym ;
3706
3729
struct rela * rela , * mcount_rela ;
3707
3730
void * * funcs ;
3708
- unsigned long insn_offset = 0 ;
3709
3731
3710
3732
switch (kelf -> arch ) {
3711
3733
case AARCH64 :
3712
- sec = find_section_by_name (& kelf -> sections , "__patchable_function_entries" );
3734
+ if (multi_pfe )
3735
+ sec = NULL ;
3736
+ else
3737
+ sec = find_section_by_name (& kelf -> sections ,
3738
+ "__patchable_function_entries" );
3713
3739
break ;
3714
3740
case PPC64 :
3715
3741
case X86_64 :
@@ -3719,12 +3745,20 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
3719
3745
default :
3720
3746
ERROR ("unsupported arch" );
3721
3747
}
3722
- relasec = sec -> rela ;
3723
- nr = (int ) (sec -> data -> d_size / sizeof (void * ));
3748
+
3749
+ if (multi_pfe ) {
3750
+ relasec = NULL ;
3751
+ nr = 0 ;
3752
+ } else {
3753
+ relasec = sec -> rela ;
3754
+ nr = (int ) (sec -> data -> d_size / sizeof (void * ));
3755
+ }
3724
3756
3725
3757
/* populate sections */
3726
3758
index = 0 ;
3727
3759
list_for_each_entry (sym , & kelf -> symbols , list ) {
3760
+ unsigned long insn_offset = 0 ;
3761
+
3728
3762
if (sym -> type != STT_FUNC || sym -> status == SAME )
3729
3763
continue ;
3730
3764
@@ -3740,7 +3774,6 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
3740
3774
int i ;
3741
3775
3742
3776
insn = sym -> sec -> data -> d_buf ;
3743
- insn_offset = 0 ;
3744
3777
3745
3778
/*
3746
3779
* If BTI (Branch Target Identification) is enabled then there
@@ -3831,6 +3864,20 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
3831
3864
ERROR ("unsupported arch" );
3832
3865
}
3833
3866
3867
+ if (multi_pfe ) {
3868
+ sec = find_nth_section_by_name (& kelf -> sections , nr ,
3869
+ "__patchable_function_entries" );
3870
+ if (!sec )
3871
+ ERROR ("cannot retrieve pre-allocated __pfe #%d\n" ,
3872
+ nr );
3873
+
3874
+ relasec = sec -> rela ;
3875
+ sym -> sec -> pfe = sec ;
3876
+ sec -> sh .sh_link = sec -> index ;
3877
+
3878
+ nr ++ ;
3879
+ }
3880
+
3834
3881
/*
3835
3882
* 'rela' points to the mcount/fentry call.
3836
3883
*
@@ -3840,7 +3887,13 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
3840
3887
mcount_rela -> sym = sym ;
3841
3888
mcount_rela -> type = absolute_rela_type (kelf );
3842
3889
mcount_rela -> addend = insn_offset - sym -> sym .st_value ;
3843
- mcount_rela -> offset = (unsigned int ) (index * sizeof (* funcs ));
3890
+
3891
+ if (multi_pfe ) {
3892
+ mcount_rela -> offset = 0 ;
3893
+ sec = NULL ;
3894
+ } else {
3895
+ mcount_rela -> offset = (unsigned int ) (index * sizeof (* funcs ));
3896
+ }
3844
3897
3845
3898
index ++ ;
3846
3899
}
@@ -3993,27 +4046,34 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
3993
4046
struct symbol * sym ;
3994
4047
struct rela * rela ;
3995
4048
unsigned char * insn ;
4049
+
3996
4050
list_for_each_entry (sym , & kelf -> symbols , list ) {
3997
4051
if (sym -> type != STT_FUNC || !sym -> sec || !sym -> sec -> rela )
3998
4052
continue ;
3999
4053
4000
4054
switch (kelf -> arch ) {
4001
4055
case AARCH64 : {
4002
- struct section * sec = find_section_by_name (& kelf -> sections ,
4003
- "__patchable_function_entries" );
4004
- /*
4005
- * If we can't find the __patchable_function_entries section or
4006
- * there are no relocations in it then not patchable.
4007
- */
4008
- if (!sec || !sec -> rela )
4009
- return ;
4010
- list_for_each_entry (rela , & sec -> rela -> relas , list ) {
4011
- if (rela -> sym -> sec && sym -> sec == rela -> sym -> sec ) {
4012
- sym -> has_func_profiling = 1 ;
4013
- break ;
4056
+ struct section * sec ;
4057
+
4058
+ list_for_each_entry (sec , & kelf -> sections , list ) {
4059
+ if (strcmp (sec -> name , "__patchable_function_entries" ))
4060
+ continue ;
4061
+ if (multi_pfe && sym -> sec -> pfe != sec )
4062
+ continue ;
4063
+ /*
4064
+ * If we can't find the __patchable_function_entries section or
4065
+ * there are no relocations in it then not patchable.
4066
+ */
4067
+ if (!sec -> rela )
4068
+ continue ;
4069
+
4070
+ list_for_each_entry (rela , & sec -> rela -> relas , list ) {
4071
+ if (rela -> sym -> sec && sym -> sec == rela -> sym -> sec ) {
4072
+ sym -> has_func_profiling = 1 ;
4073
+ goto next_symbol ;
4074
+ }
4014
4075
}
4015
4076
}
4016
-
4017
4077
break ;
4018
4078
}
4019
4079
case PPC64 :
@@ -4046,6 +4106,7 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
4046
4106
default :
4047
4107
ERROR ("unsupported arch" );
4048
4108
}
4109
+ next_symbol :;
4049
4110
}
4050
4111
}
4051
4112
@@ -4093,6 +4154,12 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
4093
4154
return 0 ;
4094
4155
}
4095
4156
4157
+ static bool has_multi_pfe (struct kpatch_elf * kelf )
4158
+ {
4159
+ return !!find_nth_section_by_name (& kelf -> sections , 1 ,
4160
+ "__patchable_function_entries" );
4161
+ }
4162
+
4096
4163
static struct argp argp = { options , parse_opt , args_doc , NULL };
4097
4164
4098
4165
int main (int argc , char * argv [])
@@ -4126,6 +4193,7 @@ int main(int argc, char *argv[])
4126
4193
4127
4194
kelf_orig = kpatch_elf_open (orig_obj );
4128
4195
kelf_patched = kpatch_elf_open (patched_obj );
4196
+ multi_pfe = has_multi_pfe (kelf_orig ) || has_multi_pfe (kelf_patched );
4129
4197
kpatch_find_func_profiling_calls (kelf_orig );
4130
4198
kpatch_find_func_profiling_calls (kelf_patched );
4131
4199
0 commit comments