diff options
author | Mike Frysinger <vapier@gentoo.org> | 2006-01-31 00:29:30 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2006-01-31 00:29:30 +0000 |
commit | 8504c3b4d833a77dc3384a0af36a85aeb36d9dcc (patch) | |
tree | 6fc1656635285c4780ccc77e2e78601c69bd1f88 /ldso/ldso/arm/dl-sysdep.h | |
parent | 8472ea4c5d55b9bde2672ca01ebac1c9f1e73b81 (diff) |
John Bowler writes in Bug 385:
This patch changes all cases where the ARM assembler mov pc,rx
instructions are used to ensure that the thumb/arm interwork change of
process more works - in essence mov pc,rx needs to become bx rc.
The ldr pc or ldm rx, {pc} instructions are not changed - this is
fine on ARM >=v5 but will fail to restore thumb mode on ARM v4T,
i.e. this code will not provide support for thumb on ARM v4T.
One mov pc is left in resolve.S, this is fixed in a different patch -
thumb-resolve.patch
The changes are protected by __THUMB_INTERWORK__ - the original
mov instruction will work on newer architectures and is required on
arch v4 (not v4t) and earlier - those which did not support thumb -
so this is safe. See gcc lib1asmfuncs for a more exact test.
Diffstat (limited to 'ldso/ldso/arm/dl-sysdep.h')
-rw-r--r-- | ldso/ldso/arm/dl-sysdep.h | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h index 794c86a0c..194fd2eb7 100644 --- a/ldso/ldso/arm/dl-sysdep.h +++ b/ldso/ldso/arm/dl-sysdep.h @@ -85,7 +85,25 @@ elf_machine_load_address (void) extern void __dl_start asm ("_dl_start"); Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; Elf32_Addr pcrel_addr; +#if !defined __thumb__ asm ("adr %0, _dl_start" : "=r" (pcrel_addr)); +#else + int tmp; + /* The above adr will not work on thumb because it + * is negative. The only safe way is to temporarily + * swap to arm. + */ + asm( ".align 2\n" + " bx pc\n" + " nop \n" + " .arm \n" + " adr %0, _dl_start\n" + " .align 2\n" + " orr %1, pc, #1\n" + " bx %1\n" + " .force_thumb\n" + : "=r" (pcrel_addr), "=&r" (tmp)); +#endif return pcrel_addr - got_addr; } |