diff options
author | grehan <grehan@FreeBSD.org> | 2004-07-17 07:26:32 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2004-07-17 07:26:32 +0000 |
commit | a43623f685ffa723792441aeb94ce567b9207946 (patch) | |
tree | cd8ccb041f6a309922337ca3486010770546eb91 /sys/powerpc | |
parent | c25602666fe48a2c1137b0e0ffe2f194e9577612 (diff) | |
download | FreeBSD-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/powerpc')
-rw-r--r-- | sys/powerpc/powerpc/elf_machdep.c | 88 |
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); } |