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;