From owner-svn-src-stable-8@FreeBSD.ORG Sat Mar 20 15:28:41 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2076C106566B; Sat, 20 Mar 2010 15:28:41 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B7DD08FC0A; Sat, 20 Mar 2010 15:28:39 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o2KFSdl1012717; Sat, 20 Mar 2010 15:28:39 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o2KFSdlh012713; Sat, 20 Mar 2010 15:28:39 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <201003201528.o2KFSdlh012713@svn.freebsd.org> From: Nathan Whitehorn Date: Sat, 20 Mar 2010 15:28:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r205383 - stable/8/libexec/rtld-elf/powerpc X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 20 Mar 2010 15:28:41 -0000 Author: nwhitehorn Date: Sat Mar 20 15:28:39 2010 New Revision: 205383 URL: http://svn.freebsd.org/changeset/base/205383 Log: MFC r204211: Support the extended PLT format used when objects have more than 8192 PLT relocations on PPC32. Modified: stable/8/libexec/rtld-elf/powerpc/reloc.c stable/8/libexec/rtld-elf/powerpc/rtld_machdep.h stable/8/libexec/rtld-elf/powerpc/rtld_start.S Directory Properties: stable/8/libexec/rtld-elf/ (props changed) Modified: stable/8/libexec/rtld-elf/powerpc/reloc.c ============================================================================== --- stable/8/libexec/rtld-elf/powerpc/reloc.c Sat Mar 20 15:27:01 2010 (r205382) +++ stable/8/libexec/rtld-elf/powerpc/reloc.c Sat Mar 20 15:28:39 2010 (r205383) @@ -47,6 +47,13 @@ ((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)) + /* * Process the R_PPC_COPY relocations */ @@ -313,7 +320,6 @@ done: return (r); } - /* * Initialise a PLT slot to the resolving trampoline */ @@ -321,27 +327,43 @@ 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; + Elf_Addr *pltresolve, *pltlongresolve, *jmptab; Elf_Addr distance; + int N = obj->pltrelasize / sizeof(Elf_Rela); int reloff; reloff = rela - obj->pltrela; - if ((reloff < 0) || (reloff >= 0x8000)) { + if (reloff < 0) return (-1); - } - pltresolve = obj->pltgot + 8; + 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); - /* li r11,reloff */ - /* b pltresolve */ - where[0] = 0x39600000 | reloff; - where[1] = 0x48000000 | (distance & 0x03fffffc); + 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; + } + /* * The icache will be sync'd in init_pltgot, which is called @@ -453,25 +475,28 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr int N = obj->pltrelasize / sizeof(Elf_Rela); int reloff = rela - obj->pltrela; - if ((reloff < 0) || (reloff >= 0x8000)) { + if (reloff < 0) return (-1); - } pltcall = obj->pltgot; - dbg(" reloc_jmpslot: indir, reloff=%d, N=%d\n", + dbg(" reloc_jmpslot: indir, reloff=%x, N=%x\n", reloff, N); - jmptab = obj->pltgot + 18 + N * 2; + jmptab = obj->pltgot + JMPTAB_BASE(N); jmptab[reloff] = target; - distance = (Elf_Addr)pltcall - (Elf_Addr)(wherep + 1); + if (reloff < PLT_EXTENDED_BEGIN) { + /* for extended PLT entries, we keep the old code */ + + distance = (Elf_Addr)pltcall - (Elf_Addr)(wherep + 1); - /* li r11,reloff */ - /* b pltcall # use indirect pltcall routine */ - wherep[0] = 0x39600000 | reloff; - wherep[1] = 0x48000000 | (distance & 0x03fffffc); - __syncicache(wherep, 8); + /* li r11,reloff */ + /* b pltcall # use indirect pltcall routine */ + wherep[0] = 0x39600000 | reloff; + wherep[1] = 0x48000000 | (distance & 0x03fffffc); + __syncicache(wherep, 8); + } } return (target); @@ -481,13 +506,14 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr /* * Setup the plt glue routines. */ -#define PLTCALL_SIZE 20 -#define PLTRESOLVE_SIZE 24 +#define PLTCALL_SIZE 20 +#define PLTLONGRESOLVE_SIZE 20 +#define PLTRESOLVE_SIZE 24 void init_pltgot(Obj_Entry *obj) { - Elf_Word *pltcall, *pltresolve; + Elf_Word *pltcall, *pltresolve, *pltlongresolve; Elf_Word *jmptab; int N = obj->pltrelasize / sizeof(Elf_Rela); @@ -524,18 +550,27 @@ init_pltgot(Obj_Entry *obj) * of the jumptable into the absolute-call assembler code so it * can determine this address. */ - jmptab = pltcall + 18 + N * 2; + jmptab = obj->pltgot + JMPTAB_BASE(N); pltcall[1] |= _ppc_ha(jmptab); /* addis 11,11,jmptab@ha */ pltcall[2] |= _ppc_la(jmptab); /* lwz 11,jmptab@l(11) */ /* - * Skip down 32 bytes into the initial reserved area and copy + * 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. */ - pltresolve = obj->pltgot + 8; + pltlongresolve = obj->pltgot + 5; + + memcpy(pltlongresolve, _rtld_powerpc_pltlongresolve, + PLTLONGRESOLVE_SIZE); + pltlongresolve[0] |= _ppc_ha(jmptab); /* lis 12,jmptab@ha */ + pltlongresolve[1] |= _ppc_la(jmptab); /* addi 12,12,jmptab@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); Modified: stable/8/libexec/rtld-elf/powerpc/rtld_machdep.h ============================================================================== --- stable/8/libexec/rtld-elf/powerpc/rtld_machdep.h Sat Mar 20 15:27:01 2010 (r205382) +++ stable/8/libexec/rtld-elf/powerpc/rtld_machdep.h Sat Mar 20 15:28:39 2010 (r205383) @@ -57,6 +57,7 @@ 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); Modified: stable/8/libexec/rtld-elf/powerpc/rtld_start.S ============================================================================== --- stable/8/libexec/rtld-elf/powerpc/rtld_start.S Sat Mar 20 15:27:01 2010 (r205382) +++ stable/8/libexec/rtld-elf/powerpc/rtld_start.S Sat Mar 20 15:28:39 2010 (r205383) @@ -163,6 +163,12 @@ _ENTRY(_rtld_bind_start) * 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@ha + addi %r12,%r12,0 # addi 12,12,jmptab@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@ha addi %r12,%r12,0 # addi 12,12,_rtld_bind_start@l