Skip to content

Commit 3fd4fa5

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 3fd4fa5

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

kpatch-build/create-diff-object.c

Lines changed: 13 additions & 7 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,7 +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)
3750+
if (kelf->has_pfe)
37493751
/*
37503752
* Create separate __patchable_function_entries sections
37513753
* for each function in the following loop.
@@ -3858,7 +3860,14 @@ static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf, bool
38583860
* - its lone rela is based on the section symbol
38593861
*/
38603862
sec = create_section_pair(kelf, "__patchable_function_entries", sizeof(void *), 1);
3861-
sec->sh.sh_flags |= SHF_WRITE | SHF_ALLOC | SHF_LINK_ORDER;
3863+
sec->sh.sh_flags |= SHF_WRITE | SHF_ALLOC;
3864+
/*
3865+
* Old linkers don't support mixing ordered and unordered sections, so set
3866+
* the SHF_LINK_ORDER flag only if it is set in the pfe section generated by
3867+
* the compiler.
3868+
*/
3869+
if (kelf->pfe_ordered)
3870+
sec->sh.sh_flags |= SHF_LINK_ORDER;
38623871
rela_sym = sym->sec->secsym;
38633872
rela_offset = 0;
38643873
rela_sym->pfe = sec;
@@ -4158,7 +4167,6 @@ int main(int argc, char *argv[])
41584167
struct section *relasec, *symtab;
41594168
char *orig_obj, *patched_obj, *parent_name;
41604169
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
4161-
bool has_pfe = false;
41624170

41634171
memset(&arguments, 0, sizeof(arguments));
41644172
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -4184,8 +4192,6 @@ int main(int argc, char *argv[])
41844192

41854193
kpatch_set_pfe_link(kelf_orig);
41864194
kpatch_set_pfe_link(kelf_patched);
4187-
if (kelf_patched->has_pfe)
4188-
has_pfe = true;
41894195

41904196
kpatch_find_func_profiling_calls(kelf_orig);
41914197
kpatch_find_func_profiling_calls(kelf_patched);
@@ -4266,7 +4272,7 @@ int main(int argc, char *argv[])
42664272
kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
42674273
kpatch_build_strings_section_data(kelf_out);
42684274

4269-
kpatch_create_ftrace_callsite_sections(kelf_out, has_pfe);
4275+
kpatch_create_ftrace_callsite_sections(kelf_out);
42704276

42714277
/*
42724278
* 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)