* sysdeps/mips/dl-machine.h (ELF_MACHINE_NO_RELA): Delete.

(elf_machine_reloc): New function, retaining the body of
	elf_machine_rel.  Take the reloc's r_info field as an argument,
	not the reloc itself.  Add extra r_addend and inplace_p arguments.
	When inplace_p is false, use r_addend as the addend, not the contents
	of the relocation field.  Hoist the conversion of reloc_addr to
	"ELFW(Addr) *".  Don't try to apply TLS relocations against
	undefined symbols.  Add R_MIPS_GLOB_DAT support.
	(elf_machine_rel, elf_machine_rela): Use elf_machine_reloc.
	(elf_machine_lazy_rel): Change the reloc type from ElfW(Rel)
	to ElfW(Rela).
This commit is contained in:
Daniel Jacobowitz 2007-01-08 15:34:50 +00:00
parent 2caa93e206
commit cb5bcf7412
2 changed files with 83 additions and 20 deletions

View file

@ -1,3 +1,17 @@
2007-01-08 Richard Sandiford <richard@codesourcery.com>
* sysdeps/mips/dl-machine.h (ELF_MACHINE_NO_RELA): Delete.
(elf_machine_reloc): New function, retaining the body of
elf_machine_rel. Take the reloc's r_info field as an argument,
not the reloc itself. Add extra r_addend and inplace_p arguments.
When inplace_p is false, use r_addend as the addend, not the contents
of the relocation field. Hoist the conversion of reloc_addr to
"ELFW(Addr) *". Don't try to apply TLS relocations against
undefined symbols. Add R_MIPS_GLOB_DAT support.
(elf_machine_rel, elf_machine_rela): Use elf_machine_reloc.
(elf_machine_lazy_rel): Change the reloc type from ElfW(Rel)
to ElfW(Rela).
2007-01-08 Daniel Jacobowitz <dan@codesourcery.com>
* sysdeps/mips/ldsodefs.h: Merge sysdeps/mips/elf/ldsodefs.h. Correct

View file

@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. MIPS version.
Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006
Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
@ -282,9 +282,6 @@ do { \
".previous"\
);
/* The MIPS never uses Elfxx_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1
/* Names of the architecture-specific auditing callback functions. */
# if _MIPS_SIM == _ABIO32
# define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
@ -301,16 +298,18 @@ do { \
#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
/* Perform a relocation described by R_INFO at the location pointed to
by RELOC_ADDR. SYM is the relocation symbol specified by R_INFO and
MAP is the object containing the reloc. */
auto inline void
__attribute__ ((always_inline))
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version,
void *const reloc_addr)
elf_machine_reloc (struct link_map *map, ElfW(Word) r_info,
const ElfW(Sym) *sym, const struct r_found_version *version,
void *reloc_addr, ElfW(Addr) r_addend, int inplace_p)
{
const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
const unsigned long int r_type = ELFW(R_TYPE) (r_info);
ElfW(Addr) *addr_field = (ElfW(Addr) *) reloc_addr;
#if !defined RTLD_BOOTSTRAP && !defined SHARED
/* This is defined in rtld.c, but nowhere in the static libc.a;
@ -342,18 +341,28 @@ elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
case R_MIPS_TLS_DTPMOD64:
case R_MIPS_TLS_DTPMOD32:
if (sym_map)
*(ElfW(Addr) *)reloc_addr = sym_map->l_tls_modid;
*addr_field = sym_map->l_tls_modid;
break;
case R_MIPS_TLS_DTPREL64:
case R_MIPS_TLS_DTPREL32:
*(ElfW(Addr) *)reloc_addr += TLS_DTPREL_VALUE (sym);
if (sym)
{
if (inplace_p)
r_addend = *addr_field;
*addr_field = r_addend + TLS_DTPREL_VALUE (sym);
}
break;
case R_MIPS_TLS_TPREL32:
case R_MIPS_TLS_TPREL64:
CHECK_STATIC_TLS (map, sym_map);
*(ElfW(Addr) *)reloc_addr += TLS_TPREL_VALUE (sym_map, sym);
if (sym)
{
CHECK_STATIC_TLS (map, sym_map);
if (inplace_p)
r_addend = *addr_field;
*addr_field = r_addend + TLS_TPREL_VALUE (sym_map, sym);
}
break;
}
@ -367,13 +376,14 @@ elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
case R_MIPS_REL32:
#endif
{
int symidx = ELFW(R_SYM) (reloc->r_info);
int symidx = ELFW(R_SYM) (r_info);
ElfW(Addr) reloc_value;
/* Support relocations on mis-aligned offsets. Should we ever
implement RELA, this should be replaced with an assignment
from reloc->r_addend. */
__builtin_memcpy (&reloc_value, reloc_addr, sizeof (reloc_value));
if (inplace_p)
/* Support relocations on mis-aligned offsets. */
__builtin_memcpy (&reloc_value, reloc_addr, sizeof (reloc_value));
else
reloc_value = r_addend;
if (symidx)
{
@ -424,6 +434,31 @@ elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
__builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
}
break;
#ifndef RTLD_BOOTSTRAP
#if _MIPS_SIM == _ABI64
case (R_MIPS_64 << 8) | R_MIPS_GLOB_DAT:
#else
case R_MIPS_GLOB_DAT:
#endif
{
int symidx = ELFW(R_SYM) (r_info);
const ElfW(Word) gotsym
= (const ElfW(Word)) map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
if (__builtin_expect ((ElfW(Word)) symidx >= gotsym, 1))
{
const ElfW(Addr) *got
= (const ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
const ElfW(Word) local_gotno
= ((const ElfW(Word))
map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val);
ElfW(Addr) reloc_value = got[symidx + local_gotno - gotsym];
__builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
}
}
break;
#endif
case R_MIPS_NONE: /* Alright, Wilbur. */
break;
#if _MIPS_SIM == _ABI64
@ -436,7 +471,7 @@ elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
itself. For ABI compliance, we ignore such _64 dummy
relocations. For RELA, this may be simply removed, since
it's totally unnecessary. */
if (ELFW(R_SYM) (reloc->r_info) == 0)
if (ELFW(R_SYM) (r_info) == 0)
break;
/* Fall through. */
#endif
@ -446,6 +481,18 @@ elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
}
}
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
auto inline void
__attribute__ ((always_inline))
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version,
void *const reloc_addr)
{
elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr, 0, 1);
}
auto inline void
__attribute__((always_inline))
elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
@ -457,7 +504,7 @@ elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
auto inline void
__attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map,
ElfW(Addr) l_addr, const ElfW(Rel) *reloc)
ElfW(Addr) l_addr, const ElfW(Rela) *reloc)
{
/* Do nothing. */
}
@ -468,6 +515,8 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version,
void *const reloc_addr)
{
elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr,
reloc->r_addend, 0);
}
auto inline void