diff --git a/kmod/patch/Makefile b/kmod/patch/Makefile index f02dda1..f8e03f8 100644 --- a/kmod/patch/Makefile +++ b/kmod/patch/Makefile @@ -3,9 +3,9 @@ KPATCH_BUILD ?= /lib/modules/$(shell uname -r)/build KPATCH_MAKE = $(MAKE) -C $(KPATCH_BUILD) M=$(PWD) LDFLAGS += $(KPATCH_LDFLAGS) -# ppc64le kernel modules are expected to compiled with -# -mcmodel=large flag. This enable 64-bit relocations, -# instead of 32-bit offset from TOC pointer. +# ppc64le kernel modules are expected to compile with the +# -mcmodel=large flag. This enables 64-bit relocations +# instead of a 32-bit offset from the TOC pointer. PROCESSOR = $(shell uname -p) ifeq ($(PROCESSOR), ppc64le) KBUILD_CFLAGS_MODULE += -mcmodel=large diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 56cd166..97781fd 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -184,10 +184,11 @@ static int rela_equal(struct rela *rela1, struct rela *rela2) * 00000000000000b4 000000b90000000a R_PPC64_REL24 0000000000000000 printk + 0 * 00000000000000bc 000000a10000000a R_PPC64_REL24 0000000000000000 dump_stack + 0 * - * with -mcmodel=large on ppc64le, gcc might generate entries in .toc section for symbol - * reference in relocation sections. There are chances of symbol referenced by toc + offset - * may point to different symbols in original and patched .o. Compare the symbols by - * reading its corresponding toc + offset rela from .toc section. + * With -mcmodel=large on ppc64le, GCC might generate entries in the .toc + * section for relocation symbol references. The .toc offsets may change + * between the original and patched .o, so comparing ".toc + offset" isn't + * right. Compare the .toc-based symbols by reading the corresponding relas + * from the .toc section. */ if (!strcmp(rela1->sym->name, ".toc") && !strcmp(rela2->sym->name, ".toc")) { @@ -237,9 +238,8 @@ static void kpatch_compare_correlated_rela_section(struct section *sec) struct rela *rela1, *rela2 = NULL; /* - * Don't compare relocation entries for .toc section. - * .toc and .rela.toc sections are included as standard - * elements. + * On ppc64le, don't compare the .rela.toc section. The .toc and + * .rela.toc sections are included as standard elements. */ if (!strcmp(sec->name, ".rela.toc")) { sec->status = SAME; @@ -1011,10 +1011,12 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf) #ifdef __powerpc__ /* - * With -mcmodel=large, the relative relocation or - * R_PPC64_REL24 type is limited to functions only. - * rela->sym->sec should have been replaced with it's - * section symbol already. If not bail out. + * With -mcmodel=large, R_PPC64_REL24 is only used for + * functions. Assuming the function is bundled in a + * section, the section symbol should have been + * replaced with a text symbol already. Otherwise, + * bail out. If we hit this situation, more core is + * needed here to calculate the value of 'add_off'. */ if (rela->type == R_PPC64_REL24) ERROR("Unexpected relocation type R_PPC64_REL24 for %s\n", rela->sym->name); @@ -1220,9 +1222,9 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf) } /* - * rela.toc section holds reference to symbols, - * referred by function section relocation - * entries. Include all of the symbols. + * On ppc64le, the .rela.toc section refers to symbols which + * are needed for function symbol relocations. Include all the + * symbols. */ if (!strcmp(sec->name, ".rela.toc")) { @@ -2254,8 +2256,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, sym_objname = objname; /* - * function prologue generated by gcc6 on ppc64le has - * the sequence: + * On ppc64le, the function prologue generated by GCC 6 + * has the sequence: * * .globl my_func * .type my_func, @function @@ -2264,12 +2266,10 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, * .reloc ., R_PPC64_ENTRY ; optional * ld r2,-8(r12) * add r2,r2,r12 - * .localentry my_func, .-my_func + * .localentry my_func, .-my_func * - * first entry past function global entry point is optional - * and has the relocation type R_PPC64_ENTRY. We should *not* - * skip this entry while building up the rela list, rather - * skip it's lookup. + * The R_PPC64_ENTRY is optional and its symbol might + * have an empty name. Leave it as a normal rela. */ if (rela->type == R_PPC64_ENTRY) continue; @@ -2291,17 +2291,19 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, */ #ifdef __powerpc__ /* - * An exported symbol, might be local to an object file - * and any access to the function might be through localentry - * (toc+offset) instead of global offset. + * An exported symbol might be local to an + * object file and any access to the function + * might be through localentry (toc+offset) + * instead of global offset. * * fs/proc/proc_sysctl::sysctl_head_grab: * 166: 0000000000000000 256 FUNC GLOBAL DEFAULT [: 8] 42 unregister_sysctl_table * 167: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND .TOC. * - * These type of function have the sym->type == STT_FUNC, treat them as local - * symbol. This creates an entry under klp.relocations and relocation - * is handled by livepatch. + * These type of symbols have a type of + * STT_FUNC. Treat them like local symbols. + * They will be handled by the livepatch + * relocation code. */ if (lookup_is_exported_symbol(table, rela->sym->name)) { if (rela->sym->type != STT_FUNC) diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c index 9c1187e..73ceb0e 100644 --- a/kpatch-build/create-klp-module.c +++ b/kpatch-build/create-klp-module.c @@ -201,8 +201,10 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section * 0000000000000058 0000003900000026 R_PPC64_ADDR64 0000000000000000 __per_cpu_offset + 0 * [...] * - * when more .o files are linked together, the .toc entries might get re-arranged. Capture new .toc rela - * offset value, which will be used below to setting the rela->addend. */ + * On ppc64le, when .o files are linked together, the .toc + * entries might get re-arranged. Capture the new .toc rela + * offset value, which is used below to set the rela->addend. + */ toc_offset = rela->addend; base = rela->sym->sec; @@ -245,10 +247,11 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section rela->offset = krelas[index].offset; /* - * gcc6 adds offset for 0x8 for every local function entry in - * .toc section, for avoiding setup of toc but when the previously - * local function becomes global, toc is anyways setup. So remove - * the wrong addend. + * GCC 6+ adds 0x8 to the offset of every local function entry + * in the .toc section, for avoiding the setup of the toc when + * the function is called locally. But when the previously + * local function becomes global, we don't want to skip the + * .toc setup anymore. */ if (!strcmp(base->name, ".toc") && rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) { diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 55a19bf..a3eb7a3 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -160,12 +160,12 @@ gcc_version_check() { return 1 fi - # On ppc64le, livepatch relies on gcc support for -mprofile-kernel flag. - # Script with differnet checks is run during kernel build, to ensure that - # the required gcc supports is available. This check is done during kernel - # build by: - # /arch/powerpc/tools/gcc-check-mprofile-kernel.sh - # Postpond the check until kernel build, instead of duplicating it here. + # On ppc64le, livepatch needs the GCC -mprofile-kernel flag. A script + # is run during the kernel build to ensure the flag is present: + # + # /arch/powerpc/tools/gcc-check-mprofile-kernel.sh + # + # Postpone the check to the kernel build instead of duplicating it here. if [[ $ARCH = "ppc64le" ]]; then return else diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c index bd249de..72ed62f 100644 --- a/kpatch-build/kpatch-elf.c +++ b/kpatch-build/kpatch-elf.c @@ -85,8 +85,7 @@ int is_debug_section(struct section *sec) (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2) /* - * function prologue generated by gcc6 on ppc64le has - * the sequence: + * On ppc64le, the function prologue generated by GCC 6+ has the sequence: * * .globl my_func * .type my_func, @function @@ -95,15 +94,12 @@ int is_debug_section(struct section *sec) * .reloc ., R_PPC64_ENTRY ; optional * ld r2,-8(r12) * add r2,r2,r12 - * .localentry my_func, .-my_func + * .localentry my_func, .-my_func * - * my_func is resolved by .TOC.-my_func to a 64-bit offset stored - * above the global entry point. my_func st_value is set 0x8, for - * calling into the .localentry of the function. - * - * Number of instructions between global and local entry point of a - * function is mostly 8 instructions. i.e st_other == 3. The count of - * instruction can be decoded only for local function symbols. + * my_func is the global entry point, which, when called, sets up the TOC. + * .localentry is the local entry point, for calls to the function from within + * the object file. The local entry point is 8 bytes after the global entry + * point. */ static int is_localentry_sym(struct symbol *sym) { @@ -381,6 +377,7 @@ void kpatch_create_symbol_list(struct kpatch_elf *kelf) } sym->sec->sym = sym; + } else if (sym->type == STT_SECTION) { sym->sec->secsym = sym; /* use the section name as the symbol name */ diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc index e796fa9..e91f4b2 100755 --- a/kpatch-build/kpatch-gcc +++ b/kpatch-build/kpatch-gcc @@ -15,9 +15,11 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then while [ "$#" -gt 0 ]; do if [ "$1" = "-o" ]; then obj=$2 - # skip copying the original .o files, when .tmp_mc_*.o - # is passed from recordmcount.pl. + + # skip copying the temporary .o files created by + # recordmcount.pl [[ $obj = */.tmp_mc_*.o ]] && break; + [[ $obj = */.tmp_*.o ]] && obj=${obj/.tmp_/} case "$obj" in *.mod.o|\