kpatch-build: clarify ppc64le comments

Clarify some of the comment wording in the new ppc64le code.
This commit is contained in:
Josh Poimboeuf 2017-07-25 11:38:48 -05:00
parent e3ccff0cab
commit 339938c0a9
6 changed files with 58 additions and 54 deletions

View File

@ -3,9 +3,9 @@ KPATCH_BUILD ?= /lib/modules/$(shell uname -r)/build
KPATCH_MAKE = $(MAKE) -C $(KPATCH_BUILD) M=$(PWD) KPATCH_MAKE = $(MAKE) -C $(KPATCH_BUILD) M=$(PWD)
LDFLAGS += $(KPATCH_LDFLAGS) LDFLAGS += $(KPATCH_LDFLAGS)
# ppc64le kernel modules are expected to compiled with # ppc64le kernel modules are expected to compile with the
# -mcmodel=large flag. This enable 64-bit relocations, # -mcmodel=large flag. This enables 64-bit relocations
# instead of 32-bit offset from TOC pointer. # instead of a 32-bit offset from the TOC pointer.
PROCESSOR = $(shell uname -p) PROCESSOR = $(shell uname -p)
ifeq ($(PROCESSOR), ppc64le) ifeq ($(PROCESSOR), ppc64le)
KBUILD_CFLAGS_MODULE += -mcmodel=large KBUILD_CFLAGS_MODULE += -mcmodel=large

View File

@ -184,10 +184,11 @@ static int rela_equal(struct rela *rela1, struct rela *rela2)
* 00000000000000b4 000000b90000000a R_PPC64_REL24 0000000000000000 printk + 0 * 00000000000000b4 000000b90000000a R_PPC64_REL24 0000000000000000 printk + 0
* 00000000000000bc 000000a10000000a R_PPC64_REL24 0000000000000000 dump_stack + 0 * 00000000000000bc 000000a10000000a R_PPC64_REL24 0000000000000000 dump_stack + 0
* *
* with -mcmodel=large on ppc64le, gcc might generate entries in .toc section for symbol * With -mcmodel=large on ppc64le, GCC might generate entries in the .toc
* reference in relocation sections. There are chances of symbol referenced by toc + offset * section for relocation symbol references. The .toc offsets may change
* may point to different symbols in original and patched .o. Compare the symbols by * between the original and patched .o, so comparing ".toc + offset" isn't
* reading its corresponding toc + offset rela from .toc section. * right. Compare the .toc-based symbols by reading the corresponding relas
* from the .toc section.
*/ */
if (!strcmp(rela1->sym->name, ".toc") && if (!strcmp(rela1->sym->name, ".toc") &&
!strcmp(rela2->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; struct rela *rela1, *rela2 = NULL;
/* /*
* Don't compare relocation entries for .toc section. * On ppc64le, don't compare the .rela.toc section. The .toc and
* .toc and .rela.toc sections are included as standard * .rela.toc sections are included as standard elements.
* elements.
*/ */
if (!strcmp(sec->name, ".rela.toc")) { if (!strcmp(sec->name, ".rela.toc")) {
sec->status = SAME; sec->status = SAME;
@ -1011,10 +1011,12 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
#ifdef __powerpc__ #ifdef __powerpc__
/* /*
* With -mcmodel=large, the relative relocation or * With -mcmodel=large, R_PPC64_REL24 is only used for
* R_PPC64_REL24 type is limited to functions only. * functions. Assuming the function is bundled in a
* rela->sym->sec should have been replaced with it's * section, the section symbol should have been
* section symbol already. If not bail out. * 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) if (rela->type == R_PPC64_REL24)
ERROR("Unexpected relocation type R_PPC64_REL24 for %s\n", rela->sym->name); 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, * On ppc64le, the .rela.toc section refers to symbols which
* referred by function section relocation * are needed for function symbol relocations. Include all the
* entries. Include all of the symbols. * symbols.
*/ */
if (!strcmp(sec->name, ".rela.toc")) if (!strcmp(sec->name, ".rela.toc"))
{ {
@ -2254,8 +2256,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
sym_objname = objname; sym_objname = objname;
/* /*
* function prologue generated by gcc6 on ppc64le has * On ppc64le, the function prologue generated by GCC 6
* the sequence: * has the sequence:
* *
* .globl my_func * .globl my_func
* .type my_func, @function * .type my_func, @function
@ -2264,12 +2266,10 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
* .reloc ., R_PPC64_ENTRY ; optional * .reloc ., R_PPC64_ENTRY ; optional
* ld r2,-8(r12) * ld r2,-8(r12)
* add r2,r2,r12 * add r2,r2,r12
* .localentry my_func, .-my_func * .localentry my_func, .-my_func
* *
* first entry past function global entry point is optional * The R_PPC64_ENTRY is optional and its symbol might
* and has the relocation type R_PPC64_ENTRY. We should *not* * have an empty name. Leave it as a normal rela.
* skip this entry while building up the rela list, rather
* skip it's lookup.
*/ */
if (rela->type == R_PPC64_ENTRY) if (rela->type == R_PPC64_ENTRY)
continue; continue;
@ -2291,17 +2291,19 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
*/ */
#ifdef __powerpc__ #ifdef __powerpc__
/* /*
* An exported symbol, might be local to an object file * An exported symbol might be local to an
* and any access to the function might be through localentry * object file and any access to the function
* (toc+offset) instead of global offset. * might be through localentry (toc+offset)
* instead of global offset.
* *
* fs/proc/proc_sysctl::sysctl_head_grab: * fs/proc/proc_sysctl::sysctl_head_grab:
* 166: 0000000000000000 256 FUNC GLOBAL DEFAULT [<localentry>: 8] 42 unregister_sysctl_table * 166: 0000000000000000 256 FUNC GLOBAL DEFAULT [<localentry>: 8] 42 unregister_sysctl_table
* 167: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND .TOC. * 167: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND .TOC.
* *
* These type of function have the sym->type == STT_FUNC, treat them as local * These type of symbols have a type of
* symbol. This creates an entry under klp.relocations and relocation * STT_FUNC. Treat them like local symbols.
* is handled by livepatch. * They will be handled by the livepatch
* relocation code.
*/ */
if (lookup_is_exported_symbol(table, rela->sym->name)) { if (lookup_is_exported_symbol(table, rela->sym->name)) {
if (rela->sym->type != STT_FUNC) if (rela->sym->type != STT_FUNC)

View File

@ -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 * 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 * On ppc64le, when .o files are linked together, the .toc
* offset value, which will be used below to setting the rela->addend. */ * 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; toc_offset = rela->addend;
base = rela->sym->sec; 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; rela->offset = krelas[index].offset;
/* /*
* gcc6 adds offset for 0x8 for every local function entry in * GCC 6+ adds 0x8 to the offset of every local function entry
* .toc section, for avoiding setup of toc but when the previously * in the .toc section, for avoiding the setup of the toc when
* local function becomes global, toc is anyways setup. So remove * the function is called locally. But when the previously
* the wrong addend. * local function becomes global, we don't want to skip the
* .toc setup anymore.
*/ */
if (!strcmp(base->name, ".toc") && if (!strcmp(base->name, ".toc") &&
rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) { rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) {

View File

@ -160,12 +160,12 @@ gcc_version_check() {
return 1 return 1
fi fi
# On ppc64le, livepatch relies on gcc support for -mprofile-kernel flag. # On ppc64le, livepatch needs the GCC -mprofile-kernel flag. A script
# Script with differnet checks is run during kernel build, to ensure that # is run during the kernel build to ensure the flag is present:
# the required gcc supports is available. This check is done during kernel #
# build by: # <linux>/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
# <linux-sources>/arch/powerpc/tools/gcc-check-mprofile-kernel.sh #
# Postpond the check until kernel build, instead of duplicating it here. # Postpone the check to the kernel build instead of duplicating it here.
if [[ $ARCH = "ppc64le" ]]; then if [[ $ARCH = "ppc64le" ]]; then
return return
else else

View File

@ -85,8 +85,7 @@ int is_debug_section(struct section *sec)
(((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2) (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
/* /*
* function prologue generated by gcc6 on ppc64le has * On ppc64le, the function prologue generated by GCC 6+ has the sequence:
* the sequence:
* *
* .globl my_func * .globl my_func
* .type my_func, @function * .type my_func, @function
@ -95,15 +94,12 @@ int is_debug_section(struct section *sec)
* .reloc ., R_PPC64_ENTRY ; optional * .reloc ., R_PPC64_ENTRY ; optional
* ld r2,-8(r12) * ld r2,-8(r12)
* add r2,r2,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 * my_func is the global entry point, which, when called, sets up the TOC.
* above the global entry point. my_func st_value is set 0x8, for * .localentry is the local entry point, for calls to the function from within
* calling into the .localentry of the function. * the object file. The local entry point is 8 bytes after the global entry
* * point.
* 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.
*/ */
static int is_localentry_sym(struct symbol *sym) 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; sym->sec->sym = sym;
} else if (sym->type == STT_SECTION) { } else if (sym->type == STT_SECTION) {
sym->sec->secsym = sym; sym->sec->secsym = sym;
/* use the section name as the symbol name */ /* use the section name as the symbol name */

View File

@ -15,9 +15,11 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then if [ "$1" = "-o" ]; then
obj=$2 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_mc_*.o ]] && break;
[[ $obj = */.tmp_*.o ]] && obj=${obj/.tmp_/} [[ $obj = */.tmp_*.o ]] && obj=${obj/.tmp_/}
case "$obj" in case "$obj" in
*.mod.o|\ *.mod.o|\