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