From 42902d0fccd8a4889b5923aeff622681851ad68c Mon Sep 17 00:00:00 2001 From: Jessica Yu Date: Mon, 23 Jan 2017 12:43:24 -0800 Subject: [PATCH] create-diff-object: create intermediate .kpatch.arch section In addition to .kpatch.relocations and .kpatch.symbols, have create-diff-object create an .kpatch.arch section. This section can be used to create .klp.arch. sections that are required for klp modules built for versions >= 4.9. Each entry in the .kpatch.arch section represents an arch-specific section (.altinstructions or .parainstructions) and contains a pointer to the arch-specific section itself (see kpatch_arch struct member 'sec') and a pointer to the objname string (see kpatch_arch struct member 'objname'). This is enough information to be able to build .klp.arch. sections in a later phase of kpatch-build. --- kpatch-build/create-diff-object.c | 53 ++++++++++++++++++++++++++++++ kpatch-build/kpatch-intermediate.h | 5 +++ 2 files changed, 58 insertions(+) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 423b09e..a9b029e 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -1584,6 +1584,8 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf, /* include both rela and base sections */ sec->include = 1; sec->base->include = 1; + /* include secsym so .kpatch.arch relas can point to section symbols */ + sec->base->secsym->include = 1; /* * Update text section data buf and size. @@ -1707,6 +1709,56 @@ static void kpatch_mark_ignored_functions_same(struct kpatch_elf *kelf) } } +static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *objname) +{ + struct special_section *special; + struct kpatch_arch *entries; + struct symbol *strsym; + struct section *sec, *karch_sec; + struct rela *rela; + int nr, index = 0; + + nr = sizeof(special_sections) / sizeof(special_sections[0]); + karch_sec = create_section_pair(kelf, ".kpatch.arch", sizeof(*entries), nr); + entries = karch_sec->data->d_buf; + + /* lookup strings symbol */ + strsym = find_symbol_by_name(&kelf->symbols, ".kpatch.strings"); + if (!strsym) + ERROR("can't find .kpatch.strings symbol"); + + for (special = special_sections; special->name; special++) { + if (strcmp(special->name, ".parainstructions") && + strcmp(special->name, ".altinstructions")) + continue; + + sec = find_section_by_name(&kelf->sections, special->name); + if (!sec) + continue; + + /* entries[index].sec */ + ALLOC_LINK(rela, &karch_sec->rela->relas); + rela->sym = sec->secsym; + rela->type = R_X86_64_64; + rela->addend = 0; + rela->offset = index * sizeof(*entries) + \ + offsetof(struct kpatch_arch, sec); + + /* entries[index].objname */ + ALLOC_LINK(rela, &karch_sec->rela->relas); + rela->sym = strsym; + rela->type = R_X86_64_64; + rela->addend = offset_of_string(&kelf->strings, objname); + rela->offset = index * sizeof(*entries) + \ + offsetof(struct kpatch_arch, objname); + + index++; + } + + karch_sec->data->d_size = index * sizeof(struct kpatch_arch); + karch_sec->sh.sh_size = karch_sec->data->d_size; +} + static void kpatch_process_special_sections(struct kpatch_elf *kelf) { struct special_section *special; @@ -2462,6 +2514,7 @@ int main(int argc, char *argv[]) kpatch_create_strings_elements(kelf_out); kpatch_create_patches_sections(kelf_out, lookup, hint, objname); kpatch_create_intermediate_sections(kelf_out, lookup, hint, objname, pmod_name); + kpatch_create_kpatch_arch_section(kelf_out, objname); kpatch_create_hooks_objname_rela(kelf_out, objname); kpatch_build_strings_section_data(kelf_out); diff --git a/kpatch-build/kpatch-intermediate.h b/kpatch-build/kpatch-intermediate.h index f6ea34f..87eeff3 100644 --- a/kpatch-build/kpatch-intermediate.h +++ b/kpatch-build/kpatch-intermediate.h @@ -40,4 +40,9 @@ struct kpatch_relocation { char *objname; /* object to which this rela applies to */ struct kpatch_symbol *ksym; }; + +struct kpatch_arch { + unsigned long sec; + char *objname; +}; #endif /* _KPATCH_ELF_H_ */