mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-25 02:33:36 +08:00
hppa: don't call ifunc functions in trace mode
This commit is contained in:
parent
86a90a837c
commit
09272d2c9f
@ -1,7 +1,12 @@
|
||||
2011-10-05 Andreas Schwab <schwab@redhat.com>
|
||||
|
||||
* sysdeps/hppa/dl-machine.h (elf_machine_rela)
|
||||
(elf_machine_lazy_rel): Add parameter skip_ifunc.
|
||||
|
||||
2010-06-24 Carlos O'Donell <carlos@codesourcery.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S: Only create stack
|
||||
frame around call to SYSCALL_ERROR_HANDLER. Do not restore %rp
|
||||
* sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S: Only create stack
|
||||
frame around call to SYSCALL_ERROR_HANDLER. Do not restore %rp
|
||||
from the stack frame on successfull return.
|
||||
|
||||
2010-06-23 Carlos O'Donell <carlos@codesourcery.com>
|
||||
@ -10,12 +15,12 @@
|
||||
Document that this function is a non-standard calling ABI.
|
||||
Document register usage.
|
||||
(__getcontext): Use normal %sp without adjustment. Use named
|
||||
resgister %sp.
|
||||
resgister %sp.
|
||||
* sysdeps/unix/sysv/linux/hppa/makecontext.c: Remove FRAME_SIZE.
|
||||
Define FRAME_SIZE_UL, FRAME_SIZE_BYTES, ARGS.
|
||||
(__makecontext): Create and setup a stack frame.
|
||||
(__makecontext): Create and setup a stack frame.
|
||||
* sysdeps/unix/sysv/linux/hppa/setcontext.S (__setcontext):
|
||||
Use named register %sp. Do not use oSS_SP.
|
||||
Use named register %sp. Do not use oSS_SP.
|
||||
|
||||
2010-06-07 Andreas Schwab <schwab@redhat.com>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Machine-dependent ELF dynamic relocation inline functions. PA-RISC version.
|
||||
Copyright (C) 1995-1997,1999-2003
|
||||
Copyright (C) 1995-1997,1999-2003,2011
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by David Huggins-Daines <dhd@debian.org>
|
||||
This file is part of the GNU C Library.
|
||||
@ -33,19 +33,19 @@
|
||||
#include <abort-instr.h>
|
||||
#include <tls.h>
|
||||
|
||||
/* These two definitions must match the definition of the stub in
|
||||
/* These two definitions must match the definition of the stub in
|
||||
bfd/elf32-hppa.c (see plt_stub[]).
|
||||
|
||||
|
||||
a. Define the size of the *entire* stub we place at the end of the PLT
|
||||
table (right up against the GOT).
|
||||
|
||||
|
||||
b. Define the number of bytes back from the GOT to the entry point of
|
||||
the PLT stub. You see the PLT stub must be entered in the middle
|
||||
so it can depwi to find it's own address (long jump stub)
|
||||
|
||||
so it can depwi to find it's own address (long jump stub)
|
||||
|
||||
c. Define the size of a single PLT entry so we can jump over the
|
||||
last entry to get the stub address */
|
||||
|
||||
|
||||
#define SIZEOF_PLT_STUB (7*4)
|
||||
#define GOT_FROM_PLT_STUB (4*4)
|
||||
#define PLT_ENTRY_SIZE (2*4)
|
||||
@ -110,8 +110,8 @@ elf_machine_load_address (void)
|
||||
return dynamic - elf_machine_dynamic ();
|
||||
}
|
||||
|
||||
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
||||
static inline struct fdesc __attribute__ ((always_inline))
|
||||
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
|
||||
static inline struct fdesc __attribute__ ((always_inline))
|
||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||
const Elf32_Rela *reloc,
|
||||
Elf32_Addr *reloc_addr, struct fdesc value)
|
||||
@ -127,7 +127,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||
}
|
||||
|
||||
/* Return the final value of a plt relocation. */
|
||||
static inline struct fdesc
|
||||
static inline struct fdesc
|
||||
elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
|
||||
struct fdesc value)
|
||||
{
|
||||
@ -149,106 +149,106 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
unsigned char c[8];
|
||||
Elf32_Addr i[2];
|
||||
} sig = {{0x00,0xc0,0xff,0xee, 0xde,0xad,0xbe,0xef}};
|
||||
|
||||
|
||||
/* If we don't have a PLT we can just skip all this... */
|
||||
if (__builtin_expect (l->l_info[DT_JMPREL] == NULL,0))
|
||||
return lazy;
|
||||
|
||||
/* All paths use these values */
|
||||
|
||||
/* All paths use these values */
|
||||
l_addr = l->l_addr;
|
||||
jmprel = D_PTR(l, l_info[DT_JMPREL]);
|
||||
end_jmprel = jmprel + l->l_info[DT_PLTRELSZ]->d_un.d_val;
|
||||
|
||||
|
||||
extern void _dl_runtime_resolve (void);
|
||||
extern void _dl_runtime_profile (void);
|
||||
|
||||
|
||||
/* Linking lazily */
|
||||
if (lazy)
|
||||
{
|
||||
/* FIXME: Search for the got, but backwards through the relocs, technically we should
|
||||
find it on the first try. However, assuming the relocs got out of order the
|
||||
routine is made a bit more robust by searching them all in case of failure. */
|
||||
find it on the first try. However, assuming the relocs got out of order the
|
||||
routine is made a bit more robust by searching them all in case of failure. */
|
||||
for (iplt = (end_jmprel - sizeof(Elf32_Rela)); iplt >= jmprel; iplt -= sizeof (Elf32_Rela))
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
reloc = (const Elf32_Rela *) iplt;
|
||||
r_type = ELF32_R_TYPE (reloc->r_info);
|
||||
r_sym = ELF32_R_SYM (reloc->r_info);
|
||||
r_type = ELF32_R_TYPE (reloc->r_info);
|
||||
r_sym = ELF32_R_SYM (reloc->r_info);
|
||||
|
||||
got = (Elf32_Addr *) (reloc->r_offset + l_addr + PLT_ENTRY_SIZE + SIZEOF_PLT_STUB);
|
||||
got = (Elf32_Addr *) (reloc->r_offset + l_addr + PLT_ENTRY_SIZE + SIZEOF_PLT_STUB);
|
||||
|
||||
/* If we aren't an IPLT, and we aren't NONE then it's a bad reloc */
|
||||
if (__builtin_expect (r_type != R_PARISC_IPLT, 0))
|
||||
/* If we aren't an IPLT, and we aren't NONE then it's a bad reloc */
|
||||
if (__builtin_expect (r_type != R_PARISC_IPLT, 0))
|
||||
{
|
||||
if (__builtin_expect (r_type != R_PARISC_NONE, 0))
|
||||
_dl_reloc_bad_type (l, r_type, 1);
|
||||
_dl_reloc_bad_type (l, r_type, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for the plt_stub that binutils placed here for us
|
||||
to use with _dl_runtime_resolve */
|
||||
if (got[-2] != sig.i[0] || got[-1] != sig.i[1])
|
||||
{
|
||||
got = NULL; /* Not the stub... keep looking */
|
||||
}
|
||||
else
|
||||
|
||||
/* Check for the plt_stub that binutils placed here for us
|
||||
to use with _dl_runtime_resolve */
|
||||
if (got[-2] != sig.i[0] || got[-1] != sig.i[1])
|
||||
{
|
||||
/* Found the GOT! */
|
||||
register Elf32_Addr ltp __asm__ ("%r19");
|
||||
|
||||
/* Identify this shared object. Second entry in the got. */
|
||||
got[1] = (Elf32_Addr) l;
|
||||
|
||||
/* This function will be called to perform the relocation. */
|
||||
if (__builtin_expect (!profile, 1))
|
||||
{
|
||||
/* If a static application called us, then _dl_runtime_resolve is not
|
||||
got = NULL; /* Not the stub... keep looking */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Found the GOT! */
|
||||
register Elf32_Addr ltp __asm__ ("%r19");
|
||||
|
||||
/* Identify this shared object. Second entry in the got. */
|
||||
got[1] = (Elf32_Addr) l;
|
||||
|
||||
/* This function will be called to perform the relocation. */
|
||||
if (__builtin_expect (!profile, 1))
|
||||
{
|
||||
/* If a static application called us, then _dl_runtime_resolve is not
|
||||
a function descriptor, but the *real* address of the function... */
|
||||
if((unsigned long) &_dl_runtime_resolve & 3)
|
||||
{
|
||||
got[-2] = (Elf32_Addr) ((struct fdesc *)
|
||||
((unsigned long) &_dl_runtime_resolve & ~3))->ip;
|
||||
got[-2] = (Elf32_Addr) ((struct fdesc *)
|
||||
((unsigned long) &_dl_runtime_resolve & ~3))->ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Static executable! */
|
||||
got[-2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
got[-2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GLRO(dl_profile) != NULL
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GLRO(dl_profile) != NULL
|
||||
&& _dl_name_match_p (GLRO(dl_profile), l))
|
||||
{
|
||||
{
|
||||
/* This is the object we are looking for. Say that
|
||||
we really want profiling and the timers are
|
||||
started. */
|
||||
GL(dl_profile_map) = l;
|
||||
}
|
||||
we really want profiling and the timers are
|
||||
started. */
|
||||
GL(dl_profile_map) = l;
|
||||
}
|
||||
|
||||
if((unsigned long) &_dl_runtime_profile & 3)
|
||||
{
|
||||
got[-2] = (Elf32_Addr) ((struct fdesc *)
|
||||
((unsigned long) &_dl_runtime_profile & ~3))->ip;
|
||||
got[-2] = (Elf32_Addr) ((struct fdesc *)
|
||||
((unsigned long) &_dl_runtime_profile & ~3))->ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Static executable */
|
||||
got[-2] = (Elf32_Addr) &_dl_runtime_profile;
|
||||
got[-2] = (Elf32_Addr) &_dl_runtime_profile;
|
||||
}
|
||||
}
|
||||
/* Plunk in the gp of this function descriptor so we
|
||||
can make the call to _dl_runtime_xxxxxx */
|
||||
got[-1] = ltp;
|
||||
break;
|
||||
/* Done looking for the GOT, and stub is setup */
|
||||
} /* else we found the GOT */
|
||||
} /* for, walk the relocs backwards */
|
||||
}
|
||||
/* Plunk in the gp of this function descriptor so we
|
||||
can make the call to _dl_runtime_xxxxxx */
|
||||
got[-1] = ltp;
|
||||
break;
|
||||
/* Done looking for the GOT, and stub is setup */
|
||||
} /* else we found the GOT */
|
||||
} /* for, walk the relocs backwards */
|
||||
|
||||
if(!got)
|
||||
return 0; /* No lazy linking for you! */
|
||||
|
||||
/* Process all the relocs, now that we know the GOT... */
|
||||
if(!got)
|
||||
return 0; /* No lazy linking for you! */
|
||||
|
||||
/* Process all the relocs, now that we know the GOT... */
|
||||
for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela))
|
||||
{
|
||||
reloc = (const Elf32_Rela *) iplt;
|
||||
@ -276,25 +276,25 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
fptr->gp = D_PTR (l, l_info[DT_PLTGOT]);
|
||||
}
|
||||
} /* r_type == R_PARISC_IPLT */
|
||||
} /* for all the relocations */
|
||||
} /* for all the relocations */
|
||||
} /* if lazy */
|
||||
else
|
||||
{
|
||||
for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela))
|
||||
{
|
||||
reloc = (const Elf32_Rela *) iplt;
|
||||
r_type = ELF32_R_TYPE (reloc->r_info);
|
||||
r_sym = ELF32_R_SYM (reloc->r_info);
|
||||
{
|
||||
reloc = (const Elf32_Rela *) iplt;
|
||||
r_type = ELF32_R_TYPE (reloc->r_info);
|
||||
r_sym = ELF32_R_SYM (reloc->r_info);
|
||||
|
||||
if (__builtin_expect ((r_type == R_PARISC_IPLT) && (r_sym == 0), 1))
|
||||
{
|
||||
fptr = (struct fdesc *) (reloc->r_offset + l_addr);
|
||||
/* Relocate this *ABS* entry, set only the gp, the rest is set later
|
||||
when elf_machine_rela_relative is called (WITHOUT the linkmap) */
|
||||
fptr->gp = D_PTR (l, l_info[DT_PLTGOT]);
|
||||
} /* r_type == R_PARISC_IPLT */
|
||||
} /* for all the relocations */
|
||||
}
|
||||
if (__builtin_expect ((r_type == R_PARISC_IPLT) && (r_sym == 0), 1))
|
||||
{
|
||||
fptr = (struct fdesc *) (reloc->r_offset + l_addr);
|
||||
/* Relocate this *ABS* entry, set only the gp, the rest is set later
|
||||
when elf_machine_rela_relative is called (WITHOUT the linkmap) */
|
||||
fptr->gp = D_PTR (l, l_info[DT_PLTGOT]);
|
||||
} /* r_type == R_PARISC_IPLT */
|
||||
} /* for all the relocations */
|
||||
}
|
||||
return lazy;
|
||||
}
|
||||
|
||||
@ -441,7 +441,7 @@ asm ( \
|
||||
" ldw -44(%sp),%r24\n" \
|
||||
\
|
||||
/* _dl_fini is a local function in the loader, so we construct \
|
||||
a false OPD here and pass this to the application. */ \
|
||||
a false OPD here and pass this to the application. */ \
|
||||
/* FIXME: Should be able to use P%, and LR RR to have the \
|
||||
the linker construct a proper OPD. */ \
|
||||
" .section .data\n" \
|
||||
@ -462,7 +462,7 @@ asm ( \
|
||||
" depi 2,31,2,%r23\n" /* delay slot */ \
|
||||
);
|
||||
|
||||
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
|
||||
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
|
||||
a TLS variable, so references should not be allowed to define the value.
|
||||
ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
|
||||
of the main executable's symbols, as for a COPY reloc. */
|
||||
@ -505,7 +505,7 @@ dl_platform_init (void)
|
||||
/* Avoid an empty string which would disturb us. */
|
||||
GLRO(dl_platform) = NULL;
|
||||
}
|
||||
|
||||
|
||||
#endif /* !dl_machine_h */
|
||||
|
||||
/* These are only actually used where RESOLVE_MAP is defined, anyway. */
|
||||
@ -523,11 +523,12 @@ dl_platform_init (void)
|
||||
| (((as14) & 0x2000) >> 13))
|
||||
|
||||
auto void __attribute__((always_inline))
|
||||
elf_machine_rela (struct link_map *map,
|
||||
elf_machine_rela (struct link_map *map,
|
||||
const Elf32_Rela *reloc,
|
||||
const Elf32_Sym *sym,
|
||||
const Elf32_Sym *sym,
|
||||
const struct r_found_version *version,
|
||||
void *const reloc_addr_arg)
|
||||
void *const reloc_addr_arg,
|
||||
int skip_ifunc)
|
||||
{
|
||||
Elf32_Addr *const reloc_addr = reloc_addr_arg;
|
||||
const Elf32_Sym *const refsym = sym;
|
||||
@ -557,7 +558,7 @@ elf_machine_rela (struct link_map *map,
|
||||
# else
|
||||
sym_map = RESOLVE_MAP (&sym, version, r_type);
|
||||
# endif
|
||||
|
||||
|
||||
if (sym_map)
|
||||
{
|
||||
value = sym ? sym_map->l_addr + sym->st_value : 0;
|
||||
@ -584,7 +585,7 @@ elf_machine_rela (struct link_map *map,
|
||||
case R_PARISC_DIR21L:
|
||||
{
|
||||
unsigned int insn = *(unsigned int *)reloc_addr;
|
||||
value = sym_map->l_addr + sym->st_value
|
||||
value = sym_map->l_addr + sym->st_value
|
||||
+ ((reloc->r_addend + 0x1000) & -0x2000);
|
||||
value = value >> 11;
|
||||
insn = (insn &~ 0x1fffff) | reassemble_21 (value);
|
||||
@ -595,7 +596,7 @@ elf_machine_rela (struct link_map *map,
|
||||
case R_PARISC_DIR14R:
|
||||
{
|
||||
unsigned int insn = *(unsigned int *)reloc_addr;
|
||||
value = ((sym_map->l_addr + sym->st_value) & 0x7ff)
|
||||
value = ((sym_map->l_addr + sym->st_value) & 0x7ff)
|
||||
+ (((reloc->r_addend & 0x1fff) ^ 0x1000) - 0x1000);
|
||||
insn = (insn &~ 0x3fff) | reassemble_14 (value);
|
||||
*(unsigned int *)reloc_addr = insn;
|
||||
@ -604,17 +605,17 @@ elf_machine_rela (struct link_map *map,
|
||||
|
||||
case R_PARISC_PLABEL32:
|
||||
/* Easy rule: If there is a symbol and it is global, then we
|
||||
need to make a dynamic function descriptor. Otherwise we
|
||||
have the address of a PLT slot for a local symbol which we
|
||||
know to be unique. */
|
||||
need to make a dynamic function descriptor. Otherwise we
|
||||
have the address of a PLT slot for a local symbol which we
|
||||
know to be unique. */
|
||||
if (sym == NULL
|
||||
|| sym_map == NULL
|
||||
|| ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
|
||||
{
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Set bit 30 to indicate to $$dyncall that this is a PLABEL.
|
||||
We have to do this outside of the generic function descriptor
|
||||
We have to do this outside of the generic function descriptor
|
||||
code, since it doesn't know about our requirement for setting
|
||||
protection bits */
|
||||
value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
|
||||
@ -625,17 +626,17 @@ elf_machine_rela (struct link_map *map,
|
||||
{
|
||||
unsigned int insn = *(unsigned int *)reloc_addr;
|
||||
|
||||
if (__builtin_expect (sym == NULL, 0))
|
||||
break;
|
||||
if (__builtin_expect (sym == NULL, 0))
|
||||
break;
|
||||
|
||||
value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
|
||||
value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
|
||||
|
||||
if (r_type == R_PARISC_PLABEL21L)
|
||||
if (r_type == R_PARISC_PLABEL21L)
|
||||
{
|
||||
value >>= 11;
|
||||
insn = (insn &~ 0x1fffff) | reassemble_21 (value);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
value &= 0x7ff;
|
||||
insn = (insn &~ 0x3fff) | reassemble_14 (value);
|
||||
@ -647,16 +648,16 @@ elf_machine_rela (struct link_map *map,
|
||||
|
||||
case R_PARISC_IPLT:
|
||||
if (__builtin_expect (sym_map != NULL, 1))
|
||||
{
|
||||
elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr,
|
||||
{
|
||||
elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr,
|
||||
DL_FIXUP_MAKE_VALUE(sym_map, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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, reloc, reloc_addr,
|
||||
DL_FIXUP_MAKE_VALUE(map, value));
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case R_PARISC_COPY:
|
||||
@ -687,21 +688,21 @@ elf_machine_rela (struct link_map *map,
|
||||
|
||||
case R_PARISC_TLS_DTPOFF32:
|
||||
/* During relocation all TLS symbols are defined and used.
|
||||
Therefore the offset is already correct. */
|
||||
Therefore the offset is already correct. */
|
||||
if (sym != NULL)
|
||||
*reloc_addr = sym->st_value;
|
||||
*reloc_addr = sym->st_value;
|
||||
return;
|
||||
|
||||
case R_PARISC_TLS_TPREL32:
|
||||
/* The offset is negative, forward from the thread pointer */
|
||||
if (sym != NULL)
|
||||
{
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
{
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
value = sym_map->l_tls_offset + sym->st_value + reloc->r_addend;
|
||||
}
|
||||
break;
|
||||
#endif /* use TLS */
|
||||
|
||||
|
||||
case R_PARISC_NONE: /* Alright, Wilbur. */
|
||||
return;
|
||||
|
||||
@ -721,13 +722,13 @@ elf_machine_rela_relative (Elf32_Addr l_addr,
|
||||
{
|
||||
unsigned long const r_type = ELF32_R_TYPE (reloc->r_info);
|
||||
Elf32_Addr *const reloc_addr = reloc_addr_arg;
|
||||
static char msgbuf[] = { "Unknown" };
|
||||
static char msgbuf[] = { "Unknown" };
|
||||
struct link_map map;
|
||||
Elf32_Addr value;
|
||||
|
||||
value = l_addr + reloc->r_addend;
|
||||
|
||||
if (ELF32_R_SYM (reloc->r_info) != 0){
|
||||
if (ELF32_R_SYM (reloc->r_info) != 0){
|
||||
_dl_error_printf ("%s: In elf_machine_rela_relative "
|
||||
"ELF32_R_SYM (reloc->r_info) != 0. Aborting.",
|
||||
rtld_progname ?: "<program name unknown>");
|
||||
@ -769,7 +770,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr,
|
||||
|
||||
auto void __attribute__((always_inline))
|
||||
elf_machine_lazy_rel (struct link_map *map,
|
||||
Elf32_Addr l_addr, const Elf32_Rela *reloc)
|
||||
Elf32_Addr l_addr, const Elf32_Rela *reloc,
|
||||
int skip_ifunc)
|
||||
{
|
||||
/* We don't have anything to do here. elf_machine_runtime_setup has
|
||||
done all the relocs already. */
|
||||
|
Loading…
Reference in New Issue
Block a user