[RHEL7,COMMIT] ms/x86: Treat R_X86_64_PLT32 as R_X86_64_PC32

Submitted by Konstantin Khorenko on Aug. 6, 2019, 9:16 a.m.

Details

Message ID 201908060916.x769GiAC003913@finist-ce7.sw.ru
State New
Series "ms/x86: Treat R_X86_64_PLT32 as R_X86_64_PC32"
Headers show

Commit Message

Konstantin Khorenko Aug. 6, 2019, 9:16 a.m.
The commit is pushed to "branch-rh7-3.10.0-957.21.3.vz7.106.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.21.3.vz7.106.7
------>
commit 4bab66841dec9ff02772a1e46d80c00fae978b0e
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Feb 7 14:20:09 2018 -0800

    ms/x86: Treat R_X86_64_PLT32 as R_X86_64_PC32
    
    On i386, there are 2 types of PLTs, PIC and non-PIC.  PIE and shared
    objects must use PIC PLT.  To use PIC PLT, you need to load
    _GLOBAL_OFFSET_TABLE_ into EBX first.  There is no need for that on
    x86-64 since x86-64 uses PC-relative PLT.
    
    On x86-64, for 32-bit PC-relative branches, we can generate PLT32
    relocation, instead of PC32 relocation, which can also be used as
    a marker for 32-bit PC-relative branches.  Linker can always reduce
    PLT32 relocation to PC32 if function is defined locally.   Local
    functions should use PC32 relocation.  As far as Linux kernel is
    concerned, R_X86_64_PLT32 can be treated the same as R_X86_64_PC32
    since Linux kernel doesn't use PLT.
    
    R_X86_64_PLT32 for 32-bit PC-relative branches has been enabled in
    binutils master branch which will become binutils 2.31.
    
    [ hjl is working on having better documentation on this all, but a few
      more notes from him:
    
       "PLT32 relocation is used as marker for PC-relative branches. Because
        of EBX, it looks odd to generate PLT32 relocation on i386 when EBX
        doesn't have GOT.
    
        As for symbol resolution, PLT32 and PC32 relocations are almost
        interchangeable. But when linker sees PLT32 relocation against a
        protected symbol, it can resolved locally at link-time since it is
        used on a branch instruction. Linker can't do that for PC32
        relocation"
    
      but for the kernel use, the two are basically the same, and this
      commit gets things building and working with the current binutils
      master   - Linus ]
    
    Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    
    (cherry picked from commit b21ebf2fb4cde1618915a97cc773e287ff49173e)
    Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 arch/x86/kernel/machine_kexec_64.c | 1 +
 arch/x86/kernel/module.c           | 1 +
 arch/x86/tools/relocs.c            | 3 +++
 3 files changed, 5 insertions(+)

Patch hide | download patch | download mbox

diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 59b8ae2879a3..00056c8fbac0 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -533,6 +533,7 @@  int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
 				goto overflow;
 			break;
 		case R_X86_64_PC32:
+		case R_X86_64_PLT32:
 			value -= (u64)address;
 			*(u32 *)location = value;
 			break;
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index 8097b03d2075..9ed711056074 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -220,6 +220,7 @@  int apply_relocate_add(Elf64_Shdr *sechdrs,
 				goto overflow;
 			break;
 		case R_X86_64_PC32:
+		case R_X86_64_PLT32:
 			if (*(u32 *)loc != 0)
 				goto invalid_relocation;
 			val -= (u64)loc;
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 404aafc46df3..8ff49e6a88fe 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -769,9 +769,12 @@  static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
 		break;
 
 	case R_X86_64_PC32:
+	case R_X86_64_PLT32:
 		/*
 		 * PC relative relocations don't need to be adjusted unless
 		 * referencing a percpu symbol.
+		 *
+		 * NB: R_X86_64_PLT32 can be treated as R_X86_64_PC32.
 		 */
 		if (is_percpu_sym(sym, symname))
 			add_reloc(&relocs32neg, offset);