Module Name:    src
Committed By:   matt
Date:           Wed Jun  8 17:19:20 UTC 2011

Modified Files:
        src/sys/arch/powerpc/powerpc: kobj_machdep.c

Log Message:
Rework to support more relocations.  Reorganize so code doesn't need to be
replicated over and over.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/powerpc/powerpc/kobj_machdep.c

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

Modified files:

Index: src/sys/arch/powerpc/powerpc/kobj_machdep.c
diff -u src/sys/arch/powerpc/powerpc/kobj_machdep.c:1.4 src/sys/arch/powerpc/powerpc/kobj_machdep.c:1.5
--- src/sys/arch/powerpc/powerpc/kobj_machdep.c:1.4	Fri Mar 25 19:37:51 2011
+++ src/sys/arch/powerpc/powerpc/kobj_machdep.c	Wed Jun  8 17:19:20 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: kobj_machdep.c,v 1.4 2011/03/25 19:37:51 riz Exp $	*/
+/*	$NetBSD: kobj_machdep.c,v 1.5 2011/06/08 17:19:20 matt Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kobj_machdep.c,v 1.4 2011/03/25 19:37:51 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kobj_machdep.c,v 1.5 2011/06/08 17:19:20 matt Exp $");
 
 #define	ELFSIZE		ARCH_ELFSIZE
 
@@ -69,8 +69,8 @@
 	Elf_Addr *where;
 	Elf32_Half *hwhere;
 	Elf_Addr addr;
-	Elf_Addr addend;
-	Elf_Word rtype, symidx;
+	Elf_Sword addend;		/* needs to be signed */
+	u_int rtype, symidx;
 	const Elf_Rela *rela;
 
 	if (!isrela) {
@@ -88,18 +88,28 @@
        	case R_PPC_NONE:
 	       	break;
 
-	case R_PPC_32: /* word32 S + A */
+	case R_PPC_RELATIVE:	/* word32 B + A */
+		addend += relocbase;			/* A += B */
+	       	break;
+
+	case R_PPC_REL32:	/* word32 S + A - P */
+	case R_PPC_REL16:	/* half16* (S + A - P) */
+	case R_PPC_REL16_LO:	/* half16 #lo(S + A - P) */
+	case R_PPC_REL16_HI:	/* half16 #hi(S + A - P) */
+	case R_PPC_REL16_HA:	/* half16 #ha(S + A - P) */
+		addend -= relocbase + rela->r_offset;	/* A -= P */
+		/* FALLTHROUGH */
+
+	case R_PPC_32:		/* word32 S + A */
+	case R_PPC_16:		/* half16* S + A */
+       	case R_PPC_16_LO:	/* half16 #lo(S + A) */
+	case R_PPC_16_HA:	/* half16 #ha(S + A) */
+	case R_PPC_16_HI:	/* half16 #hi(S + A) */
        		addr = kobj_sym_lookup(ko, symidx);
 	       	if (addr == 0)
 	       		return -1;
-		addr += addend;
-	       	*where = addr;
-	       	break;
 
-       	case R_PPC_16_LO: /* #lo(S) */
-		addr = kobj_sym_lookup(ko, symidx);
-		if (addr == 0)
-			return -1;
+#if 0
 		/*
 		 * addend values are sometimes relative to sections
 		 * (i.e. .rodata) in rela, where in reality they
@@ -108,35 +118,41 @@
 		if (addr > relocbase && addr <= (relocbase + addend))
 			addr = relocbase + addend;
 		else
-			addr += addend;
-		*hwhere = addr & 0xffff;
+#endif
+		addend += addr;				/* A += S */
 		break;
 
-	case R_PPC_16_HA: /* #ha(S) */
-		addr = kobj_sym_lookup(ko, symidx);
-		if (addr == 0)
-			return -1;
-		/*
-		 * addend values are sometimes relative to sections
-		 * (i.e. .rodata) in rela, where in reality they
-		 * are relative to relocbase. Detect this condition.
-		 */
-		if (addr > relocbase && addr <= (relocbase + addend))
-			addr = relocbase + addend;
-		else
-			addr += addend;
-	       	*hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0))
-		    & 0xffff;
-		break;
+	default:
+       		printf("kobj_reloc: unexpected relocation type %u\n", rtype);
+		return -1;
+	}
+
 
-	case R_PPC_RELATIVE: /* word32 B + A */
-       		*where = relocbase + addend;
+	switch (rtype) {
+	case R_PPC_RELATIVE:	/* word32 B + A */
+	case R_PPC_REL32:	/* word32 S + A - P */
+	case R_PPC_32:		/* word32 S + A */
+	       	*where = addend;
 	       	break;
 
-	default:
-       		printf("kobj_reloc: unexpected relocation type %d\n",
-	       	    (int)rtype);
-		return -1;
+	case R_PPC_REL16:	/* half16* (S + A - P) */
+	case R_PPC_16:		/* half16* S + A */
+		if ((int16_t) addend != addend)
+			return -1;
+		/* FALLTHROUGH */
+	case R_PPC_REL16_LO:	/* half16 #lo(S + A - P) */
+       	case R_PPC_16_LO:	/* half16 #lo(S + A) */
+		*hwhere = addend & 0xffff;
+		break;
+
+	case R_PPC_REL16_HA:	/* half16 #ha(S + A - P) */
+	case R_PPC_16_HA:	/* half16 #ha(S + A) */
+		addend += 0x8000;
+		/* FALLTHROUGH */
+	case R_PPC_REL16_HI:	/* half16 #hi(S + A - P) */
+	case R_PPC_16_HI:	/* half16 #hi(S + A) */
+		*hwhere = (addend >> 16) & 0xffff;
+		break;
 	}
 
 	return 0;

Reply via email to