summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2004-07-17 07:26:32 +0000
committergrehan <grehan@FreeBSD.org>2004-07-17 07:26:32 +0000
commita43623f685ffa723792441aeb94ce567b9207946 (patch)
treecd8ccb041f6a309922337ca3486010770546eb91 /sys
parentc25602666fe48a2c1137b0e0ffe2f194e9577612 (diff)
downloadFreeBSD-src-a43623f685ffa723792441aeb94ce567b9207946.zip
FreeBSD-src-a43623f685ffa723792441aeb94ce567b9207946.tar.gz
Resurrect kld support. Support ADDR16_HA/LA relocations, and sync
the icache on module load. Requires "-mlongcall" support, in gcc >= 3.3 but needs a bugfix to support gcc arith builtins.
Diffstat (limited to 'sys')
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c88
1 files changed, 45 insertions, 43 deletions
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
index 21c9ca3..f8e9405 100644
--- a/sys/powerpc/powerpc/elf_machdep.c
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -44,6 +44,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
+#include <machine/cpu.h>
#include <machine/elf.h>
#include <machine/md_var.h>
@@ -110,23 +111,20 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
int type, int local, elf_lookup_fn lookup)
{
Elf_Addr *where;
+ Elf_Half *hwhere;
Elf_Addr addr;
Elf_Addr addend;
Elf_Word rtype, symidx;
- const Elf_Rel *rel;
const Elf_Rela *rela;
switch (type) {
case ELF_RELOC_REL:
- rel = (const Elf_Rel *)data;
- where = (Elf_Addr *) (relocbase + rel->r_offset);
- addend = *where;
- rtype = ELF_R_TYPE(rel->r_info);
- symidx = ELF_R_SYM(rel->r_info);
+ panic("PPC only supports RELA relocations");
break;
case ELF_RELOC_RELA:
rela = (const Elf_Rela *)data;
where = (Elf_Addr *) (relocbase + rela->r_offset);
+ hwhere = (Elf_Half *) (relocbase + rela->r_offset);
addend = rela->r_addend;
rtype = ELF_R_TYPE(rela->r_info);
symidx = ELF_R_SYM(rela->r_info);
@@ -137,45 +135,48 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
switch (rtype) {
- case R_PPC_NONE:
- break;
-
- case R_PPC_GLOB_DAT:
- addr = lookup(lf, symidx, 1);
- if (addr == 0)
- return -1;
- addr += addend;
- if (*where != addr)
- *where = addr;
- break;
-
- case R_PPC_JMP_SLOT:
- /* No point in lazy binding for kernel modules. */
- addr = lookup(lf, symidx, 1);
+ case R_PPC_NONE:
+ break;
+
+ case R_PPC_ADDR32: /* word32 S + A */
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
+ return -1;
+ addr += addend;
+ *where = addr;
+ break;
+
+ case R_PPC_ADDR16_LO: /* #lo(S) */
+ if (addend != 0) {
+ addr = relocbase + addend;
+ } else {
+ addr = lookup(lf, symidx, 1);
if (addr == 0)
return -1;
- if (*where != addr)
- *where = addr;
- break;
-
- case R_PPC_RELATIVE:
- addr = relocbase + addend + *where;
- if (*where != addr)
- *where = addr;
- break;
-
- case R_PPC_COPY:
- /*
- * There shouldn't be copy relocations in kernel
- * objects.
- */
- printf("kldload: unexpected R_COPY relocation\n");
- return -1;
-
- default:
- printf("kldload: unexpected relocation type %d\n",
- (int) rtype);
- return -1;
+ }
+ *hwhere = addr & 0xffff;
+ break;
+
+ case R_PPC_ADDR16_HA: /* #ha(S) */
+ if (addend != 0) {
+ addr = relocbase + addend;
+ } else {
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
+ return -1;
+ }
+ *hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0))
+ & 0xffff;
+ break;
+
+ case R_PPC_RELATIVE: /* word32 B + A */
+ *where = relocbase + addend;
+ break;
+
+ default:
+ printf("kldload: unexpected relocation type %d\n",
+ (int) rtype);
+ return -1;
}
return(0);
}
@@ -200,6 +201,7 @@ int
elf_cpu_load_file(linker_file_t lf __unused)
{
+ __syncicache(lf->address, lf->size);
return (0);
}
OpenPOWER on IntegriCloud