diff options
author | peter <peter@FreeBSD.org> | 1998-10-16 03:55:01 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-10-16 03:55:01 +0000 |
commit | 464de37ce6099f409aa233200a94ac38216aa211 (patch) | |
tree | 59ed738c6bca93117593ea63241912064597c130 /sys/alpha | |
parent | ad0030e392049cd4f887968f40988dd6cf5e5ee0 (diff) | |
download | FreeBSD-src-464de37ce6099f409aa233200a94ac38216aa211.zip FreeBSD-src-464de37ce6099f409aa233200a94ac38216aa211.tar.gz |
*gulp*. Jordan specifically OK'ed this..
This is the bulk of the support for doing kld modules. Two linker_sets
were replaced by SYSINIT()'s. VFS's and exec handlers are self registered.
kld is now a superset of lkm. I have converted most of them, they will
follow as a seperate commit as samples.
This all still works as a static a.out kernel using LKM's.
Diffstat (limited to 'sys/alpha')
-rw-r--r-- | sys/alpha/alpha/elf_machdep.c | 74 | ||||
-rw-r--r-- | sys/alpha/linux/linux_sysvec.c | 53 |
2 files changed, 77 insertions, 50 deletions
diff --git a/sys/alpha/alpha/elf_machdep.c b/sys/alpha/alpha/elf_machdep.c index 1e7c86d..847ab2a 100644 --- a/sys/alpha/alpha/elf_machdep.c +++ b/sys/alpha/alpha/elf_machdep.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id$ + * $Id: elf_machdep.c,v 1.1 1998/09/11 08:47:02 dfr Exp $ */ #include <sys/param.h> @@ -38,73 +38,81 @@ /* Process one elf relocation with addend. */ int -elf_reloc(linker_file_t lf, const Elf_Rela *rela, const char *sym) +elf_reloc(linker_file_t lf, const void *data, int type, const char *sym) { Elf_Addr relocbase = (Elf_Addr) lf->address; - Elf_Addr *where = (Elf_Addr *) (relocbase + rela->r_offset); + Elf_Addr *where; + Elf_Addr addr, tmp_value; + Elf_Addr addend; + Elf_Word rtype; + const Elf_Rel *rel; + const Elf_Rela *rela; - switch (ELF_R_TYPE(rela->r_info)) { + switch (type) { + case ELF_RELOC_REL: + rel = (Elf_Rel *)data; + where = (Elf_Addr *) (relocbase + rel->r_offset); + addend = *where; + rtype = ELF_R_TYPE(rel->r_info); + break; + case ELF_RELOC_RELA: + rela = (Elf_Rela *)data; + where = (Elf_Addr *) (relocbase + rela->r_offset); + addend = rela->r_addend; + rtype = ELF_R_TYPE(rela->r_info); + break; + default: + panic("elf_reloc: unknown relocation mode %d\n", type); + } - case R_ALPHA_REFQUAD: { - Elf_Addr addr; - Elf_Addr tmp_value; + switch (rtype) { + case R_ALPHA_REFQUAD: addr = (Elf_Addr) linker_file_lookup_symbol(lf, sym, 1); if (addr == NULL) return -1; + addr += addend; + if (*where != addr) + *where = addr; + break; - tmp_value = addr + *where + rela->r_addend; - if (*where != tmp_value) - *where = tmp_value; - } - break; - - case R_ALPHA_GLOB_DAT: { - Elf_Addr addr; - + case R_ALPHA_GLOB_DAT: addr = (Elf_Addr) linker_file_lookup_symbol(lf, sym, 1); if (addr == NULL) return -1; - if (*where != addr) *where = addr; - } - break; + break; - case R_ALPHA_JMP_SLOT: { + case R_ALPHA_JMP_SLOT: /* No point in lazy binding for kernel modules. */ - Elf_Addr addr; - addr = (Elf_Addr) linker_file_lookup_symbol(lf, sym, 1); if (addr == NULL) return -1; - if (*where != addr) *where = addr; - } - break; + break; - case R_ALPHA_RELATIVE: { - *where += relocbase; - } - break; + case R_ALPHA_RELATIVE: + addr = relocbase + addend; + if (*where != addr) + *where = addr; + break; - case R_ALPHA_COPY: { + case R_ALPHA_COPY: /* * There shouldn't be copy relocations in kernel * objects. */ printf("kldload: unexpected R_COPY relocation\n"); return -1; - } - break; default: printf("kldload: unexpected relocation type %d\n", - ELF_R_TYPE(rela->r_info)); + rtype); return -1; } return(0); diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c index 5600111..cf8c021 100644 --- a/sys/alpha/linux/linux_sysvec.c +++ b/sys/alpha/linux/linux_sysvec.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_sysvec.c,v 1.35 1998/10/05 16:37:36 jfieber Exp $ + * $Id: linux_sysvec.c,v 1.36 1998/10/11 21:08:02 alex Exp $ */ /* XXX we use functions that might not exist. */ @@ -52,6 +52,7 @@ #include <vm/vm_extern.h> #include <sys/exec.h> #include <sys/kernel.h> +#include <sys/module.h> #include <machine/cpu.h> #include <i386/linux/linux.h> @@ -447,31 +448,49 @@ Elf32_Brandinfo *linux_brandlist[] = { NULL }; -#ifndef LKM /* * XXX: this is WRONG, it needs to be SI_SUB_EXEC, but this is just at the * "proof of concept" stage and will be fixed shortly */ -static void linux_elf_init __P((void *dummy)); +static int linux_elf_modevent __P((module_t mod, modeventtype_t type, void *data)); -static void -linux_elf_init(dummy) - void *dummy; +static int +linux_elf_modevent(module_t mod, modeventtype_t type, void *data) { Elf32_Brandinfo **brandinfo; int error; error = 0; - for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) - if (elf_insert_brand_entry(*brandinfo) < 0) - error = 1; - - if (error) - printf("cannot insert Linux elf brand handler\n"); - else if (bootverbose) - printf("Linux-ELF exec handler installed\n"); + switch(type) { + case MOD_LOAD: + for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; + ++brandinfo) + if (elf_insert_brand_entry(*brandinfo) < 0) + error = EINVAL; + if (error) + printf("cannot insert Linux elf brand handler\n"); + else if (bootverbose) + printf("Linux-ELF exec handler installed\n"); + break; + case MOD_UNLOAD: + for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; + ++brandinfo) + if (elf_remove_brand_entry(*brandinfo) < 0) + error = EINVAL; + if (error) + printf("Could not deinstall ELF interpreter entry\n"); + else if (bootverbose) + printf("Linux-elf exec handler removed\n"); + break; + default: + break; + } + return error; } - -SYSINIT(linuxelf, SI_SUB_VFS, SI_ORDER_ANY, linux_elf_init, NULL); -#endif +static moduledata_t linux_elf_mod = { + "linuxelf", + linux_elf_modevent, + 0 +}; +DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); |