Skip to content

Commit 7b3ebf8

Browse files
ZzzMaoswine
authored andcommitted
create-diff-object: Remove the multi_pfe flag.
In ARM64, every function section should have its own pfe section. It is a bug in GCC 11/12 which will only generate a single pfe section for all functions. The bug has been fixed in GCC 13.1. As the create-diff-object is generating the pfe sections on its own, we should also fix this bug, instead of try to repeat the bug. -- Adjusted whitespace in Zimao's proposed code. Signed-off-by: Pete Swain <[email protected]>
1 parent 7357853 commit 7b3ebf8

File tree

2 files changed

+57
-108
lines changed

2 files changed

+57
-108
lines changed

kpatch-build/create-diff-object.c

Lines changed: 52 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ enum subsection {
7070
enum loglevel loglevel = NORMAL;
7171

7272
bool KLP_ARCH;
73-
bool multi_pfe;
7473

7574
int jump_label_errors, static_call_errors;
7675

@@ -3754,114 +3753,68 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
37543753
}
37553754
}
37563755

3757-
/*
3758-
* Allocate the mcount/patchable_function_entry sections which must be done
3759-
* before the patched object is torn down so that the section flags can be
3760-
* copied.
3761-
*/
3762-
static void kpatch_alloc_mcount_sections(struct kpatch_elf *kelf, struct kpatch_elf *kelfout)
3756+
static void kpatch_set_pfe_link(struct kpatch_elf *kelf)
37633757
{
3764-
int nr;
3765-
struct symbol *sym;
3766-
int text_idx = 0;
3758+
struct section* sec;
3759+
struct rela *rela;
37673760

3768-
nr = 0;
3769-
list_for_each_entry(sym, &kelfout->symbols, list) {
3770-
if (sym->type == STT_FUNC && sym->status != SAME &&
3771-
sym->has_func_profiling) {
3772-
text_idx = sym->sec->index;
3773-
nr++;
3761+
list_for_each_entry(sec, &kelf->sections, list) {
3762+
if (strcmp(sec->name, "__patchable_function_entries")) {
3763+
continue;
37743764
}
3775-
}
3776-
3777-
/* create text/rela section pair */
3778-
switch(kelf->arch) {
3779-
case AARCH64: {
3780-
struct section *sec;
3781-
int entries = multi_pfe ? 1 : nr;
3782-
int copies = multi_pfe ? nr : 1;
3783-
int flags = 0, rflags = 0;
37843765

3785-
/*
3786-
* Depending on the compiler the __patchable_function_entries section
3787-
* can be ordered or not, copy this flag to the section we created to
3788-
* avoid:
3789-
* ld: __patchable_function_entries has both ordered [...] and unordered [...] sections
3790-
*/
3791-
sec = find_section_by_name(&kelf->sections, "__patchable_function_entries");
3792-
if (sec) {
3793-
flags = (sec->sh.sh_flags & (SHF_LINK_ORDER|SHF_WRITE));
3794-
if (sec->rela)
3795-
rflags = (sec->rela->sh.sh_flags & (SHF_LINK_ORDER|SHF_WRITE));
3766+
if (!sec->rela) {
3767+
continue;
37963768
}
3797-
3798-
for (nr = 0; nr < copies; nr++) {
3799-
sec = create_section_pair(kelfout,
3800-
"__patchable_function_entries",
3801-
sizeof(void *), entries);
3802-
3803-
sec->sh.sh_flags |= flags;
3804-
if (sec->rela)
3805-
sec->rela->sh.sh_flags |= rflags;
3806-
if (multi_pfe)
3807-
sec->sh.sh_link = 0;
3808-
else
3809-
sec->sh.sh_link = text_idx;
3769+
list_for_each_entry(rela, &sec->rela->relas, list) {
3770+
rela->sym->sec->pfe = sec;
38103771
}
3811-
break;
3812-
}
3813-
case PPC64:
3814-
case X86_64:
3815-
case S390:
3816-
create_section_pair(kelfout, "__mcount_loc", sizeof(void *), nr);
3817-
break;
3818-
default:
3819-
ERROR("unsupported arch\n");
38203772
}
38213773
}
38223774

38233775
/*
3824-
* Populate the mcount sections allocated by kpatch_alloc_mcount_sections()
3825-
* previously.
38263776
* This function basically reimplements the functionality of the Linux
38273777
* recordmcount script, so that patched functions can be recognized by ftrace.
38283778
*
38293779
* TODO: Eventually we can modify recordmount so that it recognizes our bundled
38303780
* sections as valid and does this work for us.
38313781
*/
3832-
static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
3782+
static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
38333783
{
38343784
int nr, index;
3835-
struct section *sec, *relasec;
3785+
struct section *relasec;
38363786
struct symbol *sym;
38373787
struct rela *rela, *mcount_rela;
38383788
void **funcs;
3789+
bool pfe_per_function;
38393790

3840-
switch(kelf->arch) {
3791+
nr = 0;
3792+
list_for_each_entry(sym, &kelf->symbols, list)
3793+
if (sym->type == STT_FUNC && sym->status != SAME &&
3794+
sym->has_func_profiling)
3795+
nr++;
3796+
3797+
switch (kelf->arch) {
38413798
case AARCH64:
3842-
if (multi_pfe)
3843-
sec = NULL;
3844-
else
3845-
sec = find_section_by_name(&kelf->sections,
3846-
"__patchable_function_entries");
3799+
/* For aarch64, we will create separate __patchable_function_entries sections for each symbols. */
3800+
pfe_per_function = true;
3801+
relasec = NULL;
38473802
break;
38483803
case PPC64:
38493804
case X86_64:
38503805
case S390:
3851-
sec = find_section_by_name(&kelf->sections, "__mcount_loc");
3806+
{
3807+
struct section *sec;
3808+
3809+
/* create text/rela section pair */
3810+
sec = create_section_pair(kelf, "__mcount_loc", sizeof(void*), nr);
3811+
relasec = sec->rela;
38523812
break;
3813+
}
38533814
default:
38543815
ERROR("unsupported arch\n");
38553816
}
38563817

3857-
if (multi_pfe) {
3858-
relasec = NULL;
3859-
nr = 0;
3860-
} else {
3861-
relasec = sec->rela;
3862-
nr = (int) (sec->data->d_size / sizeof(void *));
3863-
}
3864-
38653818
/* populate sections */
38663819
index = 0;
38673820
list_for_each_entry(sym, &kelf->symbols, list) {
@@ -3878,6 +3831,7 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
38783831

38793832
switch(kelf->arch) {
38803833
case AARCH64: {
3834+
struct section *sec;
38813835
unsigned char *insn;
38823836
int i;
38833837

@@ -3902,6 +3856,14 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
39023856
ERROR("%s: unexpected instruction in patch section of function\n", sym->name);
39033857
}
39043858

3859+
/* Allocate __patchable_function_entries for symbol */
3860+
sec = create_section_pair(kelf, "__patchable_function_entries", sizeof(void *), 1);
3861+
sec->sh.sh_flags |= SHF_WRITE | SHF_LINK_ORDER;
3862+
/* We will reset this sh_link in the reindex function. */
3863+
sec->sh.sh_link = 0;
3864+
3865+
relasec = sec->rela;
3866+
sym->sec->pfe = sec;
39053867
break;
39063868
}
39073869
case PPC64: {
@@ -3972,18 +3934,6 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
39723934
ERROR("unsupported arch");
39733935
}
39743936

3975-
if (multi_pfe) {
3976-
sec = find_nth_section_by_name(&kelf->sections, nr, "__patchable_function_entries");
3977-
if (!sec)
3978-
ERROR("cannot retrieve pre-allocated __pfe #%d\n", nr);
3979-
3980-
relasec = sec->rela;
3981-
sym->sec->pfe = sec;
3982-
sec->sh.sh_link = sec->index;
3983-
3984-
nr++;
3985-
}
3986-
39873937
/*
39883938
* 'rela' points to the mcount/fentry call.
39893939
*
@@ -3994,9 +3944,8 @@ static void kpatch_populate_mcount_sections(struct kpatch_elf *kelf)
39943944
mcount_rela->type = absolute_rela_type(kelf);
39953945
mcount_rela->addend = insn_offset - sym->sym.st_value;
39963946

3997-
if (multi_pfe) {
3947+
if (pfe_per_function) {
39983948
mcount_rela->offset = 0;
3999-
sec = NULL;
40003949
} else {
40013950
mcount_rela->offset = (unsigned int) (index * sizeof(*funcs));
40023951
}
@@ -4166,19 +4115,21 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
41664115
switch(kelf->arch) {
41674116
case AARCH64: {
41684117
struct section *sec;
4169-
41704118
list_for_each_entry(sec, &kelf->sections, list) {
4171-
if (strcmp(sec->name, "__patchable_function_entries"))
4119+
if (strcmp(sec->name, "__patchable_function_entries")) {
41724120
continue;
4173-
if (multi_pfe && sym->sec->pfe != sec)
4121+
}
4122+
if (sym->sec->pfe != sec) {
41744123
continue;
4175-
if (!sec->rela)
4124+
}
4125+
if (!sec->rela) {
41764126
continue;
4127+
}
41774128

41784129
list_for_each_entry(rela, &sec->rela->relas, list) {
41794130
if (rela->sym->sec && sym->sec == rela->sym->sec) {
41804131
sym->has_func_profiling = 1;
4181-
goto next_symbol;
4132+
goto next_symbol;
41824133
}
41834134
}
41844135
}
@@ -4268,12 +4219,6 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
42684219
return 0;
42694220
}
42704221

4271-
static bool has_multi_pfe(struct kpatch_elf *kelf)
4272-
{
4273-
return !!find_nth_section_by_name(&kelf->sections, 1,
4274-
"__patchable_function_entries");
4275-
}
4276-
42774222
static struct argp argp = { options, parse_opt, args_doc, NULL };
42784223

42794224
int main(int argc, char *argv[])
@@ -4307,7 +4252,10 @@ int main(int argc, char *argv[])
43074252

43084253
kelf_orig = kpatch_elf_open(orig_obj);
43094254
kelf_patched = kpatch_elf_open(patched_obj);
4310-
multi_pfe = has_multi_pfe(kelf_orig) || has_multi_pfe(kelf_patched);
4255+
4256+
kpatch_set_pfe_link(kelf_orig);
4257+
kpatch_set_pfe_link(kelf_patched);
4258+
43114259
kpatch_find_func_profiling_calls(kelf_orig);
43124260
kpatch_find_func_profiling_calls(kelf_patched);
43134261

@@ -4369,9 +4317,6 @@ int main(int argc, char *argv[])
43694317
/* this is destructive to kelf_patched */
43704318
kpatch_migrate_included_elements(kelf_patched, &kelf_out);
43714319

4372-
/* this must be done before kelf_patched is torn down */
4373-
kpatch_alloc_mcount_sections(kelf_patched, kelf_out);
4374-
43754320
/*
43764321
* Teardown kelf_patched since we shouldn't access sections or symbols
43774322
* through it anymore. Don't free however, since our section and symbol
@@ -4390,7 +4335,7 @@ int main(int argc, char *argv[])
43904335
kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
43914336
kpatch_build_strings_section_data(kelf_out);
43924337

4393-
kpatch_populate_mcount_sections(kelf_out);
4338+
kpatch_create_mcount_sections(kelf_out);
43944339

43954340
/*
43964341
* At this point, the set of output sections and symbols is

kpatch-build/kpatch-elf.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,7 @@ void kpatch_dump_kelf(struct kpatch_elf *kelf)
663663
if (sec->rela)
664664
printf(", rela-> %s", sec->rela->name);
665665
}
666+
printf(", pfe-> [%d]", (sec->pfe) == NULL ? -1 : (int)sec->pfe->index);
666667
next:
667668
printf("\n");
668669
}
@@ -672,8 +673,10 @@ void kpatch_dump_kelf(struct kpatch_elf *kelf)
672673
printf("sym %02d, type %d, bind %d, ndx %02d, name %s (%s)",
673674
sym->index, sym->type, sym->bind, sym->sym.st_shndx,
674675
sym->name, status_str(sym->status));
675-
if (sym->sec && (sym->type == STT_FUNC || sym->type == STT_OBJECT))
676+
if (sym->sec && (sym->type == STT_FUNC || sym->type == STT_OBJECT)) {
676677
printf(" -> %s", sym->sec->name);
678+
printf(", profiling: %d", sym->has_func_profiling);
679+
}
677680
printf("\n");
678681
}
679682
}
@@ -942,6 +945,7 @@ struct section *create_section_pair(struct kpatch_elf *kelf, char *name,
942945
relasec->sh.sh_type = SHT_RELA;
943946
relasec->sh.sh_entsize = sizeof(GElf_Rela);
944947
relasec->sh.sh_addralign = 8;
948+
relasec->sh.sh_flags = SHF_INFO_LINK;
945949

946950
/* set text rela section pointer */
947951
sec->rela = relasec;

0 commit comments

Comments
 (0)