(elf_machine_runtime_setup): Save original content of .got[1].

(ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP.
(ELF_MACHINE_PLT_REL): Define.
(elf_machine_rela, elf_machine_rela_relative): New.
(elf_machine_lazy_rel): Reinitialize R_ARM_JUMP_SLOT address instead
of adjusting it if prelinked and prelinking cannot be used.
This commit is contained in:
Ulrich Drepper 2001-12-12 00:11:47 +00:00
parent ef5f0af552
commit bcb5a520da
1 changed files with 87 additions and 3 deletions

View File

@ -92,6 +92,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
index into the .got section, load ip with &_GLOBAL_OFFSET_TABLE_[3],
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
/* If a library is prelinked but we have to relocate anyway,
we have to be able to undo the prelinking of .got.plt.
The prelinker saved us here address of .plt. */
if (got[1])
l->l_mach.plt = got[1] + l->l_addr;
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
/* The got[2] entry contains the address of a function which gets
@ -334,8 +339,9 @@ _dl_start_user:
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
#define ELF_MACHINE_JMP_SLOT R_ARM_JUMP_SLOT
/* The ARM never uses Elf32_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1
/* ARM never uses Elf32_Rela relocations for the dynamic linker.
Prelinked libraries may use Elf32_Rela though. */
#define ELF_MACHINE_PLT_REL 1
/* We define an initialization functions. This is called very early in
_dl_sysdep_start. */
@ -371,6 +377,12 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
#ifdef RESOLVE
/* ARM never uses Elf32_Rela relocations for the dynamic linker.
Prelinked libraries may use Elf32_Rela though. */
#ifdef RTLD_BOOTSTRAP
#define ELF_MACHINE_NO_RELA 1
#endif
extern char **_dl_argv;
/* Deal with an out-of-range PC24 reloc. */
@ -517,6 +529,64 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
}
}
#ifndef RTLD_BOOTSTRAP
static inline void
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
Elf32_Addr *const reloc_addr)
{
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
if (__builtin_expect (r_type == R_ARM_RELATIVE, 0))
*reloc_addr = map->l_addr + reloc->r_addend;
#ifndef RTLD_BOOTSTRAP
else if (__builtin_expect (r_type == R_ARM_NONE, 0))
return;
#endif
else
{
const Elf32_Sym *const refsym = sym;
Elf32_Addr value = RESOLVE (&sym, version, r_type);
if (sym)
value += sym->st_value;
switch (r_type)
{
case R_ARM_GLOB_DAT:
case R_ARM_JUMP_SLOT:
case R_ARM_ABS32:
*reloc_addr = value + reloc->r_addend;
break;
case R_ARM_PC24:
{
Elf32_Addr newvalue, topbits;
newvalue = value + reloc->r_addend - (Elf32_Addr)reloc_addr;
topbits = newvalue & 0xfe000000;
if (topbits != 0xfe000000 && topbits != 0x00000000)
{
newvalue = fix_bad_pc24(reloc_addr, value)
- (Elf32_Addr)reloc_addr + (addend << 2);
topbits = newvalue & 0xfe000000;
if (topbits != 0xfe000000 && topbits != 0x00000000)
{
_dl_signal_error (0, map->l_name, NULL,
"R_ARM_PC24 relocation out of range");
}
}
newvalue >>= 2;
value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
*reloc_addr = value;
}
break;
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
}
}
}
#endif
static inline void
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
Elf32_Addr *const reloc_addr)
@ -524,6 +594,15 @@ elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
*reloc_addr += l_addr;
}
#ifndef RTLD_BOOTSTRAP
static inline void
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
Elf32_Addr *const reloc_addr)
{
*reloc_addr = l_addr + reloc->r_addend;
}
#endif
static inline void
elf_machine_lazy_rel (struct link_map *map,
Elf32_Addr l_addr, const Elf32_Rel *reloc)
@ -532,7 +611,12 @@ elf_machine_lazy_rel (struct link_map *map,
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (r_type == R_ARM_JUMP_SLOT, 1))
*reloc_addr += l_addr;
{
if (__builtin_expect (map->l_mach.plt, 0) == 0)
*reloc_addr += l_addr;
else
*reloc_addr = map->l_mach.plt;
}
else
_dl_reloc_bad_type (map, r_type, 1);
}