mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 23:00:07 +00:00
Clean up R_ARM_PC24 handling.
This commit is contained in:
parent
53cea63e99
commit
fb228a2d94
@ -1,3 +1,9 @@
|
|||||||
|
2012-10-05 Roland McGrath <roland@hack.frob.com>
|
||||||
|
|
||||||
|
* sysdeps/arm/dl-machine.h (fix_bad_pc24): Rewritten, replaced with ...
|
||||||
|
(relocate_pc24): ... this new function.
|
||||||
|
(elf_machine_rel, elf_machine_rela): Update callers.
|
||||||
|
|
||||||
2012-10-02 Siddhesh Poyarekar <siddhesh@redhat.com>
|
2012-10-02 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h: Fix clone
|
* sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h: Fix clone
|
||||||
|
@ -302,36 +302,56 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
|
|||||||
#define ARCH_LA_PLTEXIT arm_gnu_pltexit
|
#define ARCH_LA_PLTEXIT arm_gnu_pltexit
|
||||||
|
|
||||||
#ifdef RESOLVE_MAP
|
#ifdef RESOLVE_MAP
|
||||||
|
/* Handle a PC24 reloc, including the out-of-range case. */
|
||||||
/* Deal with an out-of-range PC24 reloc. */
|
auto void
|
||||||
auto Elf32_Addr
|
relocate_pc24 (struct link_map *map, Elf32_Addr value,
|
||||||
fix_bad_pc24 (Elf32_Addr *const reloc_addr, Elf32_Addr value)
|
Elf32_Addr *const reloc_addr, Elf32_Sword addend)
|
||||||
{
|
{
|
||||||
static void *fix_page;
|
Elf32_Addr new_value;
|
||||||
static unsigned int fix_offset;
|
|
||||||
static size_t pagesize;
|
|
||||||
Elf32_Word *fix_address;
|
|
||||||
|
|
||||||
if (! fix_page)
|
/* Set NEW_VALUE based on V, and return true iff it overflows 24 bits. */
|
||||||
|
inline bool set_new_value (Elf32_Addr v)
|
||||||
|
{
|
||||||
|
new_value = v + addend - (Elf32_Addr) reloc_addr;
|
||||||
|
Elf32_Addr topbits = new_value & 0xfe000000;
|
||||||
|
return topbits != 0xfe000000 && topbits != 0x00000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_new_value (value))
|
||||||
{
|
{
|
||||||
if (! pagesize)
|
/* The PC-relative address doesn't fit in 24 bits! */
|
||||||
pagesize = getpagesize ();
|
|
||||||
fix_page = mmap (NULL, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC,
|
static void *fix_page;
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
static size_t fix_offset;
|
||||||
if (! fix_page)
|
if (fix_page == NULL)
|
||||||
assert (! "could not map page for fixup");
|
{
|
||||||
fix_offset = 0;
|
void *new_page = __mmap (NULL, GLRO(dl_pagesize),
|
||||||
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
|
if (new_page == MAP_FAILED)
|
||||||
|
_dl_signal_error (0, map->l_name, NULL,
|
||||||
|
"could not map page for fixup");
|
||||||
|
fix_page = new_page;
|
||||||
|
assert (fix_offset == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf32_Word *fix_address = fix_page + fix_offset;
|
||||||
|
fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
|
||||||
|
fix_address[1] = value;
|
||||||
|
|
||||||
|
fix_offset += sizeof fix_address[0] * 2;
|
||||||
|
if (fix_offset >= GLRO(dl_pagesize))
|
||||||
|
{
|
||||||
|
fix_page = NULL;
|
||||||
|
fix_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_new_value ((Elf32_Addr) fix_address))
|
||||||
|
_dl_signal_error (0, map->l_name, NULL,
|
||||||
|
"R_ARM_PC24 relocation out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
fix_address = (Elf32_Word *)(fix_page + fix_offset);
|
*reloc_addr = (*reloc_addr & 0xff000000) | ((new_value >> 2) & 0x00ffffff);
|
||||||
fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
|
|
||||||
fix_address[1] = value;
|
|
||||||
|
|
||||||
fix_offset += 8;
|
|
||||||
if (fix_offset >= pagesize)
|
|
||||||
fix_page = NULL;
|
|
||||||
|
|
||||||
return (Elf32_Addr)fix_address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
|
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
|
||||||
@ -473,30 +493,11 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R_ARM_PC24:
|
case R_ARM_PC24:
|
||||||
{
|
relocate_pc24 (map, value, reloc_addr,
|
||||||
Elf32_Sword addend;
|
/* Sign-extend the 24-bit addend in the
|
||||||
Elf32_Addr newvalue, topbits;
|
instruction (which counts instructions), and
|
||||||
|
then shift it up two so as to count bytes. */
|
||||||
addend = *reloc_addr & 0x00ffffff;
|
(((Elf32_Sword) *reloc_addr << 8) >> 8) << 2);
|
||||||
if (addend & 0x00800000) addend |= 0xff000000;
|
|
||||||
|
|
||||||
newvalue = value - (Elf32_Addr)reloc_addr + (addend << 2);
|
|
||||||
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;
|
break;
|
||||||
#if !defined RTLD_BOOTSTRAP
|
#if !defined RTLD_BOOTSTRAP
|
||||||
case R_ARM_TLS_DTPMOD32:
|
case R_ARM_TLS_DTPMOD32:
|
||||||
@ -589,26 +590,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
|||||||
*reloc_addr = value + reloc->r_addend;
|
*reloc_addr = value + reloc->r_addend;
|
||||||
break;
|
break;
|
||||||
case R_ARM_PC24:
|
case R_ARM_PC24:
|
||||||
{
|
relocate_pc24 (map, value, reloc_addr, reloc->r_addend);
|
||||||
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 + (reloc->r_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;
|
break;
|
||||||
#if !defined RTLD_BOOTSTRAP
|
#if !defined RTLD_BOOTSTRAP
|
||||||
case R_ARM_TLS_DTPMOD32:
|
case R_ARM_TLS_DTPMOD32:
|
||||||
|
Loading…
Reference in New Issue
Block a user