Changeset View
Changeset View
Standalone View
Standalone View
libexec/rtld-elf/powerpc/rtld_start.S
Show All 40 Lines | _ENTRY(.rtld_start) | ||||
stw %r3,16(%r1) /* argc */ | stw %r3,16(%r1) /* argc */ | ||||
stw %r4,20(%r1) /* argv */ | stw %r4,20(%r1) /* argv */ | ||||
stw %r5,24(%r1) /* envp */ | stw %r5,24(%r1) /* envp */ | ||||
/* stw %r6,28(%r1) *//* obj (always 0) */ | /* stw %r6,28(%r1) *//* obj (always 0) */ | ||||
/* stw %r7,32(%r1) *//* cleanup (always 0) */ | /* stw %r7,32(%r1) *//* cleanup (always 0) */ | ||||
stw %r8,36(%r1) /* ps_strings */ | stw %r8,36(%r1) /* ps_strings */ | ||||
/* | /* | ||||
* Perform initial relocation of ld-elf.so. Not as easy as it | * Perform initial relocation of ld-elf.so. Not as easy as it | ||||
bdragon: comment block will need updating to explain new procedure instead. | |||||
* sounds. | * sounds. | ||||
* - perform small forward branch to put PC into link reg | * - perform small forward branch to put PC into link reg | ||||
* - use link-time constants to determine offset to the | * - use link-time constants to determine offset to the | ||||
* _DYNAMIC section and the GOT. Add these to the PC to | * _DYNAMIC section and the GOT. Add these to the PC to | ||||
* convert to absolute addresses. | * convert to absolute addresses. | ||||
* - sync icache to allow execution of the SVR4 ABI-specified | |||||
* blrl instruction preceding the GOT | |||||
* - Use this instruction to determine the GOT absolute address | |||||
* - read GOT[0], which is the SVR4 ABI-specified link-time | * - read GOT[0], which is the SVR4 ABI-specified link-time | ||||
* value of _DYNAMIC. Subtract this value from the absolute | * value of _DYNAMIC. Subtract this value from the absolute | ||||
* value to determine the load address | * value to determine the load address | ||||
* - call reloc_non_plt_self() to fix up ld-elf.so's relocations | * - call reloc_non_plt_self() to fix up ld-elf.so's relocations | ||||
*/ | */ | ||||
bl 1f | bcl 20,31,1f | ||||
.long _DYNAMIC-. | 1: mflr %r30 | ||||
.long _GLOBAL_OFFSET_TABLE_-. /* branch lr + 4 */ | mr %r3,%r30 # save for _DYNAMIC | ||||
1: | addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha | ||||
mflr %r3 /* PC value at .long */ | addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l | ||||
lwz %r4,4(%r3) | addis %r3,%r3,_DYNAMIC-1b@ha # get _DYNAMIC actual address | ||||
add %r4,%r4,%r3 /* &_GLOBAL_OFFSET_TABLE-4, blrl insn. */ | addi %r3,%r3,_DYNAMIC-1b@l | ||||
dcbst %r0,%r4 /* sync i-cache with d-cache */ | lwz %r28,0(%r30) # get base-relative &_DYNAMIC | ||||
sync | sub %r28,%r3,%r28 # r28 = relocbase | ||||
icbi %r0,%r4 | mr %r4,%r28 # r4 = relocbase | ||||
isync | bl reloc_non_plt_self /* reloc_non_plt_self(&_DYNAMIC,base) */ | ||||
lwz %r4,0(%r3) /* offset to _DYNAMIC */ | |||||
add %r3,%r4,%r3 /* r3 = &_DYNAMIC, absolute value */ | |||||
bl _GLOBAL_OFFSET_TABLE_@local-4 | |||||
mflr %r4 /* &_GLOBAL_OFFSET_TABLE_, absolute value */ | |||||
lwz %r4,0(%r4) /* linker &_DYNAMIC, from got[0] */ | |||||
subf %r4,%r4,%r3 /* subtract to calculate relocbase */ | |||||
bl reloc_non_plt_self@plt /* reloc_non_plt_self(&_DYNAMIC,base) */ | |||||
/* | /* | ||||
* The _rtld() function likes to see a stack layout containing | * The _rtld() function likes to see a stack layout containing | ||||
* { argc, argv[0], argv[1] ... argv[N], 0, env[0], ... , env[N] } | * { argc, argv[0], argv[1] ... argv[N], 0, env[0], ... , env[N] } | ||||
* Since the PowerPC stack was 16-byte aligned at exec time, the | * Since the PowerPC stack was 16-byte aligned at exec time, the | ||||
* original stack layout has to be found by moving back a word | * original stack layout has to be found by moving back a word | ||||
* from the argv pointer. | * from the argv pointer. | ||||
*/ | */ | ||||
lwz %r4,20(%r1) /* restore argv */ | lwz %r4,20(%r1) /* restore argv */ | ||||
addi %r3,%r4,-4 /* locate argc ptr, &argv[-1] */ | addi %r3,%r4,-4 /* locate argc ptr, &argv[-1] */ | ||||
addi %r4,%r1,8 /* &exit_proc on stack */ | addi %r4,%r1,8 /* &exit_proc on stack */ | ||||
addi %r5,%r1,12 /* &obj_main on stack */ | addi %r5,%r1,12 /* &obj_main on stack */ | ||||
bl _rtld@plt /* &_start = _rtld(sp, &exit_proc, &obj_main)*/ | bl _rtld /* &_start = _rtld(sp, &exit_proc, &obj_main)*/ | ||||
mtlr %r3 | mtlr %r3 | ||||
/* | /* | ||||
* Restore args, with new obj/exit proc | * Restore args, with new obj/exit proc | ||||
*/ | */ | ||||
lwz %r3,16(%r1) /* argc */ | lwz %r3,16(%r1) /* argc */ | ||||
lwz %r4,20(%r1) /* argv */ | lwz %r4,20(%r1) /* argv */ | ||||
lwz %r5,24(%r1) /* envp */ | lwz %r5,24(%r1) /* envp */ | ||||
lwz %r6,12(%r1) /* obj */ | lwz %r6,12(%r1) /* obj */ | ||||
lwz %r7,8(%r1) /* exit proc */ | lwz %r7,8(%r1) /* exit proc */ | ||||
lwz %r8,36(%r1) /* ps_strings */ | lwz %r8,36(%r1) /* ps_strings */ | ||||
addi %r1,%r1,48 /* restore original stackptr */ | addi %r1,%r1,48 /* restore original stackptr */ | ||||
blrl /* _start(argc, argv, envp, obj, cleanup, ps_strings) */ | blrl /* _start(argc, argv, envp, obj, cleanup, ps_strings) */ | ||||
li %r0,1 /* _exit() */ | li %r0,1 /* _exit() */ | ||||
sc | sc | ||||
/* | /* | ||||
* _rtld_bind_secureplt_start() | |||||
* | |||||
* Call into the MI binder (Secure-PLT stub). | |||||
* secure-plt expects %r11 to be the offset to the rela entry. | |||||
* bss-plt expects %r11 to be index of the rela entry. | |||||
* So for bss-plt, we multiply the index by 12 to get the offset. | |||||
*/ | |||||
_ENTRY(_rtld_bind_secureplt_start) | |||||
stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr | |||||
stw %r0,20(%r1) # save r0 | |||||
/* | |||||
* Instead of division which is costly we will use multiplicative | |||||
* inverse. a / n = ((a * inv(n)) >> 32) | |||||
* where inv(n) = (0x100000000 + n - 1) / n | |||||
*/ | |||||
mr %r0,%r11 | |||||
lis %r11,0x15555556@h # load multiplicative inverse of 12 | |||||
ori %r11,%r11,0x15555556@l | |||||
mulhwu %r11,%r11,%r0 # get high half of multiplication | |||||
b 1f | |||||
/* | |||||
* _rtld_bind_start() | * _rtld_bind_start() | ||||
* | * | ||||
* Call into the MI binder. This routine is reached via the PLT call cell, | * Call into the MI binder. This routine is reached via the PLT call cell, | ||||
* and then _rtld_powerpc_pltresolve(). | * and then _rtld_powerpc_pltresolve(). | ||||
* On entry, %r11 contains the index of the PLT cell, and %r12 contains | * On entry, %r11 contains the index of the PLT cell, and %r12 contains | ||||
* a pointer to the ELF object for the file. | * a pointer to the ELF object for the file. | ||||
* Save all registers, call into the binder to resolve and fixup the external | * Save all registers, call into the binder to resolve and fixup the external | ||||
* routine, and then transfer to the external routine on return. | * routine, and then transfer to the external routine on return. | ||||
*/ | */ | ||||
.globl _rtld_bind | .globl _rtld_bind | ||||
_ENTRY(_rtld_bind_start) | _ENTRY(_rtld_bind_start) | ||||
stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr | stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr | ||||
stw %r0,20(%r1) # save r0 | stw %r0,20(%r1) # save r0 | ||||
1: | |||||
mflr %r0 | mflr %r0 | ||||
stw %r0,16(%r1) # save lr | stw %r0,16(%r1) # save lr | ||||
mfcr %r0 | mfcr %r0 | ||||
stw %r0,12(%r1) # save cr | stw %r0,12(%r1) # save cr | ||||
stmw %r3,24(%r1) # save r3-r31 | stmw %r3,24(%r1) # save r3-r31 | ||||
mr %r3,%r12 # obj | mr %r3,%r12 # obj | ||||
mulli %r4,%r11,12 # rela index * sizeof(Elf_Rela) | mulli %r4,%r11,12 # rela index * sizeof(Elf_Rela) | ||||
bl _rtld_bind@PLT # target addr = _rtld_bind(obj, reloff) | bl _rtld_bind # target addr = _rtld_bind(obj, reloff) | ||||
mtctr %r3 # move absolute target addr into ctr | mtctr %r3 # move absolute target addr into ctr | ||||
lmw %r3,24(%r1) # restore r3-r31 | lmw %r3,24(%r1) # restore r3-r31 | ||||
lwz %r0,12(%r1) # restore cr | lwz %r0,12(%r1) # restore cr | ||||
mtcr %r0 | mtcr %r0 | ||||
lwz %r0,16(%r1) # restore lr | lwz %r0,16(%r1) # restore lr | ||||
mtlr %r0 | mtlr %r0 | ||||
lwz %r0,20(%r1) # restore r0 | lwz %r0,20(%r1) # restore r0 | ||||
▲ Show 20 Lines • Show All 52 Lines • Show Last 20 Lines |
comment block will need updating to explain new procedure instead.