mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
PowerPC64 ELFv2 PPC64_OPT_LOCALENTRY
ELFv2 functions with localentry:0 are those with a single entry point, ie. global entry == local entry, that have no requirement on r2 or r12 and guarantee r2 is unchanged on return. Such an external function can be called via the PLT without saving r2 or restoring it on return, avoiding a common load-hit-store for small functions. This patch implements the ld.so changes necessary for this optimization. ld.so needs to check that an optimized plt call sequence is in fact calling a function implemented with localentry:0, end emit a fatal error otherwise. The elf/testobj6.c change is to stop "error while loading shared libraries: expected localentry:0 `preload'" when running elf/preloadtest, which we'd get otherwise. * elf/elf.h (PPC64_OPT_LOCALENTRY): Define. * sysdeps/alpha/dl-machine.h (elf_machine_fixup_plt): Add refsym and sym parameters. Adjust callers. * sysdeps/aarch64/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/arm/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/generic/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/hppa/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/i386/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/ia64/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/m68k/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/microblaze/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/mips/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/nios2/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/s390/s390-32/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/s390/s390-64/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/sh/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/sparc/sparc32/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/sparc/sparc64/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/tile/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/x86_64/dl-machine.h (elf_machine_fixup_plt): Likewise. * sysdeps/powerpc/powerpc64/dl-machine.c (_dl_error_localentry): New. (_dl_reloc_overflow): Increase buffser size. Formatting. * sysdeps/powerpc/powerpc64/dl-machine.h (ppc64_local_entry_offset): Delete reloc param, add refsym and sym. Check optimized plt call stubs for localentry:0 functions. Adjust callers. (elf_machine_fixup_plt, elf_machine_plt_conflict): Add refsym and sym parameters. Adjust callers. (_dl_reloc_overflow): Move attribute. (_dl_error_localentry): Declare. * elf/dl-runtime.c (_dl_fixup): Save original sym. Pass refsym and sym to elf_machine_fixup_plt. * elf/testobj6.c (preload): Call printf.
This commit is contained in:
parent
d5b411854f
commit
0572433b5b
37
ChangeLog
37
ChangeLog
@ -1,3 +1,40 @@
|
|||||||
|
2017-06-14 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf/elf.h (PPC64_OPT_LOCALENTRY): Define.
|
||||||
|
* sysdeps/alpha/dl-machine.h (elf_machine_fixup_plt): Add
|
||||||
|
refsym and sym parameters. Adjust callers.
|
||||||
|
* sysdeps/aarch64/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/arm/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/generic/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/hppa/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/i386/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/ia64/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/m68k/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/microblaze/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/mips/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/nios2/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_fixup_plt):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/s390/s390-32/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/s390/s390-64/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/sh/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/sparc/sparc32/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/tile/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/x86_64/dl-machine.h (elf_machine_fixup_plt): Likewise.
|
||||||
|
* sysdeps/powerpc/powerpc64/dl-machine.c (_dl_error_localentry): New.
|
||||||
|
(_dl_reloc_overflow): Increase buffser size. Formatting.
|
||||||
|
* sysdeps/powerpc/powerpc64/dl-machine.h (ppc64_local_entry_offset):
|
||||||
|
Delete reloc param, add refsym and sym. Check optimized plt
|
||||||
|
call stubs for localentry:0 functions. Adjust callers.
|
||||||
|
(elf_machine_fixup_plt, elf_machine_plt_conflict): Add refsym
|
||||||
|
and sym parameters. Adjust callers.
|
||||||
|
(_dl_reloc_overflow): Move attribute.
|
||||||
|
(_dl_error_localentry): Declare.
|
||||||
|
* elf/dl-runtime.c (_dl_fixup): Save original sym. Pass
|
||||||
|
refsym and sym to elf_machine_fixup_plt.
|
||||||
|
* elf/testobj6.c (preload): Call printf.
|
||||||
|
|
||||||
2017-06-14 Alan Modra <amodra@gmail.com>
|
2017-06-14 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* sysdeps/powerpc/powerpc64/sysdep.h: Formatting.
|
* sysdeps/powerpc/powerpc64/sysdep.h: Formatting.
|
||||||
|
@ -71,6 +71,7 @@ _dl_fixup (
|
|||||||
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);
|
||||||
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;
|
||||||
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
|
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
|
||||||
lookup_t result;
|
lookup_t result;
|
||||||
DL_FIXUP_VALUE_TYPE value;
|
DL_FIXUP_VALUE_TYPE value;
|
||||||
@ -145,7 +146,7 @@ _dl_fixup (
|
|||||||
if (__glibc_unlikely (GLRO(dl_bind_not)))
|
if (__glibc_unlikely (GLRO(dl_bind_not)))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
|
return elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PROF
|
#ifndef PROF
|
||||||
|
@ -2544,9 +2544,10 @@ enum
|
|||||||
#define DT_PPC64_OPT (DT_LOPROC + 3)
|
#define DT_PPC64_OPT (DT_LOPROC + 3)
|
||||||
#define DT_PPC64_NUM 4
|
#define DT_PPC64_NUM 4
|
||||||
|
|
||||||
/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry. */
|
/* PowerPC64 specific bits in the DT_PPC64_OPT Dyn entry. */
|
||||||
#define PPC64_OPT_TLS 1
|
#define PPC64_OPT_TLS 1
|
||||||
#define PPC64_OPT_MULTI_TOC 2
|
#define PPC64_OPT_MULTI_TOC 2
|
||||||
|
#define PPC64_OPT_LOCALENTRY 4
|
||||||
|
|
||||||
/* PowerPC64 specific values for the Elf64_Sym st_other field. */
|
/* PowerPC64 specific values for the Elf64_Sym st_other field. */
|
||||||
#define STO_PPC64_LOCAL_BIT 5
|
#define STO_PPC64_LOCAL_BIT 5
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "testobj.h"
|
#include "testobj.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -15,5 +17,6 @@ obj6func2 (int a)
|
|||||||
int
|
int
|
||||||
preload (int a)
|
preload (int a)
|
||||||
{
|
{
|
||||||
|
printf ("testobj6 preload\n");
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
@ -245,6 +245,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline ElfW(Addr)
|
static inline ElfW(Addr)
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const ElfW(Rela) *reloc,
|
const ElfW(Rela) *reloc,
|
||||||
ElfW(Addr) *reloc_addr,
|
ElfW(Addr) *reloc_addr,
|
||||||
ElfW(Addr) value)
|
ElfW(Addr) value)
|
||||||
|
@ -260,6 +260,7 @@ dl_platform_init (void)
|
|||||||
rather than the dynamic linker. */
|
rather than the dynamic linker. */
|
||||||
static inline Elf64_Addr
|
static inline Elf64_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf64_Rela *reloc,
|
const Elf64_Rela *reloc,
|
||||||
Elf64_Addr *got_addr, Elf64_Addr value)
|
Elf64_Addr *got_addr, Elf64_Addr value)
|
||||||
{
|
{
|
||||||
@ -434,11 +435,11 @@ elf_machine_rela (struct link_map *map,
|
|||||||
RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
|
RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
|
||||||
reloc = ((const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]))
|
reloc = ((const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]))
|
||||||
+ (r_type >> 8);
|
+ (r_type >> 8);
|
||||||
elf_machine_fixup_plt (map, 0, reloc, reloc_addr, sym_value);
|
elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr, sym_value);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
else if (r_type == R_ALPHA_JMP_SLOT)
|
else if (r_type == R_ALPHA_JMP_SLOT)
|
||||||
elf_machine_fixup_plt (map, 0, reloc, reloc_addr, sym_value);
|
elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr, sym_value);
|
||||||
#endif
|
#endif
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#ifndef RTLD_BOOTSTRAP
|
||||||
else if (r_type == R_ALPHA_REFQUAD)
|
else if (r_type == R_ALPHA_REFQUAD)
|
||||||
|
@ -263,6 +263,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rel *reloc,
|
const Elf32_Rel *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -51,10 +51,11 @@ elf_machine_load_address (void)
|
|||||||
|
|
||||||
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
||||||
|
|
||||||
static inline Elf32_Addr
|
static inline ElfW(Addr)
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
const Elf32_Rel *reloc,
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
const ElfW(Rel) *reloc,
|
||||||
|
ElfW(Addr) *reloc_addr, ElfW(Addr) value)
|
||||||
{
|
{
|
||||||
return *reloc_addr = value;
|
return *reloc_addr = value;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ elf_machine_load_address (void)
|
|||||||
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
||||||
static inline struct fdesc __attribute__ ((always_inline))
|
static inline struct fdesc __attribute__ ((always_inline))
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, struct fdesc value)
|
Elf32_Addr *reloc_addr, struct fdesc value)
|
||||||
{
|
{
|
||||||
@ -652,13 +653,13 @@ elf_machine_rela (struct link_map *map,
|
|||||||
case R_PARISC_IPLT:
|
case R_PARISC_IPLT:
|
||||||
if (__builtin_expect (sym_map != NULL, 1))
|
if (__builtin_expect (sym_map != NULL, 1))
|
||||||
{
|
{
|
||||||
elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr,
|
elf_machine_fixup_plt (NULL, sym_map, NULL, NULL reloc, reloc_addr,
|
||||||
DL_FIXUP_MAKE_VALUE(sym_map, value));
|
DL_FIXUP_MAKE_VALUE(sym_map, value));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* If we get here, it's a (weak) undefined sym. */
|
/* If we get here, it's a (weak) undefined sym. */
|
||||||
elf_machine_fixup_plt (NULL, map, reloc, reloc_addr,
|
elf_machine_fixup_plt (NULL, map, NULL, NULL, reloc, reloc_addr,
|
||||||
DL_FIXUP_MAKE_VALUE(map, value));
|
DL_FIXUP_MAKE_VALUE(map, value));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -246,6 +246,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rel *reloc,
|
const Elf32_Rel *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -333,6 +333,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
|||||||
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
||||||
static inline struct fdesc __attribute__ ((always_inline))
|
static inline struct fdesc __attribute__ ((always_inline))
|
||||||
elf_machine_fixup_plt (struct link_map *l, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *l, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf64_Rela *reloc,
|
const Elf64_Rela *reloc,
|
||||||
Elf64_Addr *reloc_addr, struct fdesc value)
|
Elf64_Addr *reloc_addr, struct fdesc value)
|
||||||
{
|
{
|
||||||
@ -424,7 +425,7 @@ elf_machine_rela (struct link_map *map,
|
|||||||
;/* No adjustment. */
|
;/* No adjustment. */
|
||||||
else if (r_type == R_IA64_IPLTLSB)
|
else if (r_type == R_IA64_IPLTLSB)
|
||||||
{
|
{
|
||||||
elf_machine_fixup_plt (NULL, NULL, reloc, reloc_addr,
|
elf_machine_fixup_plt (NULL, NULL, NULL, NULL, reloc, reloc_addr,
|
||||||
DL_FIXUP_MAKE_VALUE (sym_map, value));
|
DL_FIXUP_MAKE_VALUE (sym_map, value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,7 @@ _dl_start_user:\n\
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -174,6 +174,7 @@ _dl_start_user:\n\
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -453,6 +453,7 @@ dl_platform_init (void)
|
|||||||
the corresponding PLT entry instead. */
|
the corresponding PLT entry instead. */
|
||||||
static inline ElfW(Addr)
|
static inline ElfW(Addr)
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const ElfW(Rel) *reloc,
|
const ElfW(Rel) *reloc,
|
||||||
ElfW(Addr) *reloc_addr, ElfW(Addr) value)
|
ElfW(Addr) *reloc_addr, ElfW(Addr) value)
|
||||||
{
|
{
|
||||||
|
@ -207,6 +207,7 @@ _start:\n\
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -235,6 +235,7 @@ extern Elf32_Addr __elf_machine_fixup_plt (struct link_map *map,
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf64_Addr finaladdr)
|
Elf32_Addr *reloc_addr, Elf64_Addr finaladdr)
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,7 @@ _dl_reloc_overflow (struct link_map *map,
|
|||||||
Elf64_Addr *const reloc_addr,
|
Elf64_Addr *const reloc_addr,
|
||||||
const Elf64_Sym *refsym)
|
const Elf64_Sym *refsym)
|
||||||
{
|
{
|
||||||
char buffer[128];
|
char buffer[1024];
|
||||||
char *t;
|
char *t;
|
||||||
t = stpcpy (buffer, name);
|
t = stpcpy (buffer, name);
|
||||||
t = stpcpy (t, " reloc at 0x");
|
t = stpcpy (t, " reloc at 0x");
|
||||||
@ -45,3 +45,19 @@ _dl_reloc_overflow (struct link_map *map,
|
|||||||
t = stpcpy (t, " out of range");
|
t = stpcpy (t, " out of range");
|
||||||
_dl_signal_error (0, map->l_name, NULL, buffer);
|
_dl_signal_error (0, map->l_name, NULL, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _CALL_ELF == 2
|
||||||
|
void
|
||||||
|
_dl_error_localentry (struct link_map *map, const Elf64_Sym *refsym)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
char *t;
|
||||||
|
const char *strtab;
|
||||||
|
|
||||||
|
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
|
||||||
|
t = stpcpy (buffer, "expected localentry:0 `");
|
||||||
|
t = stpcpy (t, strtab + refsym->st_name);
|
||||||
|
t = stpcpy (t, "'");
|
||||||
|
_dl_signal_error (0, map->l_name, NULL, buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -440,20 +440,30 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if _CALL_ELF == 2
|
#if _CALL_ELF == 2
|
||||||
/* If the PLT entry whose reloc is 'reloc' resolves to a function in
|
extern void attribute_hidden _dl_error_localentry (struct link_map *map,
|
||||||
the same object, return the target function's local entry point
|
const Elf64_Sym *refsym);
|
||||||
offset if usable. */
|
|
||||||
|
/* If the PLT entry resolves to a function in the same object, return
|
||||||
|
the target function's local entry point offset if usable. */
|
||||||
static inline Elf64_Addr __attribute__ ((always_inline))
|
static inline Elf64_Addr __attribute__ ((always_inline))
|
||||||
ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map,
|
ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map,
|
||||||
const Elf64_Rela *reloc)
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym)
|
||||||
{
|
{
|
||||||
const Elf64_Sym *symtab;
|
|
||||||
const Elf64_Sym *sym;
|
|
||||||
|
|
||||||
/* If the target function is in a different object, we cannot
|
/* If the target function is in a different object, we cannot
|
||||||
use the local entry point. */
|
use the local entry point. */
|
||||||
if (sym_map != map)
|
if (sym_map != map)
|
||||||
|
{
|
||||||
|
/* Check that optimized plt call stubs for localentry:0 functions
|
||||||
|
are not being satisfied by a non-zero localentry symbol. */
|
||||||
|
if (map->l_info[DT_PPC64(OPT)]
|
||||||
|
&& (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_LOCALENTRY) != 0
|
||||||
|
&& refsym->st_info == ELFW(ST_INFO) (STB_GLOBAL, STT_FUNC)
|
||||||
|
&& (STO_PPC64_LOCAL_MASK & refsym->st_other) == 0
|
||||||
|
&& (STO_PPC64_LOCAL_MASK & sym->st_other) != 0)
|
||||||
|
_dl_error_localentry (map, refsym);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the linker inserted multiple TOCs, we cannot use the
|
/* If the linker inserted multiple TOCs, we cannot use the
|
||||||
local entry point. */
|
local entry point. */
|
||||||
@ -461,16 +471,13 @@ ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map,
|
|||||||
&& (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_MULTI_TOC))
|
&& (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_MULTI_TOC))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Otherwise, we can use the local entry point. Retrieve its offset
|
|
||||||
from the symbol's ELF st_other field. */
|
|
||||||
symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
|
|
||||||
sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
|
|
||||||
|
|
||||||
/* If the target function is an ifunc then the local entry offset is
|
/* If the target function is an ifunc then the local entry offset is
|
||||||
for the resolver, not the final destination. */
|
for the resolver, not the final destination. */
|
||||||
if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
|
if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* Otherwise, we can use the local entry point. Retrieve its offset
|
||||||
|
from the symbol's ELF st_other field. */
|
||||||
return PPC64_LOCAL_ENTRY_OFFSET (sym->st_other);
|
return PPC64_LOCAL_ENTRY_OFFSET (sym->st_other);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -479,6 +486,7 @@ ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map,
|
|||||||
routine. */
|
routine. */
|
||||||
static inline Elf64_Addr __attribute__ ((always_inline))
|
static inline Elf64_Addr __attribute__ ((always_inline))
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf64_Rela *reloc,
|
const Elf64_Rela *reloc,
|
||||||
Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
|
Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
|
||||||
{
|
{
|
||||||
@ -534,7 +542,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
|
|||||||
PPC_DCBST (&plt->fd_func);
|
PPC_DCBST (&plt->fd_func);
|
||||||
PPC_ISYNC;
|
PPC_ISYNC;
|
||||||
#else
|
#else
|
||||||
finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
|
finaladdr += ppc64_local_entry_offset (map, sym_map, refsym, sym);
|
||||||
*reloc_addr = finaladdr;
|
*reloc_addr = finaladdr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -543,6 +551,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
|
|||||||
|
|
||||||
static inline void __attribute__ ((always_inline))
|
static inline void __attribute__ ((always_inline))
|
||||||
elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
|
elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf64_Rela *reloc,
|
const Elf64_Rela *reloc,
|
||||||
Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
|
Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
|
||||||
{
|
{
|
||||||
@ -565,7 +574,7 @@ elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
|
|||||||
PPC_DCBST (&plt->fd_toc);
|
PPC_DCBST (&plt->fd_toc);
|
||||||
PPC_SYNC;
|
PPC_SYNC;
|
||||||
#else
|
#else
|
||||||
finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
|
finaladdr += ppc64_local_entry_offset (map, sym_map, refsym, sym);
|
||||||
*reloc_addr = finaladdr;
|
*reloc_addr = finaladdr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -604,11 +613,10 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
|
|||||||
|
|
||||||
#define dont_expect(X) __builtin_expect ((X), 0)
|
#define dont_expect(X) __builtin_expect ((X), 0)
|
||||||
|
|
||||||
extern void _dl_reloc_overflow (struct link_map *map,
|
extern void attribute_hidden _dl_reloc_overflow (struct link_map *map,
|
||||||
const char *name,
|
const char *name,
|
||||||
Elf64_Addr *const reloc_addr,
|
Elf64_Addr *const reloc_addr,
|
||||||
const Elf64_Sym *refsym)
|
const Elf64_Sym *refsym);
|
||||||
attribute_hidden;
|
|
||||||
|
|
||||||
auto inline void __attribute__ ((always_inline))
|
auto inline void __attribute__ ((always_inline))
|
||||||
elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
|
elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
|
||||||
@ -728,9 +736,11 @@ elf_machine_rela (struct link_map *map,
|
|||||||
/* Fall thru */
|
/* Fall thru */
|
||||||
case R_PPC64_JMP_SLOT:
|
case R_PPC64_JMP_SLOT:
|
||||||
#ifdef RESOLVE_CONFLICT_FIND_MAP
|
#ifdef RESOLVE_CONFLICT_FIND_MAP
|
||||||
elf_machine_plt_conflict (map, sym_map, reloc, reloc_addr, value);
|
elf_machine_plt_conflict (map, sym_map, refsym, sym,
|
||||||
|
reloc, reloc_addr, value);
|
||||||
#else
|
#else
|
||||||
elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
|
elf_machine_fixup_plt (map, sym_map, refsym, sym,
|
||||||
|
reloc, reloc_addr, value);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -294,6 +294,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -242,6 +242,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline Elf64_Addr
|
static inline Elf64_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf64_Rela *reloc,
|
const Elf64_Rela *reloc,
|
||||||
Elf64_Addr *reloc_addr, Elf64_Addr value)
|
Elf64_Addr *reloc_addr, Elf64_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -230,6 +230,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -294,6 +294,7 @@ _dl_start_user:\n\
|
|||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf32_Rela *reloc,
|
const Elf32_Rela *reloc,
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +85,7 @@ elf_machine_load_address (void)
|
|||||||
|
|
||||||
static inline Elf64_Addr __attribute__ ((always_inline))
|
static inline Elf64_Addr __attribute__ ((always_inline))
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const Elf64_Rela *reloc,
|
const Elf64_Rela *reloc,
|
||||||
Elf64_Addr *reloc_addr, Elf64_Addr value)
|
Elf64_Addr *reloc_addr, Elf64_Addr value)
|
||||||
{
|
{
|
||||||
|
@ -239,6 +239,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline ElfW(Addr)
|
static inline ElfW(Addr)
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const ElfW(Rela) *reloc,
|
const ElfW(Rela) *reloc,
|
||||||
ElfW(Addr) *reloc_addr, ElfW(Addr) value)
|
ElfW(Addr) *reloc_addr, ElfW(Addr) value)
|
||||||
{
|
{
|
||||||
@ -569,7 +570,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
|||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
case R_TILE(JMP_SLOT):
|
case R_TILE(JMP_SLOT):
|
||||||
elf_machine_fixup_plt (map, 0, reloc, reloc_addr,
|
elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr,
|
||||||
value + reloc->r_addend);
|
value + reloc->r_addend);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -253,6 +253,7 @@ dl_platform_init (void)
|
|||||||
|
|
||||||
static inline ElfW(Addr)
|
static inline ElfW(Addr)
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||||
const ElfW(Rela) *reloc,
|
const ElfW(Rela) *reloc,
|
||||||
ElfW(Addr) *reloc_addr, ElfW(Addr) value)
|
ElfW(Addr) *reloc_addr, ElfW(Addr) value)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user