mirror of
https://github.com/dynup/kpatch
synced 2025-02-16 17:57:02 +00:00
kpatch-build: Add PPC64le livepatch support
This patch adds support for livepatch hook based module creation for PPC64le. It introduces PPC64le architecture bits: - Add relocation type of R_PPC64_ADDR64 while parsing powerpc ELF. - Introduce .toc sections mainpulation. - Skip kpatch specific details for livepatch hook. Also remove the definition of rela_insn() for powerpc. The only call site is been guarded by #ifdef x86. Cc: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
This commit is contained in:
parent
c9e4230d88
commit
c14e6e9118
@ -3,6 +3,14 @@ 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.
|
||||
PROCESSOR = $(shell uname -p)
|
||||
ifeq ($(PROCESSOR), ppc64le)
|
||||
KBUILD_CFLAGS_MODULE += -mcmodel=large
|
||||
endif
|
||||
|
||||
obj-m += kpatch-$(KPATCH_NAME).o
|
||||
|
||||
kpatch-$(KPATCH_NAME)-objs += patch-hook.o kpatch.lds output.o
|
||||
|
@ -248,6 +248,11 @@ static int __init patch_init(void)
|
||||
goto out;
|
||||
lpatch->mod = THIS_MODULE;
|
||||
lpatch->objs = lobjects;
|
||||
#if __powerpc__
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
|
||||
lpatch->immediate = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry(object, &patch_objects, list) {
|
||||
|
@ -59,6 +59,12 @@
|
||||
error(2, 0, "unreconcilable difference"); \
|
||||
})
|
||||
|
||||
#ifdef __powerpc__
|
||||
#define ABSOLUTE_RELA_TYPE R_PPC64_ADDR64
|
||||
#else
|
||||
#define ABSOLUTE_RELA_TYPE R_X86_64_64
|
||||
#endif
|
||||
|
||||
char *childobj;
|
||||
|
||||
enum loglevel loglevel = NORMAL;
|
||||
@ -146,6 +152,11 @@ static int kpatch_mangled_strcmp(char *s1, char *s2)
|
||||
|
||||
static int rela_equal(struct rela *rela1, struct rela *rela2)
|
||||
{
|
||||
#ifdef __powerpc__
|
||||
struct section *toc_relasec1, *toc_relasec2;
|
||||
struct rela *r_toc_relasec1, *r_toc_relasec2;
|
||||
#endif
|
||||
|
||||
if (rela1->type != rela2->type ||
|
||||
rela1->offset != rela2->offset)
|
||||
return 0;
|
||||
@ -153,6 +164,64 @@ static int rela_equal(struct rela *rela1, struct rela *rela2)
|
||||
if (rela1->string)
|
||||
return rela2->string && !strcmp(rela1->string, rela2->string);
|
||||
|
||||
#ifdef __powerpc__
|
||||
/*
|
||||
* Relocation section '.rela.toc' at offset 0x91f0 contains 122 entries:
|
||||
* Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
* [...]
|
||||
* 0000000000000090 0000001c00000026 R_PPC64_ADDR64 0000000000000000 .rodata.__dev_remove_pack.str1.8 + 0
|
||||
* 0000000000000098 0000001a00000026 R_PPC64_ADDR64 0000000000000000 .rodata.__dev_getfirstbyhwtype.str1.8 + 0
|
||||
* 00000000000000a0 0000001a00000026 R_PPC64_ADDR64 0000000000000000 .rodata.__dev_getfirstbyhwtype.str1.8 + 10
|
||||
* 00000000000000a8 000000cb00000026 R_PPC64_ADDR64 0000000000000000 dev_base_lock + 0
|
||||
*
|
||||
* Relocation section '.rela.text.netdev_master_upper_dev_get' at offset 0xe38 contains 10 entries:
|
||||
* Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
* [...]
|
||||
* 00000000000000a0 0000004e00000032 R_PPC64_TOC16_HA 0000000000000000 .toc + 98
|
||||
* 00000000000000a8 0000004e00000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + 98
|
||||
* 00000000000000ac 0000004e00000032 R_PPC64_TOC16_HA 0000000000000000 .toc + a0
|
||||
* 00000000000000b0 0000004e00000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + a0
|
||||
* 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.
|
||||
*/
|
||||
if (!strcmp(rela1->sym->name, ".toc") &&
|
||||
!strcmp(rela2->sym->name, ".toc")) {
|
||||
|
||||
toc_relasec1 = rela1->sym->sec->rela;
|
||||
if (!toc_relasec1)
|
||||
ERROR("cannot find .rela.toc");
|
||||
|
||||
r_toc_relasec1 = find_rela_by_offset(toc_relasec1, rela1->addend);
|
||||
if (!r_toc_relasec1)
|
||||
ERROR(".toc entry not found %s + %x", rela1->sym->name, rela1->addend);
|
||||
|
||||
toc_relasec2 = rela2->sym->sec->rela;
|
||||
if (!toc_relasec2)
|
||||
ERROR("cannot find .rela.toc");
|
||||
|
||||
r_toc_relasec2 = find_rela_by_offset(toc_relasec2, rela2->addend);
|
||||
if (!r_toc_relasec2)
|
||||
ERROR(".toc entry not found %s + %x", rela2->sym->name, rela2->addend);
|
||||
|
||||
if (r_toc_relasec1->string)
|
||||
return r_toc_relasec2->string &&
|
||||
!strcmp(r_toc_relasec1->string, r_toc_relasec2->string);
|
||||
|
||||
if ((r_toc_relasec1->addend != r_toc_relasec2->addend))
|
||||
return 0;
|
||||
|
||||
if (is_special_static(r_toc_relasec1->sym))
|
||||
return !kpatch_mangled_strcmp(r_toc_relasec1->sym->name,
|
||||
r_toc_relasec2->sym->name);
|
||||
|
||||
return !strcmp(r_toc_relasec1->sym->name, r_toc_relasec2->sym->name);
|
||||
}
|
||||
#endif
|
||||
if (rela1->addend != rela2->addend)
|
||||
return 0;
|
||||
|
||||
@ -167,6 +236,16 @@ 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.
|
||||
*/
|
||||
if (!strcmp(sec->name, ".rela.toc")) {
|
||||
sec->status = SAME;
|
||||
return;
|
||||
}
|
||||
|
||||
rela2 = list_entry(sec->twin->relas.next, struct rela, list);
|
||||
list_for_each_entry(rela1, &sec->relas, list) {
|
||||
if (rela_equal(rela1, rela2)) {
|
||||
@ -198,7 +277,6 @@ static void kpatch_compare_correlated_section(struct section *sec)
|
||||
/* Compare section headers (must match or fatal) */
|
||||
if (sec1->sh.sh_type != sec2->sh.sh_type ||
|
||||
sec1->sh.sh_flags != sec2->sh.sh_flags ||
|
||||
sec1->sh.sh_addr != sec2->sh.sh_addr ||
|
||||
sec1->sh.sh_addralign != sec2->sh.sh_addralign ||
|
||||
sec1->sh.sh_entsize != sec2->sh.sh_entsize)
|
||||
DIFF_FATAL("%s section header details differ", sec1->name);
|
||||
@ -894,8 +972,6 @@ static void rela_insn(struct section *sec, struct rela *rela, struct insn *insn)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void rela_insn(struct section *sec, struct rela *rela, struct insn *insn) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -933,6 +1009,18 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
|
||||
continue;
|
||||
}
|
||||
|
||||
#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.
|
||||
*/
|
||||
if (rela->type == R_PPC64_REL24)
|
||||
ERROR("Unexpected relocation type R_PPC64_REL24 for %s\n", rela->sym->name);
|
||||
|
||||
add_off = 0;
|
||||
#else
|
||||
if (rela->type == R_X86_64_PC32) {
|
||||
struct insn insn;
|
||||
rela_insn(sec, rela, &insn);
|
||||
@ -944,6 +1032,7 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
|
||||
add_off = 0;
|
||||
else
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Attempt to replace references to unbundled sections
|
||||
@ -1114,12 +1203,14 @@ out:
|
||||
static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
|
||||
{
|
||||
struct section *sec;
|
||||
struct rela *rela;
|
||||
|
||||
list_for_each_entry(sec, &kelf->sections, list) {
|
||||
/* include these sections even if they haven't changed */
|
||||
if (!strcmp(sec->name, ".shstrtab") ||
|
||||
!strcmp(sec->name, ".strtab") ||
|
||||
!strcmp(sec->name, ".symtab") ||
|
||||
!strcmp(sec->name, ".toc") ||
|
||||
!strcmp(sec->name, ".rodata") ||
|
||||
(!strncmp(sec->name, ".rodata.", 8) &&
|
||||
strstr(sec->name, ".str1."))) {
|
||||
@ -1127,6 +1218,18 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
|
||||
if (sec->secsym)
|
||||
sec->secsym->include = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* rela.toc section holds reference to symbols,
|
||||
* referred by function section relocation
|
||||
* entries. Include all of the symbols.
|
||||
*/
|
||||
if (!strcmp(sec->name, ".rela.toc"))
|
||||
{
|
||||
sec->include = 1;
|
||||
list_for_each_entry(rela, &sec->relas, list)
|
||||
kpatch_include_symbol(rela->sym, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* include the NULL symbol */
|
||||
@ -1776,7 +1879,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
|
||||
/* entries[index].sec */
|
||||
ALLOC_LINK(rela, &karch_sec->rela->relas);
|
||||
rela->sym = sec->secsym;
|
||||
rela->type = R_X86_64_64;
|
||||
rela->type = ABSOLUTE_RELA_TYPE;
|
||||
rela->addend = 0;
|
||||
rela->offset = index * sizeof(*entries) + \
|
||||
offsetof(struct kpatch_arch, sec);
|
||||
@ -1784,7 +1887,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
|
||||
/* entries[index].objname */
|
||||
ALLOC_LINK(rela, &karch_sec->rela->relas);
|
||||
rela->sym = strsym;
|
||||
rela->type = R_X86_64_64;
|
||||
rela->type = ABSOLUTE_RELA_TYPE;
|
||||
rela->addend = offset_of_string(&kelf->strings, objname);
|
||||
rela->offset = index * sizeof(*entries) + \
|
||||
offsetof(struct kpatch_arch, objname);
|
||||
@ -1980,7 +2083,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
|
||||
*/
|
||||
ALLOC_LINK(rela, &relasec->relas);
|
||||
rela->sym = sym;
|
||||
rela->type = R_X86_64_64;
|
||||
rela->type = ABSOLUTE_RELA_TYPE;
|
||||
rela->addend = 0;
|
||||
rela->offset = index * sizeof(*funcs);
|
||||
|
||||
@ -1990,7 +2093,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
|
||||
*/
|
||||
ALLOC_LINK(rela, &relasec->relas);
|
||||
rela->sym = strsym;
|
||||
rela->type = R_X86_64_64;
|
||||
rela->type = ABSOLUTE_RELA_TYPE;
|
||||
rela->addend = offset_of_string(&kelf->strings, sym->name);
|
||||
rela->offset = index * sizeof(*funcs) +
|
||||
offsetof(struct kpatch_patch_func, name);
|
||||
@ -2001,7 +2104,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
|
||||
*/
|
||||
ALLOC_LINK(rela, &relasec->relas);
|
||||
rela->sym = strsym;
|
||||
rela->type = R_X86_64_64;
|
||||
rela->type = ABSOLUTE_RELA_TYPE;
|
||||
rela->addend = objname_offset;
|
||||
rela->offset = index * sizeof(*funcs) +
|
||||
offsetof(struct kpatch_patch_func,objname);
|
||||
@ -2120,9 +2223,28 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
||||
* a global symbol. Use a normal rela for
|
||||
* exported symbols and a dynrela otherwise.
|
||||
*/
|
||||
#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.
|
||||
*
|
||||
* fs/proc/proc_sysctl::sysctl_head_grab:
|
||||
* 166: 0000000000000000 256 FUNC GLOBAL DEFAULT [<localentry>: 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.
|
||||
*/
|
||||
if (lookup_is_exported_symbol(table, rela->sym->name)) {
|
||||
if (rela->sym->type != STT_FUNC)
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if (lookup_is_exported_symbol(table, rela->sym->name))
|
||||
continue;
|
||||
|
||||
#endif
|
||||
/*
|
||||
* If lookup_global_symbol() fails, assume the
|
||||
* symbol is defined in another object in the
|
||||
@ -2181,7 +2303,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
||||
/* add rela to fill in ksyms[index].name field */
|
||||
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
|
||||
rela2->sym = strsym;
|
||||
rela2->type = R_X86_64_64;
|
||||
rela2->type = ABSOLUTE_RELA_TYPE;
|
||||
rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
|
||||
rela2->offset = index * sizeof(*ksyms) + \
|
||||
offsetof(struct kpatch_symbol, name);
|
||||
@ -2189,7 +2311,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
||||
/* add rela to fill in ksyms[index].objname field */
|
||||
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
|
||||
rela2->sym = strsym;
|
||||
rela2->type = R_X86_64_64;
|
||||
rela2->type = ABSOLUTE_RELA_TYPE;
|
||||
rela2->addend = offset_of_string(&kelf->strings, sym_objname);
|
||||
rela2->offset = index * sizeof(*ksyms) + \
|
||||
offsetof(struct kpatch_symbol, objname);
|
||||
@ -2210,7 +2332,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
||||
ERROR("can't create dynrela for section %s (symbol %s): no bundled section or section symbol",
|
||||
sec->name, rela->sym->name);
|
||||
|
||||
rela2->type = R_X86_64_64;
|
||||
rela2->type = ABSOLUTE_RELA_TYPE;
|
||||
rela2->addend = rela->offset;
|
||||
rela2->offset = index * sizeof(*krelas) + \
|
||||
offsetof(struct kpatch_relocation, dest);
|
||||
@ -2218,7 +2340,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
||||
/* add rela to fill in krelas[index].objname field */
|
||||
ALLOC_LINK(rela2, &krela_sec->rela->relas);
|
||||
rela2->sym = strsym;
|
||||
rela2->type = R_X86_64_64;
|
||||
rela2->type = ABSOLUTE_RELA_TYPE;
|
||||
rela2->addend = offset_of_string(&kelf->strings, objname);
|
||||
rela2->offset = index * sizeof(*krelas) + \
|
||||
offsetof(struct kpatch_relocation, objname);
|
||||
@ -2226,7 +2348,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
||||
/* add rela to fill in krelas[index].ksym field */
|
||||
ALLOC_LINK(rela2, &krela_sec->rela->relas);
|
||||
rela2->sym = ksym_sec_sym;
|
||||
rela2->type = R_X86_64_64;
|
||||
rela2->type = ABSOLUTE_RELA_TYPE;
|
||||
rela2->addend = index * sizeof(*ksyms);
|
||||
rela2->offset = index * sizeof(*krelas) + \
|
||||
offsetof(struct kpatch_relocation, ksym);
|
||||
@ -2269,12 +2391,15 @@ static void kpatch_create_hooks_objname_rela(struct kpatch_elf *kelf, char *objn
|
||||
|
||||
ALLOC_LINK(rela, &sec->relas);
|
||||
rela->sym = strsym;
|
||||
rela->type = R_X86_64_64;
|
||||
rela->type = ABSOLUTE_RELA_TYPE;
|
||||
rela->addend = objname_offset;
|
||||
rela->offset = offsetof(struct kpatch_patch_hook, objname);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __powerpc__
|
||||
void kpatch_create_mcount_sections(struct kpatch_elf *kelf) { }
|
||||
#else
|
||||
/*
|
||||
* This function basically reimplements the functionality of the Linux
|
||||
* recordmcount script, so that patched functions can be recognized by ftrace.
|
||||
@ -2349,6 +2474,7 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
||||
if (index != nr)
|
||||
ERROR("size mismatch in funcs sections");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function strips out symbols that were referenced by changed rela
|
||||
|
@ -160,7 +160,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
||||
struct symbol *sym;
|
||||
struct rela *rela;
|
||||
char *objname;
|
||||
int nr, index, offset;
|
||||
int nr, index, offset, toc_offset;
|
||||
|
||||
krelas = krelasec->data->d_buf;
|
||||
nr = krelasec->data->d_size / sizeof(*krelas);
|
||||
@ -174,6 +174,37 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
||||
if (!rela)
|
||||
ERROR("find_rela_by_offset");
|
||||
|
||||
/*
|
||||
* Patched file:
|
||||
* Relocation section '.rela.toc' at offset 0x46358 contains 60 entries:
|
||||
* Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
* 0000000000000000 000001ee00000026 R_PPC64_ADDR64 0000000000000000 jiffies + 0
|
||||
* 0000000000000008 0000009400000026 R_PPC64_ADDR64 0000000000000000 __tracepoints + 0
|
||||
* 0000000000000010 000001db00000026 R_PPC64_ADDR64 0000000000000000 __cpu_online_mask + 0
|
||||
* 0000000000000018 0000009c00000026 R_PPC64_ADDR64 0000000000000000 .data..percpu + 0
|
||||
* 0000000000000020 000001ac00000026 R_PPC64_ADDR64 0000000000000000 __per_cpu_offset + 0
|
||||
* 0000000000000028 0000006900000026 R_PPC64_ADDR64 0000000000000000 .rodata.str1.8 + 0
|
||||
* [...]
|
||||
*
|
||||
* Output file:
|
||||
* Relocation section '.rela.toc' at offset 0x1270 contains 58 entries:
|
||||
* Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
* 0000000000000000 0000000700000026 R_PPC64_ADDR64 0000000000000000 .data + 0
|
||||
* 0000000000000008 0000003c00000026 R_PPC64_ADDR64 0000000000000000 __kpatch_funcs + 0
|
||||
* 0000000000000010 0000005300000026 R_PPC64_ADDR64 0000000000000000 kmalloc_caches + 0
|
||||
* 0000000000000018 0000001100000026 R_PPC64_ADDR64 0000000000000000 .rodata.str1.8 + 0
|
||||
* 0000000000000020 0000001600000026 R_PPC64_ADDR64 0000000000000000 .bss + 0
|
||||
* 0000000000000028 0000004200000026 R_PPC64_ADDR64 0000000000000038 __kpatch_funcs_end + 0
|
||||
* 0000000000000030 0000003400000026 R_PPC64_ADDR64 0000000000000000 __this_module + 0
|
||||
* 0000000000000038 0000004d00000026 R_PPC64_ADDR64 0000000000000000 jiffies + 0
|
||||
* 0000000000000048 0000004500000026 R_PPC64_ADDR64 0000000000000000 __cpu_online_mask + 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
|
||||
* offset value, which will be used below to setting the rela->addend. */
|
||||
toc_offset = rela->addend;
|
||||
|
||||
base = rela->sym->sec;
|
||||
if (!base)
|
||||
ERROR("base sec of krela not found");
|
||||
@ -208,7 +239,10 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
||||
ALLOC_LINK(rela, &klp_relasec->relas);
|
||||
rela->sym = sym;
|
||||
rela->type = krelas[index].type;
|
||||
rela->offset = krelas[index].offset;
|
||||
if (!strcmp(base->name, ".toc"))
|
||||
rela->offset = toc_offset;
|
||||
else
|
||||
rela->offset = krelas[index].offset;
|
||||
rela->addend = krelas[index].addend;
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ APPLIEDPATCHFILE="kpatch.patch"
|
||||
DEBUG=0
|
||||
SKIPCLEANUP=0
|
||||
SKIPGCCCHECK=0
|
||||
ARCH_KCFLAGS=""
|
||||
|
||||
warn() {
|
||||
echo "ERROR: $1" >&2
|
||||
@ -556,7 +557,12 @@ cd "$SRCDIR" || die
|
||||
patch -N -p1 --dry-run < "$PATCHFILE" || die "source patch file failed to apply"
|
||||
cp "$PATCHFILE" "$APPLIEDPATCHFILE" || die
|
||||
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
|
||||
export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections"
|
||||
|
||||
if [[ $ARCH = "ppc64le" ]]; then
|
||||
ARCH_KCFLAGS="-mcmodel=large"
|
||||
fi
|
||||
|
||||
export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLAGS"
|
||||
|
||||
echo "Reading special section data"
|
||||
find_special_section_data
|
||||
@ -648,7 +654,7 @@ do
|
||||
done
|
||||
echo
|
||||
|
||||
export KCFLAGS="-I$DATADIR/patch"
|
||||
export KCFLAGS="-I$DATADIR/patch $ARCH_KCFLAGS"
|
||||
if $KPATCH_MODULE; then
|
||||
export KCPPFLAGS="-D__KPATCH_MODULE__"
|
||||
fi
|
||||
|
@ -349,7 +349,7 @@ void kpatch_create_symbol_list(struct kpatch_elf *kelf)
|
||||
|
||||
}
|
||||
|
||||
/* Check which functions have fentry calls; save this info for later use. */
|
||||
/* Check which functions have fentry/mcount calls; save this info for later use. */
|
||||
static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
|
||||
{
|
||||
struct symbol *sym;
|
||||
@ -357,7 +357,14 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
|
||||
list_for_each_entry(sym, &kelf->symbols, list) {
|
||||
if (sym->type != STT_FUNC || !sym->sec || !sym->sec->rela)
|
||||
continue;
|
||||
|
||||
#ifdef __powerpc__
|
||||
list_for_each_entry(rela, &sym->sec->rela->relas, list) {
|
||||
if (!strcmp(rela->sym->name, "_mcount")) {
|
||||
sym->has_func_profiling = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
rela = list_first_entry(&sym->sec->rela->relas, struct rela,
|
||||
list);
|
||||
if (rela->type != R_X86_64_NONE ||
|
||||
@ -365,6 +372,7 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
|
||||
continue;
|
||||
|
||||
sym->has_func_profiling = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,10 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
|
||||
while [ "$#" -gt 0 ]; do
|
||||
if [ "$1" = "-o" ]; then
|
||||
obj=$2
|
||||
[[ $2 = */.tmp_*.o ]] && obj=${2/.tmp_/}
|
||||
# skip copying the original .o files, when .tmp_mc_*.o
|
||||
# is passed from recordmcount.pl.
|
||||
[[ $obj = */.tmp_mc_*.o ]] && break;
|
||||
[[ $obj = */.tmp_*.o ]] && obj=${obj/.tmp_/}
|
||||
case "$obj" in
|
||||
*.mod.o|\
|
||||
*built-in.o|\
|
||||
@ -32,6 +35,7 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
|
||||
arch/x86/vdso/*|\
|
||||
arch/x86/entry/vdso/*|\
|
||||
drivers/firmware/efi/libstub/*|\
|
||||
arch/powerpc/kernel/prom_init.o|\
|
||||
*.*.o)
|
||||
break
|
||||
;;
|
||||
|
Loading…
Reference in New Issue
Block a user