From df8a552f6f93f62c494177a49ee49d3bf40949b8 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 10 May 2012 17:05:06 -0700 Subject: [PATCH] Handle R_X86_64_RELATIVE64 and R_X86_64_64 for x32 --- ChangeLog | 23 +++++++++++++++++ elf/elf.h | 3 ++- sysdeps/x86_64/Makefile | 13 ++++++++++ sysdeps/x86_64/dl-machine.h | 22 +++++++++++++--- sysdeps/x86_64/tst-quad1.c | 25 ++++++++++++++++++ sysdeps/x86_64/tst-quad1pie.c | 1 + sysdeps/x86_64/tst-quad2.c | 1 + sysdeps/x86_64/tst-quad2pie.c | 1 + sysdeps/x86_64/tst-quadmod1.S | 44 ++++++++++++++++++++++++++++++++ sysdeps/x86_64/tst-quadmod1pie.S | 2 ++ sysdeps/x86_64/tst-quadmod2.S | 43 +++++++++++++++++++++++++++++++ sysdeps/x86_64/tst-quadmod2pie.S | 1 + 12 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 sysdeps/x86_64/tst-quad1.c create mode 100644 sysdeps/x86_64/tst-quad1pie.c create mode 100644 sysdeps/x86_64/tst-quad2.c create mode 100644 sysdeps/x86_64/tst-quad2pie.c create mode 100644 sysdeps/x86_64/tst-quadmod1.S create mode 100644 sysdeps/x86_64/tst-quadmod1pie.S create mode 100644 sysdeps/x86_64/tst-quadmod2.S create mode 100644 sysdeps/x86_64/tst-quadmod2pie.S diff --git a/ChangeLog b/ChangeLog index a3b78b078f..2f0880257c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2012-05-10 H.J. Lu + + * elf/elf.h (R_X86_64_RELATIVE64): New. + (R_X86_64_NUM): Updated. + * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Handle + R_X86_64_RELATIVE64. Always use Elf64_Addr with R_X86_64_64. + (elf_machine_rela_relative): Handle R_X86_64_RELATIVE64. + * sysdeps/x86_64/Makefile (tests): Add tst-quad1 tst-quad2 + tst-quad1pie tst-quad2pie + (modules-names): Add tst-quadmod1 tst-quadmod2. + ($(objpfx)tst-quad1): New dependency. + ($(objpfx)tst-quad2): Likewise. + ($(objpfx)tst-quad1pie): Likewise. + ($(objpfx)tst-quad2pie): Likewise. + * sysdeps/x86_64/tst-quad1.c: New file. + * sysdeps/x86_64/tst-quad1pie.c: New file. + * sysdeps/x86_64/tst-quad2.c: Likewise. + * sysdeps/x86_64/tst-quad2pie.c: Likewise. + * sysdeps/x86_64/tst-quadmod1.S: Likewise. + * sysdeps/x86_64/tst-quadmod1pie.S: Likewise. + * sysdeps/x86_64/tst-quadmod2.S: Likewise. + * sysdeps/x86_64/tst-quadmod2pie.S: Likewise. + 2012-05-10 Samuel Thibault * io/fcntl.h (mode_t, off_t, pid_t): Define types. diff --git a/elf/elf.h b/elf/elf.h index 347d6d856e..6522ea6b6f 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -2703,8 +2703,9 @@ typedef Elf32_Addr Elf32_Conflict; descriptor. */ #define R_X86_64_TLSDESC 36 /* TLS descriptor. */ #define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ -#define R_X86_64_NUM 38 +#define R_X86_64_NUM 39 /* AM33 relocations. */ diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile index b989f6a976..81c9128a95 100644 --- a/sysdeps/x86_64/Makefile +++ b/sysdeps/x86_64/Makefile @@ -21,6 +21,19 @@ sysdep-dl-routines += tlsdesc dl-tlsdesc sysdep_routines += tlsdesc dl-tlsdesc sysdep-rtld-routines += tlsdesc dl-tlsdesc +tests += tst-quad1 tst-quad2 +modules-names += tst-quadmod1 tst-quadmod2 + +$(objpfx)tst-quad1: $(objpfx)tst-quadmod1.so +$(objpfx)tst-quad2: $(objpfx)tst-quadmod2.so + +quad-pie-test += tst-quad1pie tst-quad2pie +tests += $(quad-pie-test) +tests-pie += $(quad-pie-test) + +$(objpfx)tst-quad1pie: $(objpfx)tst-quadmod1pie.o +$(objpfx)tst-quad2pie: $(objpfx)tst-quadmod2pie.o + tests: $(objpfx)tst-xmmymm.out $(objpfx)tst-xmmymm.out: ../sysdeps/x86_64/tst-xmmymm.sh $(objpfx)ld.so @echo "Checking ld.so for SSE register use. This will take a few seconds..." diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 934e0b0d6f..e3bab5f22d 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -282,6 +282,13 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, *reloc_addr = map->l_addr + reloc->r_addend; } else +# endif +# if !defined RTLD_BOOTSTRAP + /* l_addr + r_addend may be > 0xffffffff and R_X86_64_RELATIVE64 + relocation updates the whole 64-bit entry. */ + if (__builtin_expect (r_type == R_X86_64_RELATIVE64, 0)) + *(Elf64_Addr *) reloc_addr = (Elf64_Addr) map->l_addr + reloc->r_addend; + else # endif if (__builtin_expect (r_type == R_X86_64_NONE, 0)) return; @@ -407,7 +414,9 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, # ifndef RTLD_BOOTSTRAP case R_X86_64_64: - *reloc_addr = value + reloc->r_addend; + /* value + r_addend may be > 0xffffffff and R_X86_64_64 + relocation updates the whole 64-bit entry. */ + *(Elf64_Addr *) reloc_addr = (Elf64_Addr) value + reloc->r_addend; break; case R_X86_64_32: value += reloc->r_addend; @@ -478,8 +487,15 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, void *const reloc_addr_arg) { ElfW(Addr) *const reloc_addr = reloc_addr_arg; - assert (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE); - *reloc_addr = l_addr + reloc->r_addend; + /* l_addr + r_addend may be > 0xffffffff and R_X86_64_RELATIVE64 + relocation updates the whole 64-bit entry. */ + if (__builtin_expect (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE64, 0)) + *(Elf64_Addr *) reloc_addr = (Elf64_Addr) l_addr + reloc->r_addend; + else + { + assert (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE); + *reloc_addr = l_addr + reloc->r_addend; + } } auto inline void diff --git a/sysdeps/x86_64/tst-quad1.c b/sysdeps/x86_64/tst-quad1.c new file mode 100644 index 0000000000..a8567ea8a2 --- /dev/null +++ b/sysdeps/x86_64/tst-quad1.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +extern void foo (void); + +int +main (void) +{ + foo (); + return 0; +} diff --git a/sysdeps/x86_64/tst-quad1pie.c b/sysdeps/x86_64/tst-quad1pie.c new file mode 100644 index 0000000000..f5fd45f9b0 --- /dev/null +++ b/sysdeps/x86_64/tst-quad1pie.c @@ -0,0 +1 @@ +#include "tst-quad1.c" diff --git a/sysdeps/x86_64/tst-quad2.c b/sysdeps/x86_64/tst-quad2.c new file mode 100644 index 0000000000..f5fd45f9b0 --- /dev/null +++ b/sysdeps/x86_64/tst-quad2.c @@ -0,0 +1 @@ +#include "tst-quad1.c" diff --git a/sysdeps/x86_64/tst-quad2pie.c b/sysdeps/x86_64/tst-quad2pie.c new file mode 100644 index 0000000000..a15d8d36ac --- /dev/null +++ b/sysdeps/x86_64/tst-quad2pie.c @@ -0,0 +1 @@ +#include "tst-quad2.c" diff --git a/sysdeps/x86_64/tst-quadmod1.S b/sysdeps/x86_64/tst-quadmod1.S new file mode 100644 index 0000000000..0e691be803 --- /dev/null +++ b/sysdeps/x86_64/tst-quadmod1.S @@ -0,0 +1,44 @@ +/* Copyright (C) 2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef BIAS +# define BIAS 0x7fffffff +#endif + + .section .data.rel,"aw",@progbits + .align 8 +.Ljmp: + .quad func + BIAS + .text + .globl func + .type func, @function +func: + .cfi_startproc + xorl %edi, %edi + jmp exit@PLT + .cfi_endproc + .size func, .-func + .globl foo + .type foo, @function +foo: + .cfi_startproc + .cfi_def_cfa_register 6 + movq .Ljmp(%rip), %rax + subq $BIAS, %rax + jmp *%rax + .cfi_endproc + .size foo, .-foo diff --git a/sysdeps/x86_64/tst-quadmod1pie.S b/sysdeps/x86_64/tst-quadmod1pie.S new file mode 100644 index 0000000000..c671d0cda9 --- /dev/null +++ b/sysdeps/x86_64/tst-quadmod1pie.S @@ -0,0 +1,2 @@ +#define BIAS 0x7fff0000 +#include "tst-quadmod1.S" diff --git a/sysdeps/x86_64/tst-quadmod2.S b/sysdeps/x86_64/tst-quadmod2.S new file mode 100644 index 0000000000..38ab9598bf --- /dev/null +++ b/sysdeps/x86_64/tst-quadmod2.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef BIAS +# define BIAS 0x7fff0000 +#endif + + .section .data.rel.local,"aw",@progbits + .align 8 +.Ljmp: + .quad func + BIAS + .text + .type func, @function +func: + .cfi_startproc + xorl %edi, %edi + jmp exit@PLT + .cfi_endproc + .size func, .-func + .globl foo + .type foo, @function +foo: + .cfi_startproc + .cfi_def_cfa_register 6 + movq .Ljmp(%rip), %rax + subq $BIAS, %rax + jmp *%rax + .cfi_endproc + .size foo, .-foo diff --git a/sysdeps/x86_64/tst-quadmod2pie.S b/sysdeps/x86_64/tst-quadmod2pie.S new file mode 100644 index 0000000000..609183fe58 --- /dev/null +++ b/sysdeps/x86_64/tst-quadmod2pie.S @@ -0,0 +1 @@ +#include "tst-quadmod2.S"