svn commit: r209885 - in head/libexec/rtld-elf: . powerpc64
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Sat Jul 10 17:43:25 UTC 2010
Author: nwhitehorn
Date: Sat Jul 10 17:43:24 2010
New Revision: 209885
URL: http://svn.freebsd.org/changeset/base/209885
Log:
RTLD support for powerpc64. A few small modifications to the Makefile
and symbol map are required to support various consequences of the dot
symbol scheme:
- Symbols beginning with a dot are reserved, so start private symbols with
an underscore.
- In order to set RTLD breakpoints, gdb must be able to locate the text
entry point, not the data section function descriptor, so add
.r_debug_state to the symbol map on powerpc64.
Obtained from: projects/ppc64
Added:
head/libexec/rtld-elf/powerpc64/
- copied from r209845, head/libexec/rtld-elf/powerpc/
Modified:
head/libexec/rtld-elf/Makefile
head/libexec/rtld-elf/Symbol.map
head/libexec/rtld-elf/powerpc64/reloc.c
head/libexec/rtld-elf/powerpc64/rtld_machdep.h
head/libexec/rtld-elf/powerpc64/rtld_start.S
Modified: head/libexec/rtld-elf/Makefile
==============================================================================
--- head/libexec/rtld-elf/Makefile Sat Jul 10 15:36:27 2010 (r209884)
+++ head/libexec/rtld-elf/Makefile Sat Jul 10 17:43:24 2010 (r209885)
@@ -11,7 +11,11 @@ MAN= rtld.1
CSTD?= gnu99
CFLAGS+= -Wall -DFREEBSD_ELF -DIN_RTLD
CFLAGS+= -I${.CURDIR}/${MACHINE_ARCH} -I${.CURDIR}
+.if ${MACHINE_ARCH} == "powerpc64"
+LDFLAGS+= -nostdlib -e _rtld_start
+.else
LDFLAGS+= -nostdlib -e .rtld_start
+.endif
WARNS?= 2
INSTALLFLAGS= -C -b
PRECIOUSPROG=
Modified: head/libexec/rtld-elf/Symbol.map
==============================================================================
--- head/libexec/rtld-elf/Symbol.map Sat Jul 10 15:36:27 2010 (r209884)
+++ head/libexec/rtld-elf/Symbol.map Sat Jul 10 17:43:24 2010 (r209885)
@@ -15,6 +15,9 @@ FBSD_1.0 {
dlinfo;
dl_iterate_phdr;
r_debug_state;
+#ifdef __powerpc64__
+ .r_debug_state;
+#endif
__tls_get_addr;
};
Modified: head/libexec/rtld-elf/powerpc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc/reloc.c Fri Jul 9 11:27:33 2010 (r209845)
+++ head/libexec/rtld-elf/powerpc64/reloc.c Sat Jul 10 17:43:24 2010 (r209885)
@@ -43,16 +43,11 @@
#include "debug.h"
#include "rtld.h"
-#define _ppc_ha(x) ((((u_int32_t)(x) & 0x8000) ? \
- ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
-#define _ppc_la(x) ((u_int32_t)(x) & 0xffff)
-
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-
-#define PLT_EXTENDED_BEGIN (1 << 13)
-#define JMPTAB_BASE(N) (18 + N*2 + ((N > PLT_EXTENDED_BEGIN) ? \
- (N - PLT_EXTENDED_BEGIN)*2 : 0))
+struct funcdesc {
+ Elf_Addr addr;
+ Elf_Addr toc;
+ Elf_Addr env;
+};
/*
* Process the R_PPC_COPY relocations
@@ -109,7 +104,7 @@ do_copy_relocations(Obj_Entry *dstobj)
srcaddr = (const void *) (srcobj->relocbase+srcsym->st_value);
memcpy(dstaddr, srcaddr, size);
- dbg("copy_reloc: src=%p,dst=%p,size=%d\n",srcaddr,dstaddr,size);
+ dbg("copy_reloc: src=%p,dst=%p,size=%zd\n",srcaddr,dstaddr,size);
}
return (0);
@@ -168,8 +163,8 @@ reloc_nonplt_object(Obj_Entry *obj_rtld,
case R_PPC_NONE:
break;
- case R_PPC_ADDR32: /* word32 S + A */
- case R_PPC_GLOB_DAT: /* word32 S + A */
+ case R_PPC64_ADDR64: /* doubleword64 S + A */
+ case R_PPC_GLOB_DAT:
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL) {
@@ -185,7 +180,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld,
}
break;
- case R_PPC_RELATIVE: /* word32 B + A */
+ case R_PPC_RELATIVE: /* doubleword64 B + A */
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
/* As above, don't issue write unnecessarily */
@@ -216,7 +211,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld,
*/
break;
- case R_PPC_DTPMOD32:
+ case R_PPC64_DTPMOD64:
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
@@ -227,7 +222,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld,
break;
- case R_PPC_TPREL32:
+ case R_PPC64_TPREL64:
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
@@ -256,7 +251,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld,
break;
- case R_PPC_DTPREL32:
+ case R_PPC64_DTPREL64:
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
@@ -269,7 +264,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld,
break;
default:
- _rtld_error("%s: Unsupported relocation type %d"
+ _rtld_error("%s: Unsupported relocation type %ld"
" in non-PLT relocations\n", obj->path,
ELF_R_TYPE(rela->r_info));
return (-1);
@@ -287,6 +282,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry
const Elf_Rela *relalim;
const Elf_Rela *rela;
SymCache *cache;
+ int bytes = obj->nchains * sizeof(SymCache);
int r = -1;
/*
@@ -294,8 +290,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry
* limited amounts of stack available so we cannot use alloca().
*/
if (obj != obj_rtld) {
- cache = calloc(obj->nchains, sizeof(SymCache));
- /* No need to check for NULL here */
+ cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON,
+ -1, 0);
+ if (cache == MAP_FAILED)
+ cache = NULL;
} else
cache = NULL;
@@ -311,60 +309,39 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry
}
r = 0;
done:
- if (cache != NULL)
- free(cache);
+ if (cache) {
+ munmap(cache, bytes);
+ }
return (r);
}
+
/*
* Initialise a PLT slot to the resolving trampoline
*/
static int
reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
{
- Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
- Elf_Addr *pltresolve, *pltlongresolve, *jmptab;
- Elf_Addr distance;
- int N = obj->pltrelasize / sizeof(Elf_Rela);
- int reloff;
+ Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+ Elf_Addr *glink;
+ long reloff;
reloff = rela - obj->pltrela;
- if (reloff < 0)
- return (-1);
-
- pltlongresolve = obj->pltgot + 5;
- pltresolve = pltlongresolve + 5;
-
- distance = (Elf_Addr)pltresolve - (Elf_Addr)(where + 1);
-
- dbg(" reloc_plt_object: where=%p,pltres=%p,reloff=%x,distance=%x",
- (void *)where, (void *)pltresolve, reloff, distance);
+ if (obj->priv == NULL)
+ obj->priv = malloc(obj->pltrelasize);
+ glink = obj->priv + reloff*sizeof(Elf_Addr)*2;
- if (reloff < PLT_EXTENDED_BEGIN) {
- /* li r11,reloff */
- /* b pltresolve */
- where[0] = 0x39600000 | reloff;
- where[1] = 0x48000000 | (distance & 0x03fffffc);
- } else {
- jmptab = obj->pltgot + JMPTAB_BASE(N);
- jmptab[reloff] = (u_int)pltlongresolve;
-
- /* lis r11,jmptab[reloff]@ha */
- /* lwzu r12,jmptab[reloff]@l(r11) */
- /* mtctr r12 */
- /* bctr */
- where[0] = 0x3d600000 | _ppc_ha(&jmptab[reloff]);
- where[1] = 0x858b0000 | _ppc_la(&jmptab[reloff]);
- where[2] = 0x7d8903a6;
- where[3] = 0x4e800420;
+ if ((reloff < 0) || (reloff >= 0x8000)) {
+ return (-1);
}
-
- /*
- * The icache will be sync'd in init_pltgot, which is called
- * after all the slots have been updated
- */
+ dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%p", (void *)where, reloff, glink);
+
+ memcpy(where, _rtld_bind_start, sizeof(struct funcdesc));
+ ((struct funcdesc *)(where))->env = (Elf_Addr)glink;
+ *(glink++) = (Elf_Addr)obj;
+ *(glink++) = reloff*sizeof(Elf_Rela);
return (0);
}
@@ -380,7 +357,6 @@ reloc_plt(Obj_Entry *obj)
const Elf_Rela *rela;
if (obj->pltrelasize != 0) {
-
relalim = (const Elf_Rela *)((char *)obj->pltrela +
obj->pltrelasize);
for (rela = obj->pltrela; rela < relalim; rela++) {
@@ -440,150 +416,50 @@ reloc_jmpslots(Obj_Entry *obj)
/*
- * Update the value of a PLT jump slot. Branch directly to the target if
- * it is within +/- 32Mb, otherwise go indirectly via the pltcall
- * trampoline call and jump table.
+ * Update the value of a PLT jump slot.
*/
Elf_Addr
reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
const Obj_Entry *obj, const Elf_Rel *rel)
{
- Elf_Addr offset;
- const Elf_Rela *rela = (const Elf_Rela *) rel;
-
- dbg(" reloc_jmpslot: where=%p, target=%p",
- (void *)wherep, (void *)target);
+ dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)",
+ (void *)wherep, (void *)target, *(Elf_Addr *)target,
+ (Elf_Addr)defobj->relocbase);
/*
* At the PLT entry pointed at by `wherep', construct
* a direct transfer to the now fully resolved function
* address.
*/
- offset = target - (Elf_Addr)wherep;
-
- if (abs(offset) < 32*1024*1024) { /* inside 32MB? */
- /* b value # branch directly */
- *wherep = 0x48000000 | (offset & 0x03fffffc);
- __syncicache(wherep, 4);
- } else {
- Elf_Addr *pltcall, *jmptab;
- int distance;
- int N = obj->pltrelasize / sizeof(Elf_Rela);
- int reloff = rela - obj->pltrela;
-
- if (reloff < 0)
- return (-1);
-
- pltcall = obj->pltgot;
-
- dbg(" reloc_jmpslot: indir, reloff=%x, N=%x\n",
- reloff, N);
- jmptab = obj->pltgot + JMPTAB_BASE(N);
- jmptab[reloff] = target;
-
- if (reloff < PLT_EXTENDED_BEGIN) {
- /* for extended PLT entries, we keep the old code */
-
- distance = (Elf_Addr)pltcall - (Elf_Addr)(wherep + 1);
+ memcpy(wherep, (void *)target, sizeof(struct funcdesc));
+ if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) {
+ /*
+ * XXX: It is possible (e.g. LD_BIND_NOW) that the function
+ * descriptor we are copying has not yet been relocated.
+ * If this happens, fix it.
+ */
- /* li r11,reloff */
- /* b pltcall # use indirect pltcall routine */
- wherep[0] = 0x39600000 | reloff;
- wherep[1] = 0x48000000 | (distance & 0x03fffffc);
- __syncicache(wherep, 8);
- }
+ ((struct funcdesc *)(wherep))->addr +=
+ (Elf_Addr)defobj->relocbase;
+ ((struct funcdesc *)(wherep))->toc +=
+ (Elf_Addr)defobj->relocbase;
}
+ __asm __volatile("dcbst 0,%0; sync" :: "r"(wherep) : "memory");
+
return (target);
}
-
-/*
- * Setup the plt glue routines.
- */
-#define PLTCALL_SIZE 20
-#define PLTLONGRESOLVE_SIZE 20
-#define PLTRESOLVE_SIZE 24
-
void
init_pltgot(Obj_Entry *obj)
{
- Elf_Word *pltcall, *pltresolve, *pltlongresolve;
- Elf_Word *jmptab;
- int N = obj->pltrelasize / sizeof(Elf_Rela);
-
- pltcall = obj->pltgot;
-
- if (pltcall == NULL) {
- return;
- }
-
- /*
- * From the SVR4 PPC ABI:
- *
- * 'The first 18 words (72 bytes) of the PLT are reserved for
- * use by the dynamic linker.
- * ...
- * 'If the executable or shared object requires N procedure
- * linkage table entries, the link editor shall reserve 3*N
- * words (12*N bytes) following the 18 reserved words. The
- * first 2*N of these words are the procedure linkage table
- * entries themselves. The static linker directs calls to bytes
- * (72 + (i-1)*8), for i between 1 and N inclusive. The remaining
- * N words (4*N bytes) are reserved for use by the dynamic linker.'
- */
-
- /*
- * Copy the absolute-call assembler stub into the first part of
- * the reserved PLT area.
- */
- memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE);
-
- /*
- * Determine the address of the jumptable, which is the dyn-linker
- * reserved area after the call cells. Write the absolute address
- * of the jumptable into the absolute-call assembler code so it
- * can determine this address.
- */
- jmptab = obj->pltgot + JMPTAB_BASE(N);
- pltcall[1] |= _ppc_ha(jmptab); /* addis 11,11,jmptab at ha */
- pltcall[2] |= _ppc_la(jmptab); /* lwz 11,jmptab at l(11) */
-
- /*
- * Skip down 20 bytes into the initial reserved area and copy
- * in the standard resolving assembler call. Into this assembler,
- * insert the absolute address of the _rtld_bind_start routine
- * and the address of the relocation object.
- *
- * We place pltlongresolve first, so it can fix up its arguments
- * and then fall through to the regular PLT resolver.
- */
- pltlongresolve = obj->pltgot + 5;
-
- memcpy(pltlongresolve, _rtld_powerpc_pltlongresolve,
- PLTLONGRESOLVE_SIZE);
- pltlongresolve[0] |= _ppc_ha(jmptab); /* lis 12,jmptab at ha */
- pltlongresolve[1] |= _ppc_la(jmptab); /* addi 12,12,jmptab at l */
-
- pltresolve = pltlongresolve + PLTLONGRESOLVE_SIZE/sizeof(uint32_t);
- memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE);
- pltresolve[0] |= _ppc_ha(_rtld_bind_start);
- pltresolve[1] |= _ppc_la(_rtld_bind_start);
- pltresolve[3] |= _ppc_ha(obj);
- pltresolve[4] |= _ppc_la(obj);
-
- /*
- * Sync the icache for the byte range represented by the
- * trampoline routines and call slots.
- */
- __syncicache(pltcall, 72 + N * 8);
}
void
allocate_initial_tls(Obj_Entry *list)
{
- register Elf_Addr **tp __asm__("r2");
+ register Elf_Addr **tp __asm__("r13");
Elf_Addr **_tp;
/*
@@ -594,7 +470,7 @@ allocate_initial_tls(Obj_Entry *list)
tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
- _tp = (Elf_Addr **) ((char *) allocate_tls(list, NULL, TLS_TCB_SIZE, 8)
+ _tp = (Elf_Addr **) ((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16)
+ TLS_TP_OFFSET + TLS_TCB_SIZE);
/*
@@ -607,7 +483,7 @@ allocate_initial_tls(Obj_Entry *list)
void*
__tls_get_addr(tls_index* ti)
{
- register Elf_Addr **tp __asm__("r2");
+ register Elf_Addr **tp __asm__("r13");
char *p;
p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET
Modified: head/libexec/rtld-elf/powerpc64/rtld_machdep.h
==============================================================================
--- head/libexec/rtld-elf/powerpc/rtld_machdep.h Fri Jul 9 11:27:33 2010 (r209845)
+++ head/libexec/rtld-elf/powerpc64/rtld_machdep.h Sat Jul 10 17:43:24 2010 (r209885)
@@ -54,25 +54,17 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where,
void _rtld_bind_start(void);
/*
- * PLT functions. Not really correct prototypes, but the
- * symbol values are needed.
- */
-void _rtld_powerpc_pltlongresolve(void);
-void _rtld_powerpc_pltresolve(void);
-void _rtld_powerpc_pltcall(void);
-
-/*
* TLS
*/
#define TLS_TP_OFFSET 0x7000
#define TLS_DTV_OFFSET 0x8000
-#define TLS_TCB_SIZE 8
+#define TLS_TCB_SIZE 16
#define round(size, align) \
(((size) + (align) - 1) & ~((align) - 1))
#define calculate_first_tls_offset(size, align) \
- round(8, align)
+ round(16, align)
#define calculate_tls_offset(prev_offset, prev_size, size, align) \
round(prev_offset + prev_size, align)
#define calculate_tls_end(off, size) ((off) + (size))
Modified: head/libexec/rtld-elf/powerpc64/rtld_start.S
==============================================================================
--- head/libexec/rtld-elf/powerpc/rtld_start.S Fri Jul 9 11:27:33 2010 (r209845)
+++ head/libexec/rtld-elf/powerpc64/rtld_start.S Sat Jul 10 17:43:24 2010 (r209885)
@@ -34,16 +34,16 @@
.extern _GLOBAL_OFFSET_TABLE_
.extern _DYNAMIC
-_ENTRY(.rtld_start)
- stwu %r1,-48(%r1) /* 16-byte aligned stack for reg saves +
+_ENTRY(_rtld_start)
+ stdu %r1,-96(%r1) /* 16-byte aligned stack for reg saves +
exit_proc & obj _rtld args +
backchain & lrsave stack frame */
- stw %r3,16(%r1) /* argc */
- stw %r4,20(%r1) /* argv */
- stw %r5,24(%r1) /* envp */
-/* stw %r6,28(%r1) *//* obj (always 0) */
-/* stw %r7,32(%r1) *//* cleanup (always 0) */
- stw %r8,36(%r1) /* ps_strings */
+ std %r3,48(%r1) /* argc */
+ std %r4,56(%r1) /* argv */
+ std %r5,64(%r1) /* envp */
+/* std %r6,72(%r1) *//* obj (always 0) */
+/* std %r7,80(%r1) *//* cleanup (always 0) */
+ std %r8,88(%r1) /* ps_strings */
/*
* Perform initial relocation of ld-elf.so. Not as easy as it
@@ -52,35 +52,21 @@ _ENTRY(.rtld_start)
* - use link-time constants to determine offset to the
* _DYNAMIC section and the GOT. Add these to the PC to
* 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
- * value of _DYNAMIC. Subtract this value from the absolute
- * value to determine the load address
* - call reloc_non_plt_self() to fix up ld-elf.so's relocations
*/
+
bl 1f
- .long _DYNAMIC-.
- .long _GLOBAL_OFFSET_TABLE_-. /* branch lr + 4 */
+ .llong _DYNAMIC-.
1:
- mflr %r3 /* PC value at .long */
- lwz %r4,4(%r3)
- add %r4,%r4,%r3 /* &_GLOBAL_OFFSET_TABLE-4, blrl insn. */
- dcbst %r0,%r4 /* sync i-cache with d-cache */
- sync
- icbi %r0,%r4
- isync
-
- lwz %r4,0(%r3) /* offset to _DYNAMIC */
+ mflr %r3 /* PC value at .llong */
+ ld %r4,0(%r3) /* offset to _DYNAMIC */
add %r3,%r4,%r3 /* r3 = &_DYNAMIC, absolute value */
- bl _GLOBAL_OFFSET_TABLE_ at 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 */
+ ld %r4,-0x8000(%r2) /* First TOC entry is TOC base */
+ subf %r4,%r4,%r2 /* Subtract from real TOC base to get base */
- bl reloc_non_plt_self at plt /* reloc_non_plt_self(&_DYNAMIC,base) */
+ bl .reloc_non_plt_self /* reloc_non_plt_self(&_DYNAMIC,base) */
+ nop
/*
* The _rtld() function likes to see a stack layout containing
@@ -89,25 +75,27 @@ _ENTRY(.rtld_start)
* original stack layout has to be found by moving back a word
* from the argv pointer.
*/
- lwz %r4,20(%r1) /* restore argv */
- addi %r3,%r4,-4 /* locate argc ptr, &argv[-1] */
-
- addi %r4,%r1,8 /* &exit_proc on stack */
- addi %r5,%r1,12 /* &obj_main on stack */
-
- bl _rtld at plt /* &_start = _rtld(sp, &exit_proc, &obj_main)*/
+ ld %r4,56(%r1)
+ addi %r3,%r4,-8 /* locate argc ptr, &argv[-1] */
+ addi %r4,%r1,80 /* &exit_proc on stack */
+ addi %r5,%r1,72 /* &obj_main on stack */
+
+ bl ._rtld /* &_start = _rtld(sp, &exit_proc, &obj_main)*/
+ nop
+ ld %r2,8(%r3)
+ ld %r11,16(%r3)
+ ld %r3,0(%r3)
mtlr %r3
/*
* Restore args, with new obj/exit proc
*/
- lwz %r3,16(%r1) /* argc */
- lwz %r4,20(%r1) /* argv */
- lwz %r5,24(%r1) /* envp */
- lwz %r6,12(%r1) /* obj */
- lwz %r7,8(%r1) /* exit proc */
- lwz %r8,36(%r1) /* ps_strings */
- addi %r1,%r1,48 /* restore original stackptr */
+ ld %r3,48(%r1) /* argc */
+ ld %r4,56(%r1) /* argv */
+ ld %r5,64(%r1) /* envp */
+ ld %r6,72(%r1) /* obj */
+ ld %r7,80(%r1) /* exit proc */
+ ld %r8,88(%r1) /* ps_strings */
blrl /* _start(argc, argv, envp, obj, cleanup, ps_strings) */
@@ -117,84 +105,57 @@ _ENTRY(.rtld_start)
/*
* _rtld_bind_start()
*
- * Call into the MI binder. This routine is reached via the PLT call cell,
- * and then _rtld_powerpc_pltresolve().
- * On entry, %r11 contains the index of the PLT cell, and %r12 contains
- * a pointer to the ELF object for the file.
- * Save all registers, call into the binder to resolve and fixup the external
+ * Call into the MI binder. This routine is reached via the PLT call cell
+ * On entry, %r11 contains a pointer to the (object, relocation) tuple.
+ *
+ * Save all registers, call into the binder to resolve and fixup the external
* routine, and then transfer to the external routine on return.
*/
.globl _rtld_bind
_ENTRY(_rtld_bind_start)
- stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr
- stw %r0,20(%r1) # save r0
mflr %r0
- stw %r0,16(%r1) # save lr
+ std %r0,16(%r1) # save lr
mfcr %r0
- stw %r0,12(%r1) # save cr
- stmw %r3,24(%r1) # save r3-r31
+ std %r0,8(%r1) # save cr
- mr %r3,%r12 # obj
- mulli %r4,%r11,12 # rela index * sizeof(Elf_Rela)
- bl _rtld_bind at PLT # target addr = _rtld_bind(obj, reloff)
+ stdu %r1,-48-9*8(%r1) # stack space for 8 regs + header
+ std %r3,48+0*8(%r1) # save r3-r31
+ std %r4,48+1*8(%r1)
+ std %r5,48+2*8(%r1)
+ std %r6,48+3*8(%r1)
+ std %r7,48+4*8(%r1)
+ std %r8,48+5*8(%r1)
+ std %r9,48+6*8(%r1)
+ std %r10,48+7*8(%r1)
+ std %r12,48+8*8(%r1)
+
+ ld %r3,0(%r11)
+ ld %r4,8(%r11)
+ bl ._rtld_bind # target addr = _rtld_bind(obj, reloff)
+ nop
+
+ ld %r2,8(%r3)
+ ld %r11,16(%r3)
+ ld %r3,0(%r3)
mtctr %r3 # move absolute target addr into ctr
- lmw %r3,24(%r1) # restore r3-r31
- lwz %r0,12(%r1) # restore cr
+ ld %r3,48+0*8(%r1) # restore r3-r31
+ ld %r4,48+1*8(%r1)
+ ld %r5,48+2*8(%r1)
+ ld %r6,48+3*8(%r1)
+ ld %r7,48+4*8(%r1)
+ ld %r8,48+5*8(%r1)
+ ld %r9,48+6*8(%r1)
+ ld %r10,48+7*8(%r1)
+ ld %r12,48+8*8(%r1)
+
+ addi %r1,%r1,48+9*8 # restore stack
+
+ ld %r0,8(%r1) # restore cr
mtcr %r0
- lwz %r0,16(%r1) # restore lr
+ ld %r0,16(%r1) # restore lr
mtlr %r0
- lwz %r0,20(%r1) # restore r0
- addi %r1,%r1,160 # restore stack
bctr # jump to target
-
-/*
- * _rtld_powerpc_pltresolve()
- *
- * This routine is copied into the latter part of the 72-byte reserved
- * area at the start of the PLT. The absolute address of the _rtld_bind_start
- * routine, and the ELF object for the loaded file, are inserted into
- * the code by the reloc.c:init_pltgot() routine.
- * The first time an external routine is called, the PLT slot will
- * set up %r11 to the offset of the slot, and will jump to this routine.
- * The ELF object is shifted into %r11, and _rtld_bind_start is called
- * to complete the binding.
- */
-_ENTRY(_rtld_powerpc_pltlongresolve)
- lis %r12,0 # lis 12,jmptab at ha
- addi %r12,%r12,0 # addi 12,12,jmptab at l
- subf %r11,%r12,%r11 # reloff
- li %r12,2
- srw %r11,%r11,%r12 # index = reloff/sizeof(Elf_Addr)
-_ENTRY(_rtld_powerpc_pltresolve)
- lis %r12,0 # lis 12,_rtld_bind_start at ha
- addi %r12,%r12,0 # addi 12,12,_rtld_bind_start at l
- mtctr %r12
- lis %r12,0 # lis 12,obj at ha
- addi %r12,%r12,0 # addi 12,12,obj at l
- bctr
-
-/*
- * _rtld_powerpc_pltcall()
- *
- * This routine is copied into the 72-byte reserved area at the
- * start of the PLT. The reloc.c:init_pltgot() routine inserts
- * the absolute address of the jumptable.
- * Control is transferred to this routine when the binder has
- * located the external routine, but determined that it is > 32Mb
- * from the PLT slot. Code is inserted into the PLT slot to set up
- * %r11 with the jumptable index, and jump to here, where the
- * absolute address of the external routine is loaded from the
- * jumptable and transferred to
- */
-_ENTRY(_rtld_powerpc_pltcall)
- slwi %r11,%r11,2 # jmptab offset = index * 4
- addis %r11,%r11,0 # addis 11,11,jmptab at ha
- lwz %r11,0(%r11) # lwz 11,jmptab at l(11)
- mtctr %r11
- bctr # (*jmptab[index])()
-
-
More information about the svn-src-head
mailing list