Unify the ELFv1 and ELFv2 code paths and make ELFv1 (the normal ABI) more

correct in the process.

MFC after:	2 weeks
This commit is contained in:
Nathan Whitehorn 2016-01-01 00:11:29 +00:00
parent 43a57fd160
commit a4c5dfc0fa
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=293018
2 changed files with 33 additions and 39 deletions

View File

@ -338,26 +338,19 @@ static int
reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
#if !defined(_CALL_ELF) || _CALL_ELF == 1
Elf_Addr *glink;
#endif
long reloff;
reloff = rela - obj->pltrela;
dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%#lx", (void *)where,
reloff, obj->glink);
#if !defined(_CALL_ELF) || _CALL_ELF == 1
if (obj->priv == NULL)
obj->priv = xmalloc(obj->pltrelasize);
glink = obj->priv + reloff*sizeof(Elf_Addr)*2;
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);
/* Glink code is 3 instructions after the first 32k, 2 before */
*where = (Elf_Addr)obj->glink + 32 +
8*((reloff < 0x8000) ? reloff : 0x8000) +
12*((reloff < 0x8000) ? 0 : (reloff - 0x8000));
#else
dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%#lx", (void *)where, reloff, obj->glink);
*where = (Elf_Addr)obj->glink + 4*reloff + 32;
#endif
@ -416,13 +409,6 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
target = (Elf_Addr)(defobj->relocbase + def->st_value);
#if 0
/* PG XXX */
dbg("\"%s\" in \"%s\" --> %p in \"%s\"",
defobj->strtab + def->st_name, basename(obj->path),
(void *)target, basename(defobj->path));
#endif
if (def == &sym_zero) {
/* Zero undefined weak symbols */
#if !defined(_CALL_ELF) || _CALL_ELF == 1
@ -461,12 +447,28 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
(void *)wherep, (void *)target, *(Elf_Addr *)target,
(Elf_Addr)defobj->relocbase);
/*
* For the trampoline, the second two elements of the function
* descriptor are unused, so we are fine replacing those at any time
* with the real ones with no thread safety implications. However, we
* need to make sure the main entry point pointer ([0]) is seen to be
* modified *after* the second two elements. This can't be done in
* general, since there are no barriers in the reading code, but put in
* some isyncs to at least make it a little better.
*/
memcpy(wherep, (void *)target, sizeof(struct funcdesc));
wherep[2] = ((Elf_Addr *)target)[2];
wherep[1] = ((Elf_Addr *)target)[1];
__asm __volatile ("isync" : : : "memory");
wherep[0] = ((Elf_Addr *)target)[0];
__asm __volatile ("isync" : : : "memory");
if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) {
/*
* XXX: It is possible (e.g. LD_BIND_NOW) that the function
* It is possible (LD_BIND_NOW) that the function
* descriptor we are copying has not yet been relocated.
* If this happens, fix it.
* If this happens, fix it. Don't worry about threading in
* this case since LD_BIND_NOW makes it irrelevant.
*/
((struct funcdesc *)(wherep))->addr +=
@ -481,8 +483,6 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
*wherep = target;
#endif
__asm __volatile("sync" ::: "memory");
return (target);
}
@ -506,7 +506,6 @@ reloc_gnu_ifunc(Obj_Entry *obj, int flags,
void
init_pltgot(Obj_Entry *obj)
{
#if defined(_CALL_ELF) && _CALL_ELF == 2
Elf_Addr *pltcall;
pltcall = obj->pltgot;
@ -515,10 +514,12 @@ init_pltgot(Obj_Entry *obj)
return;
}
#if defined(_CALL_ELF) && _CALL_ELF == 2
pltcall[0] = (Elf_Addr)&_rtld_bind_start;
pltcall[1] = (Elf_Addr)obj;
__asm __volatile("sync" ::: "memory");
#else
memcpy(pltcall, _rtld_bind_start, sizeof(struct funcdesc));
pltcall[2] = (Elf_Addr)obj;
#endif
}

View File

@ -111,10 +111,7 @@ _ENTRY(_rtld_start)
*
* Call into the MI binder. This routine is reached via the PLT call cell
*
* For ELFv1, on entry, %r11 contains a pointer to the (object, relocation)
* tuple.
*
* For ELFv2, %r11 contains an object pointer and %r0 contains the PLT index.
* On entry, %r11 contains an object pointer and %r0 contains the PLT index.
*
* Save all registers, call into the binder to resolve and fixup the external
* routine, and then transfer to the external routine on return.
@ -122,7 +119,7 @@ _ENTRY(_rtld_start)
.globl _rtld_bind
_ENTRY(_rtld_bind_start)
mr %r12,%r0 # shunt r0 immediately to r12 for ELFv2
mr %r12,%r0 # save r0 (index) immediately to r12
mflr %r0
std %r0,16(%r1) # save lr
mfcr %r0
@ -139,13 +136,9 @@ _ENTRY(_rtld_bind_start)
std %r9,64+6*8(%r1)
std %r10,64+7*8(%r1)
#if !defined(_CALL_ELF) || _CALL_ELF == 1
ld %r3,0(%r11)
ld %r4,8(%r11)
#else
mr %r3,%r11
mulli %r4,%r12,24 /* Multiply index by sizeof(Elf_Rela) */
#endif
mulli %r4,%r12,24 # Multiply index by sizeof(Elf_Rela)
bl _rtld_bind # target addr = _rtld_bind(obj, reloff)
nop