|
@@ -110,24 +110,20 @@ elf_machine_load_address (void)
|
|
extern void __dl_start asm ("_dl_start");
|
|
extern void __dl_start asm ("_dl_start");
|
|
Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
|
|
Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
|
|
Elf32_Addr pcrel_addr;
|
|
Elf32_Addr pcrel_addr;
|
|
-#if !defined __thumb__
|
|
+#if defined __OPTIMIZE__ && !defined __thumb__
|
|
asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
|
|
asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
|
|
#else
|
|
#else
|
|
|
|
+ /* A simple adr does not work in Thumb mode because the offset is
|
|
|
|
+ negative, and for debug builds may be too large. */
|
|
int tmp;
|
|
int tmp;
|
|
- /* The above adr will not work on thumb because it
|
|
+ asm ("adr %1, 1f\n\t"
|
|
- * is negative. The only safe way is to temporarily
|
|
+ "ldr %0, [%1]\n\t"
|
|
- * swap to arm.
|
|
+ "add %0, %0, %1\n\t"
|
|
- */
|
|
+ "b 2f\n\t"
|
|
- asm( ".align 2\n"
|
|
+ ".align 2\n\t"
|
|
- " bx pc\n"
|
|
+ "1: .word _dl_start - 1b\n\t"
|
|
- " nop \n"
|
|
+ "2:"
|
|
- " .arm \n"
|
|
+ : "=r" (pcrel_addr), "=r" (tmp));
|
|
- " 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
|
|
#endif
|
|
return pcrel_addr - got_addr;
|
|
return pcrel_addr - got_addr;
|
|
}
|
|
}
|