diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk index 8278d47c582b..61872ff67c4a 100644 --- a/share/mk/bsd.cpu.mk +++ b/share/mk/bsd.cpu.mk @@ -203,11 +203,9 @@ LD += -EB .if ${MACHINE_ARCH} == "mips" . if defined(TARGET_BIG_ENDIAN) CFLAGS += -EB -LDFLAGS += -Wl,-EB LD += -EB . else CFLAGS += -EL -LDFLAGS += -Wl,-EL LD += -EL . endif CFLAGS += -msoft-float -G0 -mno-dsp -mabicalls diff --git a/sys/conf/files.mips b/sys/conf/files.mips index 6b2ece424c78..63d93ef9c5bf 100644 --- a/sys/conf/files.mips +++ b/sys/conf/files.mips @@ -89,6 +89,8 @@ libkern/umoddi3.c optional isa_mips32 #libkern/mips/strcmp.S standard #libkern/mips/strncmp.S standard +kern/link_elf_obj.c standard + dev/cfe/cfe_api.c optional cfe dev/cfe/cfe_console.c optional cfe_console dev/cfe/cfe_env.c optional cfe_env diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 1c788a36b953..6d543e4981ac 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -128,6 +128,10 @@ CFLAGS+= -fno-omit-frame-pointer CFLAGS+= -mlongcall -fno-omit-frame-pointer .endif +.if ${MACHINE_ARCH} == "mips" +CFLAGS+= -G0 -fno-pic -mno-abicalls -mlong-calls +.endif + .if defined(FIRMWS) .if !exists(@) ${KMOD:S/$/.c/}: @ @@ -174,7 +178,7 @@ ${PROG}.symbols: ${FULLPROG} ${OBJCOPY} --only-keep-debug ${FULLPROG} ${.TARGET} .endif -.if ${MACHINE_ARCH} != amd64 +.if ${MACHINE_ARCH} != amd64 && ${MACHINE_ARCH} != mips ${FULLPROG}: ${KMOD}.kld ${LD} -Bshareable ${LDFLAGS} -o ${.TARGET} ${KMOD}.kld .if !defined(DEBUG_FLAGS) @@ -187,7 +191,7 @@ EXPORT_SYMS?= NO CLEANFILES+= export_syms .endif -.if ${MACHINE_ARCH} != amd64 +.if ${MACHINE_ARCH} != amd64 && ${MACHINE_ARCH} != mips ${KMOD}.kld: ${OBJS} .else ${FULLPROG}: ${OBJS} @@ -206,7 +210,8 @@ ${FULLPROG}: ${OBJS} export_syms | xargs -J% ${OBJCOPY} % ${.TARGET} .endif .endif -.if !defined(DEBUG_FLAGS) && ${MACHINE_ARCH} == amd64 +.if !defined(DEBUG_FLAGS) && \ + (${MACHINE_ARCH} == amd64 || ${MACHINE_ARCH} == mips) ${OBJCOPY} --strip-debug ${.TARGET} .endif diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 68c60d8d62db..a337fd00c620 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -853,8 +853,8 @@ link_elf_load_file(linker_class_t cls, const char *filename, panic("lost relatab"); if (mapbase != (vm_offset_t)ef->address + mapsize) panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n", - mapbase, ef->address, mapsize, - (vm_offset_t)ef->address + mapsize); + (u_long)mapbase, ef->address, (u_long)mapsize, + (u_long)(vm_offset_t)ef->address + mapsize); /* Local intra-module relocations */ link_elf_reloc_local(lf); diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c index 54c31e523963..90e3dacade65 100644 --- a/sys/mips/mips/elf_machdep.c +++ b/sys/mips/mips/elf_machdep.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #ifdef __mips_n64 struct sysentvec elf64_freebsd_sysvec = { @@ -163,7 +164,12 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, Elf_Addr addend = (Elf_Addr)0; Elf_Word rtype = (Elf_Word)0, symidx; const Elf_Rel *rel; - const Elf_Rela *rela; + + /* + * Stash R_MIPS_HI16 info so we can use it when processing R_MIPS_LO16 + */ + static Elf_Addr ahl; + static Elf_Addr *where_hi16; switch (type) { case ELF_RELOC_REL: @@ -173,108 +179,63 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; - case ELF_RELOC_RELA: - rela = (const Elf_Rela *)data; - where = (Elf_Addr *) (relocbase + rela->r_offset); - addend = rela->r_addend; - rtype = ELF_R_TYPE(rela->r_info); - symidx = ELF_R_SYM(rela->r_info); - break; default: panic("unknown reloc type %d\n", type); } - if (local) { -#if 0 /* TBD */ - if (rtype == R_386_RELATIVE) { /* A + B */ - addr = elf_relocaddr(lf, relocbase + addend); - if (*where != addr) - *where = addr; - } - return (0); -#endif - } - switch (rtype) { + case R_MIPS_NONE: /* none */ + break; - case R_MIPS_NONE: /* none */ - break; - - case R_MIPS_16: /* S + sign-extend(A) */ - /* - * There shouldn't be R_MIPS_16 relocs in kernel objects. - */ - printf("kldload: unexpected R_MIPS_16 relocation\n"); - return -1; - break; - - case R_MIPS_32: /* S + A - P */ - addr = lookup(lf, symidx, 1); - if (addr == 0) - return -1; - addr += addend; - if (*where != addr) - *where = addr; - break; - - case R_MIPS_REL32: /* A - EA + S */ - /* - * There shouldn't be R_MIPS_REL32 relocs in kernel objects? - */ - printf("kldload: unexpected R_MIPS_REL32 relocation\n"); - return -1; - break; - - case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */ - break; - - case R_MIPS_HI16: - /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */ - /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */ - break; - - case R_MIPS_LO16: - /* extern/local: AHL + S */ - /* _gp_disp: AHL + GP - P + 4 */ - break; - - case R_MIPS_GPREL16: - /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */ - /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */ - break; - - case R_MIPS_LITERAL: /* sign-extend(A) + L */ - break; - - case R_MIPS_GOT16: /* external: G */ - /* local: tbd */ - break; - - case R_MIPS_PC16: /* sign-extend(A) + S - P */ - break; - - case R_MIPS_CALL16: /* G */ - break; - - case R_MIPS_GPREL32: /* A + S + GP0 - GP */ - break; - - case R_MIPS_GOTHI16: /* (G - (short)G) >> 16 + A */ - break; - - case R_MIPS_GOTLO16: /* G & 0xffff */ - break; - - case R_MIPS_CALLHI16: /* (G - (short)G) >> 16 + A */ - break; - - case R_MIPS_CALLLO16: /* G & 0xffff */ - break; - - default: - printf("kldload: unexpected relocation type %d\n", - rtype); + case R_MIPS_32: /* S + A */ + addr = lookup(lf, symidx, 1); + if (addr == 0) return (-1); + addr += addend; + if (*where != addr) + *where = addr; + break; + + case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */ + addr = lookup(lf, symidx, 1); + if (addr == 0) + return (-1); + + addend &= 0x03ffffff; + addend <<= 2; + + addr += ((Elf_Addr)where & 0xf0000000) | addend; + addr >>= 2; + + *where &= ~0x03ffffff; + *where |= addr & 0x03ffffff; + break; + + case R_MIPS_HI16: /* ((AHL + S) - ((short)(AHL + S)) >> 16 */ + ahl = addend << 16; + where_hi16 = where; + break; + + case R_MIPS_LO16: /* AHL + S */ + ahl += (int16_t)addend; + addr = lookup(lf, symidx, 1); + if (addr == 0) + return (-1); + + addend &= 0xffff0000; + addend |= (uint16_t)(ahl + addr); + *where = addend; + + addend = *where_hi16; + addend &= 0xffff0000; + addend |= ((ahl + addr) - (int16_t)(ahl + addr)) >> 16; + *where_hi16 = addend; + break; + + default: + printf("kldload: unexpected relocation type %d\n", + rtype); + return (-1); } return(0); } @@ -299,6 +260,11 @@ int elf_cpu_load_file(linker_file_t lf __unused) { + /* + * Sync the I and D caches to make sure our relocations are visible. + */ + mips_icache_sync_all(); + return (0); }