summaryrefslogtreecommitdiffstats
path: root/sys/alpha
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-10-16 03:55:01 +0000
committerpeter <peter@FreeBSD.org>1998-10-16 03:55:01 +0000
commit464de37ce6099f409aa233200a94ac38216aa211 (patch)
tree59ed738c6bca93117593ea63241912064597c130 /sys/alpha
parentad0030e392049cd4f887968f40988dd6cf5e5ee0 (diff)
downloadFreeBSD-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.c74
-rw-r--r--sys/alpha/linux/linux_sysvec.c53
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);
OpenPOWER on IntegriCloud