dl-runtime: reloc_{offset,index} now functions arch overide'able

The existing macros are fragile and expect local variables with a
certain name. Fix this by defining them as functions with default
implementation in a new header dl-runtime.h which arches can override
if need be.

This came up during ARC port review, hence the need for argument pltgot
in reloc_index() which is not needed by existing ports.

This patch potentially only affects hppa/x86 ports,
build tested for both those configs and a few more.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
Vineet Gupta 2020-05-27 12:54:21 -07:00
parent a23bd00f9d
commit 8dbb7a08ec
6 changed files with 113 additions and 24 deletions

View File

@ -27,6 +27,7 @@
#include "dynamic-link.h" #include "dynamic-link.h"
#include <tls.h> #include <tls.h>
#include <dl-irel.h> #include <dl-irel.h>
#include <dl-runtime.h>
#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ #if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
@ -42,13 +43,6 @@
# define ARCH_FIXUP_ATTRIBUTE # define ARCH_FIXUP_ATTRIBUTE
#endif #endif
#ifndef reloc_offset
# define reloc_offset reloc_arg
# define reloc_index reloc_arg / sizeof (PLTREL)
#endif
/* This function is called through a special trampoline from the PLT the /* This function is called through a special trampoline from the PLT the
first time each PLT entry is called. We must perform the relocation first time each PLT entry is called. We must perform the relocation
specified in the PLT of the given shared object, and return the resolved specified in the PLT of the given shared object, and return the resolved
@ -68,8 +62,11 @@ _dl_fixup (
= (const void *) D_PTR (l, l_info[DT_SYMTAB]); = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
const PLTREL *const reloc const PLTREL *const reloc
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset); = (const void *) (D_PTR (l, l_info[DT_JMPREL])
+ reloc_offset (pltgot, reloc_arg));
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)]; const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
const ElfW(Sym) *refsym = sym; const ElfW(Sym) *refsym = sym;
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset); void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
@ -180,9 +177,12 @@ _dl_profile_fixup (
l, reloc_arg); l, reloc_arg);
} }
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
/* This is the address in the array where we store the result of previous /* This is the address in the array where we store the result of previous
relocations. */ relocations. */
struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; struct reloc_result *reloc_result
= &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
/* CONCURRENCY NOTES: /* CONCURRENCY NOTES:
@ -219,8 +219,11 @@ _dl_profile_fixup (
= (const void *) D_PTR (l, l_info[DT_SYMTAB]); = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]); const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
const PLTREL *const reloc const PLTREL *const reloc
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset); = (const void *) (D_PTR (l, l_info[DT_JMPREL])
+ reloc_offset (pltgot, reloc_arg));
const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)]; const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
const ElfW(Sym) *defsym = refsym; const ElfW(Sym) *defsym = refsym;
lookup_t result; lookup_t result;
@ -485,11 +488,14 @@ _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
const void *inregs, void *outregs) const void *inregs, void *outregs)
{ {
#ifdef SHARED #ifdef SHARED
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
/* This is the address in the array where we store the result of previous /* This is the address in the array where we store the result of previous
relocations. */ relocations. */
// XXX Maybe the bound information must be stored on the stack since // XXX Maybe the bound information must be stored on the stack since
// XXX with bind_not a new value could have been stored in the meantime. // XXX with bind_not a new value could have been stored in the meantime.
struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; struct reloc_result *reloc_result =
&l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
l_info[DT_SYMTAB]) l_info[DT_SYMTAB])
+ reloc_result->boundndx); + reloc_result->boundndx);

30
elf/dl-runtime.h Normal file
View File

@ -0,0 +1,30 @@
/* Helpers for On-demand PLT fixup for shared objects. Generic version.
Copyright (C) 2020 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
static inline uintptr_t
reloc_offset (uintptr_t plt0, uintptr_t pltn)
{
return pltn;
}
static inline uintptr_t
reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size)
{
return pltn / size;
}

View File

@ -17,10 +17,6 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
/* Clear PA_GP_RELOC bit in relocation offset. */
#define reloc_offset (reloc_arg & ~PA_GP_RELOC)
#define reloc_index (reloc_arg & ~PA_GP_RELOC) / sizeof (PLTREL)
#include <elf/dl-runtime.c> #include <elf/dl-runtime.c>
/* The caller has encountered a partially relocated function descriptor. /* The caller has encountered a partially relocated function descriptor.

31
sysdeps/hppa/dl-runtime.h Normal file
View File

@ -0,0 +1,31 @@
/* Helpers for On-demand PLT fixup for shared objects. HPAA version.
Copyright (C) 2020 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Clear PA_GP_RELOC bit in relocation offset. */
static inline uintptr_t
reloc_offset (uintptr_t plt0, uintptr_t pltn)
{
return pltn & ~PA_GP_RELOC;
}
static inline uintptr_t
reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size)
{
return (pltn & ~PA_GP_RELOC )/ size;
}

View File

@ -1,9 +0,0 @@
/* The ABI calls for the PLT stubs to pass the index of the relocation
and not its offset. In _dl_profile_fixup and _dl_call_pltexit we
also use the index. Therefore it is wasteful to compute the offset
in the trampoline just to reverse the operation immediately
afterwards. */
#define reloc_offset reloc_arg * sizeof (PLTREL)
#define reloc_index reloc_arg
#include <elf/dl-runtime.c>

View File

@ -0,0 +1,35 @@
/* Helpers for On-demand PLT fixup for shared objects. x86_64 version.
Copyright (C) 2020 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* The ABI calls for the PLT stubs to pass the index of the relocation
and not its offset. In _dl_profile_fixup and _dl_call_pltexit we
also use the index. Therefore it is wasteful to compute the offset
in the trampoline just to reverse the operation immediately
afterwards. */
static inline uintptr_t
reloc_offset (uintptr_t plt0, uintptr_t pltn)
{
return pltn * sizeof (ElfW(Rela));
}
static inline uintptr_t
reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size)
{
return pltn;
}