Module Name: src
Committed By: dsl
Date: Mon Aug 17 19:44:32 UTC 2009
Modified Files:
src/sys/arch/arm/arm32: kobj_machdep.c
Log Message:
Add support for R_ARM_PC24 relocations and fix R_ARM_ABS32.
Changes from PR/40309, but structure changed so there is a common error printf.
Compiles ok, but my quick kernel build failed to find module_init_md().
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/arm32/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/arm/arm32/kobj_machdep.c
diff -u src/sys/arch/arm/arm32/kobj_machdep.c:1.2 src/sys/arch/arm/arm32/kobj_machdep.c:1.3
--- src/sys/arch/arm/arm32/kobj_machdep.c:1.2 Mon Apr 28 20:23:13 2008
+++ src/sys/arch/arm/arm32/kobj_machdep.c Mon Aug 17 19:44:32 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: kobj_machdep.c,v 1.2 2008/04/28 20:23:13 martin Exp $ */
+/* $NetBSD: kobj_machdep.c,v 1.3 2009/08/17 19:44:32 dsl 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.2 2008/04/28 20:23:13 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kobj_machdep.c,v 1.3 2009/08/17 19:44:32 dsl Exp $");
#define ELFSIZE ARCH_ELFSIZE
@@ -91,44 +91,64 @@
switch (rtype) {
case R_ARM_NONE: /* none */
- break;
+ return 0;
case R_ARM_ABS32:
addr = kobj_sym_lookup(ko, symidx);
if (addr == 0)
- return -1;
- if (*where != addr)
- *where = addr;
-
- break;
+ break;
+ *where = addr + addend;
+ return 0;
case R_ARM_COPY: /* none */
- /*
- * There shouldn't be copy relocations in kernel
- * objects.
- */
- printf("kobj_reloc: unexpected R_COPY relocation\n");
- return -1;
+ /* There shouldn't be copy relocations in kernel objects. */
+ break;
case R_ARM_JUMP_SLOT:
addr = kobj_sym_lookup(ko, symidx);
- if (addr) {
- *where = addr;
- return 0;
- }
- return -1;
+ if (addr == 0)
+ break;
+ *where = addr;
+ return 0;
case R_ARM_RELATIVE: /* A + B */
addr = relocbase + addend;
if (*where != addr)
*where = addr;
- break;
+ return 0;
+
+ case R_ARM_PC24:
+ if (local)
+ return 0;
+
+ /* Remove the instruction from the 24 bit offset */
+ addend &= 0x00ffffff;
+
+ /* Sign extend if necessary */
+ if (addend & 0x00800000)
+ addend |= 0xff000000;
+
+ addr = kobj_sym_lookup(ko, symidx);
+ if (addr == 0)
+ break;
+
+ addend += ((uint32_t *)addr - (uint32_t *)where);
+
+ if ((addend & 0xff800000) != 0x00000000 &&
+ (addend & 0xff800000) != 0xff800000) {
+ printf ("Relocation %x too far @ %p\n", addend, where);
+ return -1;
+ }
+ *where = (*where & 0xff000000) | (addend & 0x00ffffff);
+ return 0;
default:
- printf("kobj_reloc: unexpected relocation type %d\n", rtype);
- return -1;
+ break;
}
- return 0;
+
+ printf("kobj_reloc: unexpected/invalid relocation type %d @ %p symidx %u\n",
+ rtype, where, symidx);
+ return -1;
}
int