diff options
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/ldso/cris/dl-startup.h | 35 | ||||
-rw-r--r-- | ldso/ldso/cris/dl-sysdep.h | 24 | ||||
-rw-r--r-- | ldso/ldso/cris/resolve.S | 88 |
3 files changed, 116 insertions, 31 deletions
diff --git a/ldso/ldso/cris/dl-startup.h b/ldso/ldso/cris/dl-startup.h index 3274b41a5..417cb5096 100644 --- a/ldso/ldso/cris/dl-startup.h +++ b/ldso/ldso/cris/dl-startup.h @@ -4,22 +4,43 @@ /* This code fixes the stack pointer so that the dynamic linker * can find argc, argv and auxvt (Auxillary Vector Table). */ +#ifdef __arch_v32 + +asm("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" lapc _dl_start,$r9\n" \ +" jsr $r9\n" \ +" nop\n" \ +" moveq 0,$r8\n" \ +" jump $r10\n" \ +" move $r8,$srp\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#else + asm("" \ " .text\n" \ " .globl _start\n" \ " .type _start,@function\n" \ "_start:\n" \ -" move.d $sp,$r10\n" \ -" move.d $pc,$r9\n" \ -" add.d _dl_start - ., $r9\n" \ -" jsr $r9\n" \ -" moveq 0,$r8\n" \ -" move $r8,$srp\n" \ -" jump $r10\n" \ +" move.d $sp,$r10\n" \ +" move.d $pc,$r9\n" \ +" add.d _dl_start - ., $r9\n" \ +" jsr $r9\n" \ +" moveq 0,$r8\n" \ +" move $r8,$srp\n" \ +" jump $r10\n" \ " .size _start,.-_start\n" \ " .previous\n" \ ); +#endif /* __arch_v32 */ /* Get a pointer to the argv array. On many platforms this can be just * the address if the first argument, on other platforms we need to diff --git a/ldso/ldso/cris/dl-sysdep.h b/ldso/ldso/cris/dl-sysdep.h index b58f5e0a3..b5fa89035 100644 --- a/ldso/ldso/cris/dl-sysdep.h +++ b/ldso/ldso/cris/dl-sysdep.h @@ -68,8 +68,32 @@ elf_machine_load_address(void) { Elf32_Addr gotaddr_diff; +#ifdef __arch_v32 + extern char ___CRISv32_dummy[] __asm__ ("_dl_start"); + + __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t" + "lapc _dl_start,%0\n\t" + "sub.d [$acr],%0" + /* For v32, we need to force GCC to have R0 loaded with + _GLOBAL_OFFSET_TABLE_ at this point, which might not + otherwise have happened in the caller. (For v10, it's + loaded for non-global variables too, so we don't need + anything special there.) We accomplish this by faking the + address of a global variable (as seen by GCC) as input to + the asm; that address calculation goes through the GOT. + Use of this function happens before we've filled in the + GOT, so the address itself will not be correctly + calculated, therefore we don't use any symbol whose + address may be re-used later on. Let's just reuse the + _dl_start symbol, faking it as a global by renaming it as + another variable through an asm. */ + : "=r" (gotaddr_diff) + : "g" (___CRISv32_dummy) + : "acr"); +#else __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t" "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff)); +#endif return gotaddr_diff; } diff --git a/ldso/ldso/cris/resolve.S b/ldso/ldso/cris/resolve.S index 9d2f079fe..9ca27b5ef 100644 --- a/ldso/ldso/cris/resolve.S +++ b/ldso/ldso/cris/resolve.S @@ -17,33 +17,73 @@ .globl _dl_linux_resolve .type _dl_linux_resolve,@function +#ifdef __arch_v32 + +_dl_linux_resolve: + subq 4,$sp + move.d $r0,[$sp] + subq 4,$sp + move.d $r13,[$sp] + subq 4,$sp + move.d $r12,[$sp] + subq 4,$sp + move.d $r11,[$sp] + subq 4,$sp + addoq 5*4,$sp,$acr + move.d $r10,[$sp] + subq 4,$sp + move $mof,$r10 + move.d $r9,[$sp] + subq 4,$sp + move.d [$acr],$r11 + move $srp,[$sp] + lapc _GLOBAL_OFFSET_TABLE_,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 + nop + move.d $r10,$acr + move [$sp+],$srp + move.d [$sp+],$r9 + move.d [$sp+],$r10 + move.d [$sp+],$r11 + move.d [$sp+],$r12 + move.d [$sp+],$r13 + move.d [$sp+],$r0 + jump $acr + addq 4,$sp + +#else + _dl_linux_resolve: - push $r13 - push $r12 - push $r11 - push $r10 - push $r9 - push $r0 - push $srp - move.d [$sp+7*4],$r11 - move $mof,$r10 + push $r13 + push $r12 + push $r11 + push $r10 + push $r9 + push $r0 + push $srp + move.d [$sp+7*4],$r11 + move $mof,$r10 #ifdef __PIC__ - move.d $pc,$r0 - sub.d .:GOTOFF,$r0 - move.d _dl_linux_resolver:PLTG,$r9 - add.d $r0,$r9 - jsr $r9 + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 #else - jsr _dl_linux_resolver + jsr _dl_linux_resolver #endif - move.d $r10,[$sp+7*4] - pop $srp - pop $r0 - pop $r9 - pop $r10 - pop $r11 - pop $r12 - pop $r13 - jump [$sp+] + move.d $r10,[$sp+7*4] + pop $srp + pop $r0 + pop $r9 + pop $r10 + pop $r11 + pop $r12 + pop $r13 + jump [$sp+] + +#endif /* __arch_v32 */ .size _dl_linux_resolve, . - _dl_linux_resolve |