Skip to content

Commit 9ea87f8

Browse files
committed
create-diff-object: Fix ordering of __patchable_function_entries
Old linkers don't support mixing ordered and unordered sections. This was fixed in binutils, see discussion in [1]. But without this fix, kpatch-build fails with an error like: | ld.bfd: __patchable_function_entries has both ordered | [`__patchable_function_entries' in /builddir/.kpatch/tmp/patch/output.o] | and unordered [`__patchable_function_entries' in | /builddir/.kpatch/tmp/patch/patch-hook.o] sections | ld.bfd: final link failed: bad value Fix this by only setting SHF_LINK_ORDER in the output object if the patched object also has this flag set. Signed-off-by: Puranjay Mohan <pjy@amazon.com>
1 parent e390415 commit 9ea87f8

File tree

3 files changed

+25
-15
lines changed

3 files changed

+25
-15
lines changed

kpatch-build/create-diff-object.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,8 @@ static void kpatch_migrate_included_elements(struct kpatch_elf *kelf, struct kpa
19921992
ERROR("malloc");
19931993
memset(out, 0, sizeof(*out));
19941994
out->arch = kelf->arch;
1995+
out->has_pfe = kelf->has_pfe;
1996+
out->pfe_ordered = kelf->pfe_ordered;
19951997
INIT_LIST_HEAD(&out->sections);
19961998
INIT_LIST_HEAD(&out->symbols);
19971999
INIT_LIST_HEAD(&out->strings);
@@ -3729,7 +3731,7 @@ static void kpatch_set_pfe_link(struct kpatch_elf *kelf)
37293731
* TODO: Eventually we can modify recordmount so that it recognizes our bundled
37303732
* sections as valid and does this work for us.
37313733
*/
3732-
static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf, bool has_pfe)
3734+
static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf)
37333735
{
37343736
int nr, index;
37353737
struct section *sec = NULL;
@@ -3745,13 +3747,7 @@ static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf, bool
37453747
sym->has_func_profiling)
37463748
nr++;
37473749

3748-
if (has_pfe)
3749-
/*
3750-
* Create separate __patchable_function_entries sections
3751-
* for each function in the following loop.
3752-
*/
3753-
kelf->has_pfe = true;
3754-
else
3750+
if (!kelf->has_pfe)
37553751
/*
37563752
* Create a single __mcount_loc section pair for all
37573753
* functions.
@@ -3858,7 +3854,14 @@ static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf, bool
38583854
* - its lone rela is based on the section symbol
38593855
*/
38603856
sec = create_section_pair(kelf, "__patchable_function_entries", sizeof(void *), 1);
3861-
sec->sh.sh_flags |= SHF_WRITE | SHF_ALLOC | SHF_LINK_ORDER;
3857+
sec->sh.sh_flags |= SHF_WRITE | SHF_ALLOC;
3858+
/*
3859+
* Old linkers don't support mixing ordered and unordered sections, so set
3860+
* the SHF_LINK_ORDER flag only if it is set in the pfe section generated by
3861+
* the compiler.
3862+
*/
3863+
if (kelf->pfe_ordered)
3864+
sec->sh.sh_flags |= SHF_LINK_ORDER;
38623865
rela_sym = sym->sec->secsym;
38633866
rela_offset = 0;
38643867
rela_sym->pfe = sec;
@@ -4158,7 +4161,6 @@ int main(int argc, char *argv[])
41584161
struct section *relasec, *symtab;
41594162
char *orig_obj, *patched_obj, *parent_name;
41604163
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
4161-
bool has_pfe = false;
41624164

41634165
memset(&arguments, 0, sizeof(arguments));
41644166
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -4184,8 +4186,6 @@ int main(int argc, char *argv[])
41844186

41854187
kpatch_set_pfe_link(kelf_orig);
41864188
kpatch_set_pfe_link(kelf_patched);
4187-
if (kelf_patched->has_pfe)
4188-
has_pfe = true;
41894189

41904190
kpatch_find_func_profiling_calls(kelf_orig);
41914191
kpatch_find_func_profiling_calls(kelf_patched);
@@ -4266,7 +4266,7 @@ int main(int argc, char *argv[])
42664266
kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
42674267
kpatch_build_strings_section_data(kelf_out);
42684268

4269-
kpatch_create_ftrace_callsite_sections(kelf_out, has_pfe);
4269+
kpatch_create_ftrace_callsite_sections(kelf_out);
42704270

42714271
/*
42724272
* At this point, the set of output sections and symbols is

kpatch-build/kpatch-elf.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ struct kpatch_elf *kpatch_elf_open(const char *name)
559559
int fd;
560560
struct kpatch_elf *kelf;
561561
struct section *relasec;
562+
struct section *pfesec;
562563
GElf_Ehdr ehdr;
563564

564565
fd = open(name, O_RDONLY);
@@ -614,9 +615,17 @@ struct kpatch_elf *kpatch_elf_open(const char *name)
614615
* These sections aren't used by ftrace on this arch, so do not
615616
* bother reading/writing them for x86_64.
616617
*/
617-
if (kelf->arch != X86_64)
618-
if (find_section_by_name(&kelf->sections, "__patchable_function_entries"))
618+
if (kelf->arch != X86_64) {
619+
pfesec = find_section_by_name(&kelf->sections, "__patchable_function_entries");
620+
if (pfesec) {
619621
kelf->has_pfe = true;
622+
/*
623+
* Check if the pfe section generated by the toolchain has the SHF_LINK_ORDER
624+
* flag set. This info is used while generating pfe sections in the diff object.
625+
*/
626+
kelf->pfe_ordered = !!(pfesec->sh.sh_flags & SHF_LINK_ORDER);
627+
}
628+
}
620629

621630
return kelf;
622631
}

kpatch-build/kpatch-elf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ struct kpatch_elf {
127127
Elf_Data *symtab_shndx;
128128
int fd;
129129
bool has_pfe;
130+
bool pfe_ordered;
130131
};
131132

132133
/*******************

0 commit comments

Comments
 (0)