Module Name:    src
Committed By:   matt
Date:           Thu Mar  6 09:34:07 UTC 2014

Modified Files:
        src/libexec/ld.elf_so/arch/powerpc: ppc_reloc.c

Log Message:
Make ELF64 aware.


To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
diff -u src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.49 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.50
--- src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.49	Fri Mar 25 18:07:06 2011
+++ src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c	Thu Mar  6 09:34:07 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ppc_reloc.c,v 1.49 2011/03/25 18:07:06 joerg Exp $	*/
+/*	$NetBSD: ppc_reloc.c,v 1.50 2014/03/06 09:34:07 matt Exp $	*/
 
 /*-
  * Copyright (C) 1998	Tsubai Masanari
@@ -30,7 +30,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ppc_reloc.c,v 1.49 2011/03/25 18:07:06 joerg Exp $");
+__RCSID("$NetBSD: ppc_reloc.c,v 1.50 2014/03/06 09:34:07 matt Exp $");
 #endif /* not lint */
 
 #include <stdarg.h>
@@ -46,19 +46,37 @@ __RCSID("$NetBSD: ppc_reloc.c,v 1.49 201
 void _rtld_powerpc_pltcall(Elf_Word);
 void _rtld_powerpc_pltresolve(Elf_Word, Elf_Word);
 
-#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \
-			((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
-#define l(x) ((u_int32_t)(x) & 0xffff)
-
+#define __u64(x)	((uint64_t)(x))
+#define __u32(x)	((uint32_t)(x))
+#define __ha48		__u64(0xffffffff8000)
+#define __ha32		__u64(0xffff8000)
+#define __ha16		__u32(0x8000)
+#define __ha(x,n) ((((x) >> (n)) + ((x) & __ha##n) == __ha##n) & 0xffff)
+#define __hi(x,n) (((x) >> (n)) & 0xffff)
+#ifdef __LP64
+#define highesta(x)	__ha(__u64(x), 48)
+#define highest(x)	__hi(__u64(x), 48)
+#define higher(x)	__ha(__u64(x), 32)
+#define higher(x)	__hi(__u64(x), 32)
+#endif
+#define ha(x)		__ha(__u32(x), 16)
+#define hi(x)		__hi(__u32(x), 16)
+#define lo(x)		(__u32(x) & 0xffff)
+
+#ifdef _LP64
+/* function descriptor for _rtld_bind_start */
+extern const uint64_t _rtld_bind_start[3];
+#else
 void _rtld_bind_bssplt_start(void);
 void _rtld_bind_secureplt_start(void);
+#endif
 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
 caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
 static int _rtld_relocate_plt_object(const Obj_Entry *,
     const Elf_Rela *, int, Elf_Addr *);
 
 /*
- * The PPC PLT format consists of three sections:
+ * The PPC32 PLT format consists of three sections:
  * (1) The "pltcall" and "pltresolve" glue code.  This is always 18 words.
  * (2) The code part of the PLT entries.  There are 2 words per entry for
  *     up to 8192 entries, then 4 words per entry for any additional entries.
@@ -67,15 +85,19 @@ static int _rtld_relocate_plt_object(con
  *     per entry).
  */
 
-/*
- * Setup the plt glue routines (for bss-plt).
- */
-#define PLTCALL_SIZE	20
-#define PLTRESOLVE_SIZE	24
-
 void
 _rtld_setup_pltgot(const Obj_Entry *obj)
 {
+#ifdef _LP64
+	/*
+	 * For powerpc64, just copy the function descriptor to pltgot[0].
+	 */
+	if (obj->pltgot != NULL) {
+		obj->pltgot[0] = (Elf_Addr) _rtld_bind_start[0];
+		obj->pltgot[1] = (Elf_Addr) _rtld_bind_start[1];
+		obj->pltgot[2] = (Elf_Addr) obj;
+	}
+#else
 	/*
 	 * Secure-PLT is much more sane.
 	 */
@@ -86,6 +108,12 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
 		    obj->path, obj->gotptr,
 		    (void *) obj->gotptr[1], (void *) obj->gotptr[2]));
 	} else {
+/*
+ * Setup the plt glue routines (for bss-plt).
+ */
+#define BSSPLTCALL_SIZE		20
+#define BSSPLTRESOLVE_SIZE	24
+
 		Elf_Word *pltcall, *pltresolve;
 		Elf_Word *jmptab;
 		int N = obj->pltrelalim - obj->pltrela;
@@ -101,17 +129,17 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
 		pltcall = obj->pltgot;
 		jmptab = pltcall + 18 + N * 2;
 
-		memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE);
+		memcpy(pltcall, _rtld_powerpc_pltcall, BSSPLTCALL_SIZE);
 		pltcall[1] |= ha(jmptab);
-		pltcall[2] |= l(jmptab);
+		pltcall[2] |= lo(jmptab);
 
 		pltresolve = obj->pltgot + 8;
 
-		memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE);
+		memcpy(pltresolve, _rtld_powerpc_pltresolve, BSSPLTRESOLVE_SIZE);
 		pltresolve[0] |= ha(_rtld_bind_bssplt_start);
-		pltresolve[1] |= l(_rtld_bind_bssplt_start);
+		pltresolve[1] |= lo(_rtld_bind_bssplt_start);
 		pltresolve[3] |= ha(obj);
-		pltresolve[4] |= l(obj);
+		pltresolve[4] |= lo(obj);
 
 		/*
 		 * Invalidate the icache for only the code part of the PLT
@@ -119,6 +147,7 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
 		 */
 		__syncicache(pltcall, (char *)jmptab - (char *)pltcall);
 	}
+#endif
 }
 
 void
@@ -167,8 +196,12 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		case R_TYPE(NONE):
 			break;
 
-		case R_TYPE(32):	/* word32 S + A */
-		case R_TYPE(GLOB_DAT):	/* word32 S + A */
+#ifdef _LP64
+		case R_TYPE(ADDR64):	/* <address> S + A */
+#else
+		case R_TYPE(ADDR32):	/* <address> S + A */
+#endif
+		case R_TYPE(GLOB_DAT):	/* <address> S + A */
 			def = _rtld_find_symdef(symnum, obj, &defobj, false);
 			if (def == NULL)
 				return -1;
@@ -182,7 +215,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			    obj->path, (void *)*where, defobj->path));
 			break;
 
-		case R_TYPE(RELATIVE):	/* word32 B + A */
+		case R_TYPE(RELATIVE):	/* <address> B + A */
 			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
 			rdbg(("RELATIVE in %s --> %p", obj->path,
 			    (void *)*where));
@@ -204,7 +237,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			rdbg(("COPY (avoid in main)"));
 			break;
 
-		case R_TYPE(DTPMOD32):
+		case R_TYPE(DTPMOD):
 			def = _rtld_find_symdef(symnum, obj, &defobj, false);
 			if (def == NULL)
 				return -1;
@@ -215,7 +248,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			    obj->path, (void *)*where, defobj->path));
 			break;
 
-		case R_TYPE(DTPREL32):
+		case R_TYPE(DTPREL):
 			def = _rtld_find_symdef(symnum, obj, &defobj, false);
 			if (def == NULL)
 				return -1;
@@ -230,7 +263,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 			    obj->path, (void *)*where, defobj->path));
 			break;
 
-		case R_TYPE(TPREL32):
+		case R_TYPE(TPREL):
 			def = _rtld_find_symdef(symnum, obj, &defobj, false);
 			if (def == NULL)
 				return -1;
@@ -264,7 +297,9 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 int
 _rtld_relocate_plt_lazy(const Obj_Entry *obj)
 {
+#ifndef _LP64
 	Elf_Addr * const pltresolve = obj->pltgot + 8;
+#endif
 	const Elf_Rela *rela;
 	int reloff;
 
@@ -275,6 +310,12 @@ _rtld_relocate_plt_lazy(const Obj_Entry 
 
 		assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
 
+#ifdef _LP64
+		/*
+		 * For now, simply treat then as relative.
+		 */
+		*where += (Elf_Addr)obj->relocbase;
+#else
 		if (obj->gotptr != NULL) {
 			/*
 			 * For now, simply treat then as relative.
@@ -288,9 +329,9 @@ _rtld_relocate_plt_lazy(const Obj_Entry 
 				*where++ = 0x39600000 | reloff;
 			} else {
 				/* lis  r11,ha(reloff) */
-				/* addi	r11,l(reloff) */
+				/* addi	r11,lo(reloff) */
 				*where++ = 0x3d600000 | ha(reloff);
-				*where++ = 0x396b0000 | l(reloff);
+				*where++ = 0x396b0000 | lo(reloff);
 			}
 			/* b	pltresolve */
 			distance = (Elf_Addr)pltresolve - (Elf_Addr)where;
@@ -304,6 +345,7 @@ _rtld_relocate_plt_lazy(const Obj_Entry 
 			 */
 			/* __syncicache(where - 3, 12); */
 		}
+#endif
 	}
 
 	return 0;
@@ -332,10 +374,19 @@ _rtld_relocate_plt_object(const Obj_Entr
 	rdbg(("bind now/fixup in %s --> new=%p", 
 	    defobj->strtab + def->st_name, (void *)value));
 
+#ifdef _LP64
+	/*
+	 * For PowerPC64 we simply replace the entry in the PLTGOT with the
+	 * address of the routine.
+	 */
+	assert(where >= (Elf_Word *)obj->pltgot);
+	assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
+	*where = value;
+#else
 	if (obj->gotptr != NULL) {
 		/*
-		 * For Secure-PLT we simply replace the entry in GOT with the address
-		 * of the routine.
+		 * For Secure-PLT we simply replace the entry in GOT with the
+		 * address of the routine.
 		 */
 		assert(where >= (Elf_Word *)obj->pltgot);
 		assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
@@ -363,18 +414,18 @@ _rtld_relocate_plt_object(const Obj_Entr
 		} else {
 #ifdef notyet
 			/* lis  r11,ha(value) */
-			/* addi	r11,l(value) */
+			/* addi	r11,lo(value) */
 			/* mtctr r11 */
 			/* bctr */
 			*where++ = 0x3d600000 | ha(value);
-			*where++ = 0x396b0000 | l(value);
+			*where++ = 0x396b0000 | lo(value);
 			*where++ = 0x7d6903a6;
 			*where++ = 0x4e800420;
 #else
 			/* lis  r11,ha(reloff) */
-			/* addi	r11,l(reloff) */
+			/* addi	r11,lo(reloff) */
 			*where++ = 0x3d600000 | ha(reloff);
-			*where++ = 0x396b0000 | l(reloff);
+			*where++ = 0x396b0000 | lo(reloff);
 #endif
 		}
 		/* b	pltcall	*/
@@ -382,6 +433,7 @@ _rtld_relocate_plt_object(const Obj_Entr
 		*where++ = 0x48000000 | (distance & 0x03fffffc);
 		__syncicache(where - 3, 12);
 	}
+#endif /* _LP64 */
 
 	if (tp)
 		*tp = value;

Reply via email to