Re: [PATCH v2 4/8] x86: add support for 64-bit place relative relocations

2018-07-03 Thread kbuild test robot
Hi Ard,

I love your patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.18-rc3 next-20180702]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Ard-Biesheuvel/add-support-for-relative-references-in-jump-tables/20180703-031712
config: um-x86_64_defconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=um SUBARCH=x86_64

All errors (new ones prefixed by >>):

   arch/x86/um/../kernel/module.c: In function 'apply_relocate_add':
>> arch/x86/um/../kernel/module.c:204:8: error: 'R_X86_64_PC64' undeclared 
>> (first use in this function); did you mean 'R_X86_64_PC16'?
  case R_X86_64_PC64:
   ^
   R_X86_64_PC16
   arch/x86/um/../kernel/module.c:204:8: note: each undeclared identifier is 
reported only once for each function it appears in

vim +204 arch/x86/um/../kernel/module.c

99  
   100  #ifdef CONFIG_X86_32
   101  int apply_relocate(Elf32_Shdr *sechdrs,
   102 const char *strtab,
   103 unsigned int symindex,
   104 unsigned int relsec,
   105 struct module *me)
   106  {
   107  unsigned int i;
   108  Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
   109  Elf32_Sym *sym;
   110  uint32_t *location;
   111  
   112  DEBUGP("Applying relocate section %u to %u\n",
   113 relsec, sechdrs[relsec].sh_info);
   114  for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
   115  /* This is where to make the change */
   116  location = (void 
*)sechdrs[sechdrs[relsec].sh_info].sh_addr
   117  + rel[i].r_offset;
   118  /* This is the symbol it is referring to.  Note that all
   119 undefined symbols have been resolved.  */
   120  sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
   121  + ELF32_R_SYM(rel[i].r_info);
   122  
   123  switch (ELF32_R_TYPE(rel[i].r_info)) {
   124  case R_386_32:
   125  /* We add the value into the location given */
   126  *location += sym->st_value;
   127  break;
   128  case R_386_PC32:
   129  /* Add the value, subtract its position */
   130  *location += sym->st_value - (uint32_t)location;
   131  break;
   132  default:
   133  pr_err("%s: Unknown relocation: %u\n",
   134 me->name, ELF32_R_TYPE(rel[i].r_info));
   135  return -ENOEXEC;
   136  }
   137  }
   138  return 0;
   139  }
   140  #else /*X86_64*/
   141  int apply_relocate_add(Elf64_Shdr *sechdrs,
   142 const char *strtab,
   143 unsigned int symindex,
   144 unsigned int relsec,
   145 struct module *me)
   146  {
   147  unsigned int i;
   148  Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
   149  Elf64_Sym *sym;
   150  void *loc;
   151  u64 val;
   152  
   153  DEBUGP("Applying relocate section %u to %u\n",
   154 relsec, sechdrs[relsec].sh_info);
   155  for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
   156  /* This is where to make the change */
   157  loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
   158  + rel[i].r_offset;
   159  
   160  /* This is the symbol it is referring to.  Note that all
   161 undefined symbols have been resolved.  */
   162  sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
   163  + ELF64_R_SYM(rel[i].r_info);
   164  
   165  DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n",
   166 (int)ELF64_R_TYPE(rel[i].r_info),
   167 sym->st_value, rel[i].r_addend, (u64)loc);
   168  
   169  val = sym->st_value + rel[i].r_addend;
   170  
   171  switch (ELF64_R_TYPE(rel[i].r_info)) {
   172  case R_X86_64_NONE:
   173  break;
   174  case R_X86_64_64:
   175  if (*(u64 *)loc != 0)
   176  goto invalid_relocation;
   177  *(u64 *)loc = val;
   178  break;
   179  case R_X86_64_32:
   180  if (*(u32 *)loc != 0)
  

[PATCH v2 4/8] x86: add support for 64-bit place relative relocations

2018-07-02 Thread Ard Biesheuvel
Add support for R_X86_64_PC64 relocations, which operate on 64-bit
quantities holding a relative symbol reference. This allows jump
table entries to be emitted in a way that makes them invariant under
runtime relocation, which means that no metadata needs to be emitted
into the kernel image to describe such data structures, resulting in
a size reduction.

Signed-off-by: Ard Biesheuvel 
---
 arch/x86/include/asm/elf.h |  1 +
 arch/x86/kernel/machine_kexec_64.c |  4 
 arch/x86/kernel/module.c   |  6 ++
 arch/x86/tools/relocs.c| 10 ++
 4 files changed, 21 insertions(+)

diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 0d157d2a1e2a..d3925d684296 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -62,6 +62,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
 #define R_X86_64_PC16  13  /* 16 bit sign extended pc relative */
 #define R_X86_64_8 14  /* Direct 8 bit sign extended  */
 #define R_X86_64_PC8   15  /* 8 bit sign extended pc relative */
+#define R_X86_64_PC64  24  /* Place relative 64-bit signed */
 
 #define R_X86_64_NUM   16
 
diff --git a/arch/x86/kernel/machine_kexec_64.c 
b/arch/x86/kernel/machine_kexec_64.c
index 4c8acdfdc5a7..6638d1edb2be 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -496,6 +496,10 @@ int arch_kexec_apply_relocations_add(struct purgatory_info 
*pi,
value -= (u64)address;
*(u32 *)location = value;
break;
+   case R_X86_64_PC64:
+   value -= (u64)address;
+   *(u64 *)location = value;
+   break;
default:
pr_err("Unknown rela relocation: %llu\n",
   ELF64_R_TYPE(rel[i].r_info));
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index f58336af095c..b052e883dd8c 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -201,6 +201,12 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
goto overflow;
 #endif
break;
+   case R_X86_64_PC64:
+   if (*(u64 *)loc != 0)
+   goto invalid_relocation;
+   val -= (u64)loc;
+   *(u64 *)loc = val;
+   break;
default:
pr_err("%s: Unknown rela relocation: %llu\n",
   me->name, ELF64_R_TYPE(rel[i].r_info));
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 220e97841e49..a4075bc37e8f 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -195,6 +195,7 @@ static const char *rel_type(unsigned type)
 #if ELF_BITS == 64
REL_TYPE(R_X86_64_NONE),
REL_TYPE(R_X86_64_64),
+   REL_TYPE(R_X86_64_PC64),
REL_TYPE(R_X86_64_PC32),
REL_TYPE(R_X86_64_GOT32),
REL_TYPE(R_X86_64_PLT32),
@@ -781,6 +782,15 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, 
ElfW(Sym) *sym,
add_reloc(&relocs32neg, offset);
break;
 
+   case R_X86_64_PC64:
+   /*
+* Only used by jump labels
+*/
+   if (is_percpu_sym(sym, symname))
+   die("Invalid R_X86_64_PC64 relocation against per-CPU 
symbol %s\n",
+   symname);
+   break;
+
case R_X86_64_32:
case R_X86_64_32S:
case R_X86_64_64:
-- 
2.17.1