From 7b4efd150987301aa07f33fa3c4198f06a47ac98 Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Tue, 6 Mar 2018 16:16:51 +0530 Subject: [PATCH] create-diff-object: ppc64le - Fix wrong addend value for switch labels Commit f0518ef58afc ("create-diff-object: fix ppc64le kpatch_replace_sections_syms() bundling assumption"), subtracted sym.st_value for all bundled symbols on ppc64le and GCC6+ irrespective of function or switch label. As a side effect the addend for switch labels were incorrect and call to local function executed TOC setup code. Fallback to the original behaviour of subtracting sym.st_value only for the dynrela. Example of wrong switch label: ------------------------------ 0000000000000008 : ... 31c: 05 00 85 2b cmplwi cr7,r5,5 320: 7c 02 9d 41 bgt cr7,59c 324: 00 00 e2 3c addis r7,r2,0 324: R_PPC64_TOC16_HA .toc+0x580 328: 64 17 a5 78 rldicr r5,r5,2,61 32c: 00 00 47 e9 ld r10,0(r7) 32c: R_PPC64_TOC16_LO_DS .toc+0x580 330: aa 2a 2a 7d lwax r9,r10,r5 334: 14 52 29 7d add r9,r9,r10 338: a6 03 29 7d mtctr r9 33c: 20 04 80 4e bctr 340: 44 02 00 00 .long 0x244 344: f0 01 00 00 .long 0x1f0 348: 20 02 00 00 .long 0x220 34c: 38 02 00 00 .long 0x238 350: 2c 02 00 00 .long 0x22c 354: 50 02 00 00 .long 0x250 358: 00 00 00 60 nop Before Patch (.toc section): Offset Info Type Symbol's Value Symbol's Name + Addend ... 0x580 0000008200000026 R_PPC64_ADDR64 0000000000000008 register_netdevice + 338 After Patch (.toc section): Offset Info Type Symbol's Value Symbol's Name + Addend ... 0x580 0000008200000026 R_PPC64_ADDR64 0000000000000008 register_netdevice + 340 Example of localentry addend removed: ------------------------------------ Before Patch (.toc section): Offset Info Type Symbol's Value Symbol's Name + Addend ... 0x48 0000002c00000026 R_PPC64_ADDR64 0000000000000008 cmdline_proc_show + 0 After Patch (.toc section): Offset Info Type Symbol's Value Symbol's Name + Addend ... 0x48 0000002c00000026 R_PPC64_ADDR64 0000000000000008 cmdline_proc_show + 8 Fixes: f0518ef58afc ("create-diff-object: fix ppc64le kpatch_replace_sections_syms() bundling assumption") Cc: Josh Poimboeuf Signed-off-by: Kamalesh Babulal --- kpatch-build/create-diff-object.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 49d0aa982..81363eaf2 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -1114,12 +1114,6 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf) if (rela->sym->sec && rela->sym->sec->sym) { rela->sym = rela->sym->sec->sym; - /* - * ppc64le: a GCC 6+ bundled function is at - * offset 8 in its section. - */ - rela->addend -= rela->sym->sym.st_value; - continue; } @@ -2514,6 +2508,9 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, offsetof(struct kpatch_symbol, objname); /* Fill in krelas[index] */ + if (is_gcc6_localentry_bundled_sym(rela->sym) && + rela->addend == rela->sym->sym.st_value) + rela->addend -= rela->sym->sym.st_value; krelas[index].addend = rela->addend; krelas[index].type = rela->type; krelas[index].external = external;