This is the kernel linker. To use it, you will first need to apply

the patches in freefall:/home/dfr/ld.diffs to your ld sources and set
BINFORMAT to aoutkld when linking the kernel.

Library changes and userland utilities will appear in a later commit.
This commit is contained in:
Doug Rabson 1997-05-07 16:05:47 +00:00
parent 5bd588ccb0
commit cea6c86c11
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=25537
15 changed files with 1885 additions and 5 deletions

View File

@ -1,7 +1,7 @@
# Makefile.i386 -- with config changes.
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
# $Id: Makefile.i386,v 1.94 1997/04/22 06:55:21 jdp Exp $
# $Id: Makefile.i386,v 1.95 1997/04/27 20:01:47 peter Exp $
#
# Makefile for FreeBSD
#
@ -17,6 +17,7 @@
#
BINFORMAT?= aout
#BINFORMAT?= aoutkld
#BINFORMAT?= elf
.if exists(./@/.)
@ -70,6 +71,12 @@ SYSTEM_LD_TAIL= @echo rearranging symbols; \
symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \
size $@; chmod 755 $@
.endif
.if ${BINFORMAT} == aoutkld
SYSTEM_LD= @${LD} -Bforcedynamic -Z -T ${LOAD_ADDRESS} -o $@ -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @echo rearranging symbols; \
symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \
size $@; chmod 755 $@
.endif
.if ${BINFORMAT} == elf
SYSTEM_LD= @${LD} -Bstatic -Ttext ${LOAD_ADDRESS} -e btext -o $@ -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @size $@; chmod 755 $@

View File

@ -1,7 +1,7 @@
# Makefile.i386 -- with config changes.
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
# $Id: Makefile.i386,v 1.94 1997/04/22 06:55:21 jdp Exp $
# $Id: Makefile.i386,v 1.95 1997/04/27 20:01:47 peter Exp $
#
# Makefile for FreeBSD
#
@ -17,6 +17,7 @@
#
BINFORMAT?= aout
#BINFORMAT?= aoutkld
#BINFORMAT?= elf
.if exists(./@/.)
@ -70,6 +71,12 @@ SYSTEM_LD_TAIL= @echo rearranging symbols; \
symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \
size $@; chmod 755 $@
.endif
.if ${BINFORMAT} == aoutkld
SYSTEM_LD= @${LD} -Bforcedynamic -Z -T ${LOAD_ADDRESS} -o $@ -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @echo rearranging symbols; \
symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \
size $@; chmod 755 $@
.endif
.if ${BINFORMAT} == elf
SYSTEM_LD= @${LD} -Bstatic -Ttext ${LOAD_ADDRESS} -e btext -o $@ -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @size $@; chmod 755 $@

View File

@ -48,6 +48,9 @@ kern/init_main.c standard
kern/init_smp.c optional smp
kern/init_sysent.c standard
kern/init_sysvec.c standard
kern/kern_module.c standard
kern/kern_linker.c standard
kern/link_aout.c standard
kern/kern_acct.c standard
kern/kern_clock.c standard
kern/kern_conf.c standard

View File

@ -1,7 +1,7 @@
# Makefile.i386 -- with config changes.
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
# $Id: Makefile.i386,v 1.94 1997/04/22 06:55:21 jdp Exp $
# $Id: Makefile.i386,v 1.95 1997/04/27 20:01:47 peter Exp $
#
# Makefile for FreeBSD
#
@ -17,6 +17,7 @@
#
BINFORMAT?= aout
#BINFORMAT?= aoutkld
#BINFORMAT?= elf
.if exists(./@/.)
@ -70,6 +71,12 @@ SYSTEM_LD_TAIL= @echo rearranging symbols; \
symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \
size $@; chmod 755 $@
.endif
.if ${BINFORMAT} == aoutkld
SYSTEM_LD= @${LD} -Bforcedynamic -Z -T ${LOAD_ADDRESS} -o $@ -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @echo rearranging symbols; \
symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \
size $@; chmod 755 $@
.endif
.if ${BINFORMAT} == elf
SYSTEM_LD= @${LD} -Bstatic -Ttext ${LOAD_ADDRESS} -e btext -o $@ -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @size $@; chmod 755 $@

View File

@ -287,4 +287,59 @@ struct sysent sysent[] = {
{ 0, (sy_call_t *)nosys }, /* 252 = poll */
{ 0, (sy_call_t *)issetugid }, /* 253 = issetugid */
{ 3, (sy_call_t *)lchown }, /* 254 = lchown */
{ 0, (sy_call_t *)nosys }, /* 255 = nosys */
{ 0, (sy_call_t *)nosys }, /* 256 = nosys */
{ 0, (sy_call_t *)nosys }, /* 257 = nosys */
{ 0, (sy_call_t *)nosys }, /* 258 = nosys */
{ 0, (sy_call_t *)nosys }, /* 259 = nosys */
{ 0, (sy_call_t *)nosys }, /* 260 = nosys */
{ 0, (sy_call_t *)nosys }, /* 261 = nosys */
{ 0, (sy_call_t *)nosys }, /* 262 = nosys */
{ 0, (sy_call_t *)nosys }, /* 263 = nosys */
{ 0, (sy_call_t *)nosys }, /* 264 = nosys */
{ 0, (sy_call_t *)nosys }, /* 265 = nosys */
{ 0, (sy_call_t *)nosys }, /* 266 = nosys */
{ 0, (sy_call_t *)nosys }, /* 267 = nosys */
{ 0, (sy_call_t *)nosys }, /* 268 = nosys */
{ 0, (sy_call_t *)nosys }, /* 269 = nosys */
{ 0, (sy_call_t *)nosys }, /* 270 = nosys */
{ 0, (sy_call_t *)nosys }, /* 271 = nosys */
{ 0, (sy_call_t *)nosys }, /* 272 = nosys */
{ 0, (sy_call_t *)nosys }, /* 273 = nosys */
{ 0, (sy_call_t *)nosys }, /* 274 = nosys */
{ 0, (sy_call_t *)nosys }, /* 275 = nosys */
{ 0, (sy_call_t *)nosys }, /* 276 = nosys */
{ 0, (sy_call_t *)nosys }, /* 277 = nosys */
{ 0, (sy_call_t *)nosys }, /* 278 = nosys */
{ 0, (sy_call_t *)nosys }, /* 279 = nosys */
{ 0, (sy_call_t *)nosys }, /* 280 = nosys */
{ 0, (sy_call_t *)nosys }, /* 281 = nosys */
{ 0, (sy_call_t *)nosys }, /* 282 = nosys */
{ 0, (sy_call_t *)nosys }, /* 283 = nosys */
{ 0, (sy_call_t *)nosys }, /* 284 = nosys */
{ 0, (sy_call_t *)nosys }, /* 285 = nosys */
{ 0, (sy_call_t *)nosys }, /* 286 = nosys */
{ 0, (sy_call_t *)nosys }, /* 287 = nosys */
{ 0, (sy_call_t *)nosys }, /* 288 = nosys */
{ 0, (sy_call_t *)nosys }, /* 289 = nosys */
{ 0, (sy_call_t *)nosys }, /* 290 = nosys */
{ 0, (sy_call_t *)nosys }, /* 291 = nosys */
{ 0, (sy_call_t *)nosys }, /* 292 = nosys */
{ 0, (sy_call_t *)nosys }, /* 293 = nosys */
{ 0, (sy_call_t *)nosys }, /* 294 = nosys */
{ 0, (sy_call_t *)nosys }, /* 295 = nosys */
{ 0, (sy_call_t *)nosys }, /* 296 = nosys */
{ 0, (sy_call_t *)nosys }, /* 297 = nosys */
{ 0, (sy_call_t *)nosys }, /* 298 = nosys */
{ 0, (sy_call_t *)nosys }, /* 299 = nosys */
{ 1, (sy_call_t *)modnext }, /* 300 = modnext */
{ 2, (sy_call_t *)modstat }, /* 301 = modstat */
{ 1, (sy_call_t *)modfnext }, /* 302 = modfnext */
{ 1, (sy_call_t *)modfind }, /* 303 = modfind */
{ 1, (sy_call_t *)kldload }, /* 304 = kldload */
{ 1, (sy_call_t *)kldunload }, /* 305 = kldunload */
{ 1, (sy_call_t *)kldfind }, /* 306 = kldfind */
{ 1, (sy_call_t *)kldnext }, /* 307 = kldnext */
{ 2, (sy_call_t *)kldstat }, /* 308 = kldstat */
{ 1, (sy_call_t *)kldfirstmod }, /* 309 = kldfirstmod */
};

562
sys/kern/kern_linker.c Normal file
View File

@ -0,0 +1,562 @@
/*-
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (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$
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/sysproto.h>
#include <sys/sysent.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <machine/cpu.h>
#include <sys/module.h>
#include <sys/linker.h>
static struct lock lock; /* lock for the file list */
static linker_class_list_t classes;
static linker_file_list_t files;
static int next_file_id = 1;
static void
linker_init(void* arg)
{
lockinit(&lock, PVM, "klink", 0, 0);
TAILQ_INIT(&classes);
TAILQ_INIT(&files);
}
SYSINIT(linker, SI_SUB_KMEM, SI_ORDER_SECOND, linker_init, 0);
int
linker_add_class(const char* desc, void* priv,
struct linker_class_ops* ops)
{
linker_class_t lc;
lc = malloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT);
if (!lc)
return ENOMEM;
lc->desc = desc;
lc->priv = priv;
lc->ops = ops;
TAILQ_INSERT_HEAD(&classes, lc, link);
return 0;
}
static void
linker_file_sysinit(linker_file_t lf)
{
struct linker_set* sysinits;
struct sysinit** sipp;
struct sysinit** xipp;
struct sysinit* save;
int rval[2]; /* SI_TYPE_KTHREAD support*/
linker_current_file = lf;
KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
lf->filename));
sysinits = (struct linker_set*)
linker_file_lookup_symbol(lf, "sysinit_set", 0);
if (!sysinits)
return;
/*
* Perform a bubble sort of the system initialization objects by
* their subsystem (primary key) and order (secondary key).
*
* Since some things care about execution order, this is the
* operation which ensures continued function.
*/
for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
for( xipp = sipp + 1; *xipp; xipp++) {
if( (*sipp)->subsystem < (*xipp)->subsystem ||
( (*sipp)->subsystem == (*xipp)->subsystem &&
(*sipp)->order < (*xipp)->order))
continue; /* skip*/
save = *sipp;
*sipp = *xipp;
*xipp = save;
}
}
/*
* Traverse the (now) ordered list of system initialization tasks.
* Perform each task, and continue on to the next task.
*
* The last item on the list is expected to be the scheduler,
* which will not return.
*/
for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
if( (*sipp)->subsystem == SI_SUB_DUMMY)
continue; /* skip dummy task(s)*/
switch( (*sipp)->type) {
case SI_TYPE_DEFAULT:
/* no special processing*/
(*((*sipp)->func))( (*sipp)->udata);
break;
case SI_TYPE_KTHREAD:
/* kernel thread*/
if (fork(&proc0, NULL, rval))
panic("fork kernel process");
cpu_set_fork_handler(pfind(rval[0]), (*sipp)->func, (*sipp)->udata);
break;
default:
panic( "linker_file_sysinit: unrecognized init type");
}
}
}
int
linker_load_file(const char* filename, linker_file_t* result)
{
linker_class_t lc;
linker_file_t lf;
int error = 0;
lf = linker_find_file_by_name(filename);
if (lf) {
KLD_DPF(FILE, ("linker_load_file: file %s is already loaded, incrementing refs\n", filename));
*result = lf;
lf->refs++;
goto out;
}
lf = NULL;
for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) {
KLD_DPF(FILE, ("linker_load_file: trying to load %s as %s\n",
filename, lc->desc));
if (error = lc->ops->load_file(filename, &lf))
goto out;
if (lf) {
linker_file_sysinit(lf);
*result = lf;
goto out;
}
}
error = ENOEXEC; /* format not recognised */
out:
return error;
}
linker_file_t
linker_find_file_by_name(const char* filename)
{
linker_file_t lf = 0;
lockmgr(&lock, LK_SHARED, 0, curproc);
for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link))
if (!strcmp(lf->filename, filename))
break;
lockmgr(&lock, LK_RELEASE, 0, curproc);
return lf;
}
linker_file_t
linker_find_file_by_id(int fileid)
{
linker_file_t lf = 0;
lockmgr(&lock, LK_SHARED, 0, curproc);
for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link))
if (lf->id == fileid)
break;
lockmgr(&lock, LK_RELEASE, 0, curproc);
return lf;
}
linker_file_t
linker_make_file(const char* filename, void* priv, struct linker_file_ops* ops)
{
linker_file_t lf = 0;
int namelen;
KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc);
namelen = strlen(filename) + 1;
lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK);
if (!lf)
goto out;
lf->refs = 1;
lf->userrefs = 0;
lf->filename = (char*) (lf + 1);
strcpy(lf->filename, filename);
lf->id = next_file_id++;
lf->ndeps = 0;
lf->deps = NULL;
STAILQ_INIT(&lf->common);
TAILQ_INIT(&lf->modules);
lf->priv = priv;
lf->ops = ops;
TAILQ_INSERT_TAIL(&files, lf, link);
out:
lockmgr(&lock, LK_RELEASE, 0, curproc);
return lf;
}
int
linker_file_unload(linker_file_t file)
{
module_t mod, next;
struct common_symbol* cp;
int error = 0;
int i;
KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", lf->refs));
lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc);
if (file->refs == 1) {
KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n"));
/*
* Inform any modules associated with this file.
*/
for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
next = module_getfnext(mod);
/*
* Give the module a chance to veto the unload.
*/
if (error = module_unload(mod)) {
KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n",
mod));
lockmgr(&lock, LK_RELEASE, 0, curproc);
goto out;
}
module_release(mod);
}
}
file->refs--;
if (file->refs > 0) {
lockmgr(&lock, LK_RELEASE, 0, curproc);
goto out;
}
TAILQ_REMOVE(&files, file, link);
lockmgr(&lock, LK_RELEASE, 0, curproc);
for (i = 0; i < file->ndeps; i++)
linker_file_unload(file->deps[i]);
free(file->deps, M_LINKER);
for (cp = STAILQ_FIRST(&file->common); cp;
cp = STAILQ_FIRST(&file->common)) {
STAILQ_REMOVE(&file->common, cp, common_symbol, link);
free(cp, M_LINKER);
}
file->ops->unload(file);
free(file, M_LINKER);
out:
return error;
}
int
linker_file_add_dependancy(linker_file_t file, linker_file_t dep)
{
linker_file_t* newdeps;
newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*),
M_LINKER, M_WAITOK);
if (newdeps == NULL)
return ENOMEM;
if (file->deps) {
bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*));
free(file->deps, M_LINKER);
}
file->deps = newdeps;
file->deps[file->ndeps] = dep;
file->ndeps++;
return 0;
}
caddr_t
linker_file_lookup_symbol(linker_file_t file, const char* name, int deps)
{
caddr_t address;
size_t size;
size_t common_size = 0;
int i;
KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d",
file, name, deps));
if (file->ops->lookup_symbol(file, name, &address, &size) == 0)
if (address == 0)
/*
* For commons, first look them up in the dependancies and
* only allocate space if not found there.
*/
common_size = size;
else
return address;
if (deps)
for (i = 0; i < file->ndeps; i++) {
address = linker_file_lookup_symbol(file->deps[i], name, 0);
if (address)
return address;
}
if (common_size > 0) {
/*
* This is a common symbol which was not found in the
* dependancies. We maintain a simple common symbol table in
* the file object.
*/
struct common_symbol* cp;
for (cp = STAILQ_FIRST(&file->common); cp;
cp = STAILQ_NEXT(cp, link))
if (!strcmp(cp->name, name))
return cp->address;
/*
* Round the symbol size up to align.
*/
common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
cp = malloc(sizeof(struct common_symbol)
+ common_size
+ strlen(name) + 1,
M_LINKER, M_WAITOK);
if (!cp)
return 0;
cp->address = (caddr_t) (cp + 1);
cp->name = cp->address + common_size;
strcpy(cp->name, name);
bzero(cp->address, common_size);
STAILQ_INSERT_TAIL(&file->common, cp, link);
return cp->address;
}
return 0;
}
/*
* Syscalls.
*/
int
kldload(struct proc* p, struct kldload_args* uap, int* retval)
{
char* filename = NULL;
linker_file_t lf;
int error = 0;
*retval = -1;
if (securelevel > 0)
return EPERM;
if (error = suser(p->p_ucred, &p->p_acflag))
return error;
filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL))
goto out;
if (error = linker_load_file(uap->file, &lf))
goto out;
lf->userrefs++;
*retval = lf->id;
out:
if (filename)
free(filename, M_TEMP);
return error;
}
int
kldunload(struct proc* p, struct kldunload_args* uap, int* retval)
{
linker_file_t lf;
int error = 0;
if (securelevel > 0)
return EPERM;
if (error = suser(p->p_ucred, &p->p_acflag))
return error;
lf = linker_find_file_by_id(SCARG(uap, fileid));
if (lf) {
KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
if (lf->userrefs == 0) {
printf("linkerunload: attempt to unload file which was not loaded by user\n");
error = EBUSY;
goto out;
}
lf->userrefs--;
error = linker_file_unload(lf);
} else
error = ENOENT;
out:
return error;
}
int
kldfind(struct proc* p, struct kldfind_args* uap, int* retval)
{
char* filename = NULL;
linker_file_t lf;
int error = 0;
*retval = -1;
filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL))
goto out;
lf = linker_find_file_by_name(filename);
if (lf)
*retval = lf->id;
else
error = ENOENT;
out:
if (filename)
free(filename, M_TEMP);
return error;
}
int
kldnext(struct proc* p, struct kldnext_args* uap, int* retval)
{
linker_file_t lf;
int error = 0;
if (SCARG(uap, fileid) == 0) {
if (TAILQ_FIRST(&files))
*retval = TAILQ_FIRST(&files)->id;
else
*retval = 0;
return 0;
}
lf = linker_find_file_by_id(SCARG(uap, fileid));
if (lf) {
if (TAILQ_NEXT(lf, link))
*retval = TAILQ_NEXT(lf, link)->id;
else
*retval = 0;
} else
error = ENOENT;
return error;
}
int
kldstat(struct proc* p, struct kldstat_args* uap, int* retval)
{
linker_file_t lf;
int error = 0;
int version;
struct kld_file_stat* stat;
int namelen;
lf = linker_find_file_by_id(SCARG(uap, fileid));
if (!lf) {
error = ENOENT;
goto out;
}
stat = SCARG(uap, stat);
/*
* Check the version of the user's structure.
*/
if (error = copyin(&stat->version, &version, sizeof(version)))
goto out;
if (version != sizeof(struct kld_file_stat)) {
error = EINVAL;
goto out;
}
namelen = strlen(lf->filename) + 1;
if (namelen > MAXPATHLEN)
namelen = MAXPATHLEN;
if (error = copyout(lf->filename, &stat->name[0], namelen))
goto out;
if (error = copyout(&lf->refs, &stat->refs, sizeof(int)))
goto out;
if (error = copyout(&lf->id, &stat->id, sizeof(int)))
goto out;
if (error = copyout(&lf->address, &stat->address, sizeof(caddr_t)))
goto out;
if (error = copyout(&lf->size, &stat->size, sizeof(size_t)))
goto out;
*retval = 0;
out:
return error;
}
int
kldfirstmod(struct proc* p, struct kldfirstmod_args* uap, int* retval)
{
linker_file_t lf;
int error = 0;
lf = linker_find_file_by_id(SCARG(uap, fileid));
if (lf) {
if (TAILQ_FIRST(&lf->modules))
*retval = module_getid(TAILQ_FIRST(&lf->modules));
else
*retval = 0;
} else
error = ENOENT;
return error;
}

304
sys/kern/kern_module.c Normal file
View File

@ -0,0 +1,304 @@
/*-
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (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$
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/sysproto.h>
#include <sys/sysent.h>
#include <sys/module.h>
#include <sys/linker.h>
#define M_MODULE M_TEMP /* XXX */
typedef TAILQ_HEAD(, module) modulelist_t;
struct module {
TAILQ_ENTRY(module) link; /* chain together all modules */
TAILQ_ENTRY(module) flink; /* all modules in a file */
struct linker_file* file; /* file which contains this module */
int refs; /* reference count */
int id; /* unique id number */
char *name; /* module name */
modeventhand_t handler; /* event handler */
void *arg; /* argument for handler */
};
#define MOD_EVENT(mod, type) (mod)->handler((mod), (type), (mod)->arg)
static modulelist_t modules;
static int nextid = 1;
static void module_shutdown(int, void*);
static void
module_init(void* arg)
{
TAILQ_INIT(&modules);
at_shutdown(module_shutdown, 0, SHUTDOWN_POST_SYNC);
}
SYSINIT(module, SI_SUB_KMEM, SI_ORDER_ANY, module_init, 0);
static void
module_shutdown(int arg1, void* arg2)
{
module_t mod;
int error;
for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link))
MOD_EVENT(mod, MOD_SHUTDOWN);
}
void
module_register_static(void *arg)
{
moduledata_t* data = (moduledata_t*) arg;
int error;
if (error = module_register(data->name, data->evhand, data->priv))
printf("module_register_static: module_register(%s, %x, %x) returned %d",
data->name, data->evhand, data->priv, error);
}
int
module_register(const char* name, modeventhand_t handler, void* arg)
{
size_t namelen;
module_t newmod;
int error;
namelen = strlen(name) + 1;
newmod = (module_t) malloc(sizeof(struct module) + namelen,
M_MODULE, M_WAITOK);
if (newmod == 0)
return ENOMEM;
newmod->refs = 1;
newmod->id = nextid++;
newmod->name = (char *) (newmod + 1);
strcpy(newmod->name, name);
newmod->handler = handler;
newmod->arg = arg;
TAILQ_INSERT_TAIL(&modules, newmod, link);
if (linker_current_file) {
TAILQ_INSERT_TAIL(&linker_current_file->modules, newmod, flink);
newmod->file = linker_current_file;
} else
newmod->file = 0;
if (error = MOD_EVENT(newmod, MOD_LOAD)) {
module_release(newmod);
return error;
}
return 0;
}
void
module_reference(module_t mod)
{
MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs));
mod->refs++;
}
void
module_release(module_t mod)
{
if (mod->refs <= 0)
panic("module_release: bad reference count");
MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs));
mod->refs--;
if (mod->refs == 0) {
TAILQ_REMOVE(&modules, mod, link);
if (mod->file) {
TAILQ_REMOVE(&mod->file->modules, mod, flink);
}
free(mod, M_MODULE);
}
}
module_t
module_lookupbyname(const char* name)
{
module_t mod;
for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
if (!strcmp(mod->name, name))
return mod;
}
return 0;
}
module_t
module_lookupbyid(int modid)
{
module_t mod;
for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) {
if (mod->id == modid)
return mod;
}
return 0;
}
int
module_unload(module_t mod)
{
return MOD_EVENT(mod, MOD_UNLOAD);
}
int
module_getid(module_t mod)
{
return mod->id;
}
module_t
module_getfnext(module_t mod)
{
return TAILQ_NEXT(mod, flink);
}
/*
* Syscalls.
*/
int
modnext(struct proc* p, struct modnext_args* uap, int* retval)
{
module_t mod;
*retval = -1;
if (SCARG(uap, modid) == 0) {
mod = TAILQ_FIRST(&modules);
if (mod) {
*retval = mod->id;
return 0;
} else
return ENOENT;
}
mod = module_lookupbyid(SCARG(uap, modid));
if (!mod)
return ENOENT;
if (TAILQ_NEXT(mod, link))
*retval = TAILQ_NEXT(mod, link)->id;
else
*retval = 0;
return 0;
}
int
modfnext(struct proc* p, struct modfnext_args* uap, int* retval)
{
module_t mod;
*retval = -1;
mod = module_lookupbyid(SCARG(uap, modid));
if (!mod)
return ENOENT;
if (TAILQ_NEXT(mod, flink))
*retval = TAILQ_NEXT(mod, flink)->id;
else
*retval = 0;
return 0;
}
int
modstat(struct proc* p, struct modstat_args* uap, int* retval)
{
module_t mod;
int error = 0;
int namelen;
int version;
struct module_stat* stat;
mod = module_lookupbyid(SCARG(uap, modid));
if (!mod)
return ENOENT;
stat = SCARG(uap, stat);
/*
* Check the version of the user's structure.
*/
if (error = copyin(&stat->version, &version, sizeof(version)))
goto out;
if (version != sizeof(struct module_stat)) {
error = EINVAL;
goto out;
}
namelen = strlen(mod->name) + 1;
if (namelen > MAXMODNAME)
namelen = MAXMODNAME;
if (error = copyout(mod->name, &stat->name[0], namelen))
goto out;
if (error = copyout(&mod->refs, &stat->refs, sizeof(int)))
goto out;
if (error = copyout(&mod->id, &stat->id, sizeof(int)))
goto out;
*retval = 0;
out:
return error;
}
int
modfind(struct proc* p, struct modfind_args* uap, int* retval)
{
int error = 0;
char name[MAXMODNAME];
module_t mod;
if (error = copyinstr(SCARG(uap, name), name, sizeof name, 0))
goto out;
mod = module_lookupbyname(name);
if (!mod)
error = ENOENT;
else
*retval = mod->id;
out:
return error;
}

448
sys/kern/link_aout.c Normal file
View File

@ -0,0 +1,448 @@
/*-
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (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$
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/sysproto.h>
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include <sys/linker.h>
#include <a.out.h>
#include <link.h>
#include <machine/reloc.h>
#include <sys/imgact_aout.h>
static int link_aout_load_file(const char*, linker_file_t*);
static int link_aout_lookup_symbol(linker_file_t, const char*,
caddr_t*, size_t*);
static void link_aout_unload(linker_file_t);
static struct linker_class_ops link_aout_class_ops = {
link_aout_load_file,
};
static struct linker_file_ops link_aout_file_ops = {
link_aout_lookup_symbol,
link_aout_unload,
};
typedef struct aout_file {
char* address; /* Load address */
struct _dynamic* dynamic; /* Symbol table etc. */
} *aout_file_t;
static int load_dependancies(linker_file_t lf);
static int relocate_file(linker_file_t lf);
/*
* The kernel symbol table starts here.
*/
extern struct _dynamic _DYNAMIC;
static void
link_aout_init(void* arg)
{
struct _dynamic* dp = &_DYNAMIC;
linker_add_class("a.out", NULL, &link_aout_class_ops);
if (dp) {
aout_file_t af;
af = malloc(sizeof(struct aout_file), M_LINKER, M_NOWAIT);
if (af == NULL)
panic("link_aout_init: Can't create linker structures for kernel");
af->address = 0;
af->dynamic = dp;
linker_kernel_file =
linker_make_file(kernelname, af, &link_aout_file_ops);
if (linker_kernel_file == NULL)
panic("link_aout_init: Can't create linker structures for kernel");
/*
* XXX there must be a better way of getting these constants.
*/
linker_kernel_file->address = (caddr_t) 0xf0100000;
linker_kernel_file->size = -0xf0100000;
linker_current_file = linker_kernel_file;
}
}
SYSINIT(link_aout, SI_SUB_KMEM, SI_ORDER_THIRD, link_aout_init, 0);
int
link_aout_load_file(const char* filename, linker_file_t* result)
{
struct nameidata nd;
struct vnode* file;
struct proc* p = curproc; /* XXX */
int error = 0;
int resid;
struct iovec aiov;
struct uio auio;
struct exec header;
aout_file_t af;
linker_file_t lf;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, p);
error = vn_open(&nd, FREAD, 0);
if (error)
return error;
/*
* Read the a.out header from the file.
*/
error = vn_rdwr(UIO_READ, nd.ni_vp, (void*) &header, sizeof header, 0,
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
if (error)
goto out;
if (N_BADMAG(header) || !(N_GETFLAG(header) & EX_DYNAMIC))
goto out;
/*
* We have an a.out file, so make some space to read it in.
*/
af = malloc(sizeof(struct aout_file), M_LINKER, M_WAITOK);
af->address = malloc(header.a_text + header.a_data + header.a_bss,
M_LINKER, M_WAITOK);
/*
* Read the text and data sections and zero the bss.
*/
error = vn_rdwr(UIO_READ, nd.ni_vp, (void*) af->address,
header.a_text + header.a_data, 0,
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
if (error)
goto out;
bzero(af->address + header.a_text + header.a_data, header.a_bss);
/*
* Assume _DYNAMIC is the first data item.
*/
af->dynamic = (struct _dynamic*) (af->address + header.a_text);
if (af->dynamic->d_version != LD_VERSION_BSD) {
free(af->address, M_LINKER);
free(af, M_LINKER);
goto out;
}
(long) af->dynamic->d_un.d_sdt += af->address;
lf = linker_make_file(filename, af, &link_aout_file_ops);
if (lf == NULL) {
free(af->address, M_LINKER);
free(af, M_LINKER);
error = ENOMEM;
goto out;
}
lf->address = af->address;
lf->size = header.a_text + header.a_data + header.a_bss;
if ((error = load_dependancies(lf)) != 0
|| (error = relocate_file(lf)) != 0) {
linker_file_unload(lf);
goto out;
}
*result = lf;
out:
VOP_UNLOCK(nd.ni_vp, 0, p);
vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
return error;
}
void
link_aout_unload(linker_file_t file)
{
aout_file_t af = file->priv;
if (af) {
if (af->address)
free(af->address, M_LINKER);
free(af, M_LINKER);
}
}
#define AOUT_RELOC(af, type, off) (type*) ((af)->address + (off))
static int
load_dependancies(linker_file_t lf)
{
aout_file_t af = lf->priv;
linker_file_t lfdep;
long off;
struct sod* sodp;
char* name;
char* filename = 0;
int error = 0;
/*
* All files are dependant on /kernel.
*/
linker_kernel_file->refs++;
linker_file_add_dependancy(lf, linker_kernel_file);
off = LD_NEED(af->dynamic);
/*
* Load the dependancies.
*/
while (off != 0) {
sodp = AOUT_RELOC(af, struct sod, off);
name = AOUT_RELOC(af, char, sodp->sod_name);
/*
* Prepend pathname if dep is not an absolute filename.
*/
if (name[0] != '/') {
char* p;
filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
p = lf->filename + strlen(lf->filename) - 1;
while (p >= lf->filename && *p != '/')
p--;
if (p >= lf->filename) {
strncpy(filename, lf->filename, p - lf->filename);
filename[p - lf->filename] = '\0';
strcat(filename, "/");
strcat(filename, name);
name = filename;
}
}
error = linker_load_file(name, &lfdep);
if (error)
goto out;
error = linker_file_add_dependancy(lf, lfdep);
if (error)
goto out;
off = sodp->sod_next;
}
out:
if (filename)
free(filename, M_TEMP);
return error;
}
/*
* XXX i386 dependant.
*/
static long
read_relocation(struct relocation_info* r, char* addr)
{
int length = r->r_length;
if (length == 0)
return *(u_char*) addr;
else if (length == 1)
return *(u_short*) addr;
else if (length == 2)
return *(u_int*) addr;
else
printf("link_aout: unsupported relocation size %d\n", r->r_length);
return 0;
}
static void
write_relocation(struct relocation_info* r, char* addr, long value)
{
int length = r->r_length;
if (length == 0)
*(u_char*) addr = value;
else if (length == 1)
*(u_short*) addr = value;
else if (length == 2)
*(u_int*) addr = value;
else
printf("link_aout: unsupported relocation size %d\n", r->r_length);
}
static int
relocate_file(linker_file_t lf)
{
aout_file_t af = lf->priv;
struct relocation_info* rel;
struct relocation_info* erel;
struct relocation_info* r;
struct nzlist* symbolbase;
char* stringbase;
struct nzlist* np;
char* sym;
long relocation;
rel = AOUT_RELOC(af, struct relocation_info, LD_REL(af->dynamic));
erel = AOUT_RELOC(af, struct relocation_info,
LD_REL(af->dynamic) + LD_RELSZ(af->dynamic));
symbolbase = AOUT_RELOC(af, struct nzlist, LD_SYMBOL(af->dynamic));
stringbase = AOUT_RELOC(af, char, LD_STRINGS(af->dynamic));
for (r = rel; r < erel; r++) {
char* addr;
if (r->r_address == 0)
break;
addr = AOUT_RELOC(af, char, r->r_address);
if (r->r_extern) {
np = &symbolbase[r->r_symbolnum];
sym = &stringbase[np->nz_strx];
if (sym[0] != '_') {
printf("link_aout: bad symbol name %s\n", sym);
relocation = 0;
} else
relocation = (long)
linker_file_lookup_symbol(lf, sym + 1,
np->nz_type != (N_SETV+N_EXT));
if (!relocation) {
printf("link_aout: symbol %s not found\n", sym);
return ENOENT;
}
relocation += read_relocation(r, addr);
if (r->r_jmptable) {
printf("link_aout: can't cope with jump table relocations\n");
continue;
}
if (r->r_pcrel)
relocation -= (long) af->address;
if (r->r_copy) {
printf("link_aout: can't cope with copy relocations\n");
continue;
}
write_relocation(r, addr, relocation);
} else {
write_relocation(r, addr,
(long)(read_relocation(r, addr) + af->address));
}
}
return 0;
}
static long
symbol_hash_value(aout_file_t af, const char* name)
{
long hashval;
const char* p;
hashval = '_'; /* fake a starting '_' for C symbols */
for (p = name; *p; p++)
hashval = (hashval << 1) + *p;
return (hashval & 0x7fffffff) % LD_BUCKETS(af->dynamic);
}
int
link_aout_lookup_symbol(linker_file_t file, const char* name,
caddr_t* address, size_t* size)
{
aout_file_t af = file->priv;
int buckets;
long hashval;
struct rrs_hash* hashbase;
struct nzlist* symbolbase;
char* stringbase;
struct rrs_hash* hp;
struct nzlist* np;
char* cp;
if (LD_BUCKETS(af->dynamic) == 0)
return NULL;
hashbase = AOUT_RELOC(af, struct rrs_hash, LD_HASH(af->dynamic));
symbolbase = AOUT_RELOC(af, struct nzlist, LD_SYMBOL(af->dynamic));
stringbase = AOUT_RELOC(af, char, LD_STRINGS(af->dynamic));
restart:
hashval = symbol_hash_value(af, name);
hp = &hashbase[hashval];
if (hp->rh_symbolnum == -1)
return ENOENT;
while (hp) {
np = (struct nzlist *) &symbolbase[hp->rh_symbolnum];
cp = stringbase + np->nz_strx;
/*
* Note: we fake the leading '_' for C symbols.
*/
if (cp[0] == '_' && !strcmp(cp + 1, name))
break;
if (hp->rh_next == 0)
hp = NULL;
else
hp = &hashbase[hp->rh_next];
}
if (hp == NULL)
/*
* Not found.
*/
return ENOENT;
/*
* Check for an aliased symbol, whatever that is.
*/
if (np->nz_type == N_INDR+N_EXT) {
name = stringbase + (++np)->nz_strx + 1; /* +1 for '_' */
goto restart;
}
/*
* Check this is an actual definition of the symbol.
*/
if (np->nz_value == 0)
return ENOENT;
if (np->nz_type == N_UNDF+N_EXT && np->nz_value != 0) {
if (np->nz_other == AUX_FUNC)
/* weak function */
return ENOENT;
*address = 0;
*size = np->nz_value;
} else {
*address = AOUT_RELOC(af, char, np->nz_value);
*size = np->nz_size;
}
return 0;
}

View File

@ -276,4 +276,59 @@ char *syscallnames[] = {
"#252", /* 252 = poll */
"issetugid", /* 253 = issetugid */
"lchown", /* 254 = lchown */
"#255", /* 255 = nosys */
"#256", /* 256 = nosys */
"#257", /* 257 = nosys */
"#258", /* 258 = nosys */
"#259", /* 259 = nosys */
"#260", /* 260 = nosys */
"#261", /* 261 = nosys */
"#262", /* 262 = nosys */
"#263", /* 263 = nosys */
"#264", /* 264 = nosys */
"#265", /* 265 = nosys */
"#266", /* 266 = nosys */
"#267", /* 267 = nosys */
"#268", /* 268 = nosys */
"#269", /* 269 = nosys */
"#270", /* 270 = nosys */
"#271", /* 271 = nosys */
"#272", /* 272 = nosys */
"#273", /* 273 = nosys */
"#274", /* 274 = nosys */
"#275", /* 275 = nosys */
"#276", /* 276 = nosys */
"#277", /* 277 = nosys */
"#278", /* 278 = nosys */
"#279", /* 279 = nosys */
"#280", /* 280 = nosys */
"#281", /* 281 = nosys */
"#282", /* 282 = nosys */
"#283", /* 283 = nosys */
"#284", /* 284 = nosys */
"#285", /* 285 = nosys */
"#286", /* 286 = nosys */
"#287", /* 287 = nosys */
"#288", /* 288 = nosys */
"#289", /* 289 = nosys */
"#290", /* 290 = nosys */
"#291", /* 291 = nosys */
"#292", /* 292 = nosys */
"#293", /* 293 = nosys */
"#294", /* 294 = nosys */
"#295", /* 295 = nosys */
"#296", /* 296 = nosys */
"#297", /* 297 = nosys */
"#298", /* 298 = nosys */
"#299", /* 299 = nosys */
"modnext", /* 300 = modnext */
"modstat", /* 301 = modstat */
"modfnext", /* 302 = modfnext */
"modfind", /* 303 = modfind */
"kldload", /* 304 = kldload */
"kldunload", /* 305 = kldunload */
"kldfind", /* 306 = kldfind */
"kldnext", /* 307 = kldnext */
"kldstat", /* 308 = kldstat */
"kldfirstmod", /* 309 = kldfirstmod */
};

View File

@ -1,4 +1,4 @@
$Id: syscalls.master,v 1.34 1997/03/31 12:14:48 peter Exp $
$Id: syscalls.master,v 1.35 1997/03/31 14:52:50 peter Exp $
; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94
;
; System call name/number master file.
@ -393,3 +393,59 @@
252 UNIMPL NOHIDE poll (OpenBSD)
253 STD BSD { int issetugid(void); }
254 STD BSD { int lchown(char *path, int uid, int gid); }
255 UNIMPL NOHIDE nosys
256 UNIMPL NOHIDE nosys
257 UNIMPL NOHIDE nosys
258 UNIMPL NOHIDE nosys
259 UNIMPL NOHIDE nosys
260 UNIMPL NOHIDE nosys
261 UNIMPL NOHIDE nosys
262 UNIMPL NOHIDE nosys
263 UNIMPL NOHIDE nosys
264 UNIMPL NOHIDE nosys
265 UNIMPL NOHIDE nosys
266 UNIMPL NOHIDE nosys
267 UNIMPL NOHIDE nosys
268 UNIMPL NOHIDE nosys
269 UNIMPL NOHIDE nosys
270 UNIMPL NOHIDE nosys
271 UNIMPL NOHIDE nosys
272 UNIMPL NOHIDE nosys
273 UNIMPL NOHIDE nosys
274 UNIMPL NOHIDE nosys
275 UNIMPL NOHIDE nosys
276 UNIMPL NOHIDE nosys
277 UNIMPL NOHIDE nosys
278 UNIMPL NOHIDE nosys
279 UNIMPL NOHIDE nosys
280 UNIMPL NOHIDE nosys
281 UNIMPL NOHIDE nosys
282 UNIMPL NOHIDE nosys
283 UNIMPL NOHIDE nosys
284 UNIMPL NOHIDE nosys
285 UNIMPL NOHIDE nosys
286 UNIMPL NOHIDE nosys
287 UNIMPL NOHIDE nosys
288 UNIMPL NOHIDE nosys
289 UNIMPL NOHIDE nosys
290 UNIMPL NOHIDE nosys
291 UNIMPL NOHIDE nosys
292 UNIMPL NOHIDE nosys
293 UNIMPL NOHIDE nosys
294 UNIMPL NOHIDE nosys
295 UNIMPL NOHIDE nosys
296 UNIMPL NOHIDE nosys
297 UNIMPL NOHIDE nosys
298 UNIMPL NOHIDE nosys
299 UNIMPL NOHIDE nosys
; syscall numbers for FreeBSD
300 STD BSD { int modnext(int modid); }
301 STD BSD { int modstat(int modid, struct module_stat* stat); }
302 STD BSD { int modfnext(int modid); }
303 STD BSD { int modfind(char *name); }
304 STD BSD { int kldload(const char *file); }
305 STD BSD { int kldunload(int fileid); }
306 STD BSD { int kldfind(const char *file); }
307 STD BSD { int kldnext(int fileid); }
308 STD BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
309 STD BSD { int kldfirstmod(int fileid); }

207
sys/sys/linker.h Normal file
View File

@ -0,0 +1,207 @@
/*-
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (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$
*/
#ifndef _SYS_LINKER_H_
#define _SYS_LINKER_H_
#ifdef KERNEL
#define M_LINKER M_TEMP /* XXX */
/*
* Object representing a file which has been loaded by the linker.
*/
typedef struct linker_file* linker_file_t;
typedef TAILQ_HEAD(, linker_file) linker_file_list_t;
struct linker_file_ops {
/*
* Lookup a symbol in the file's symbol table. If the symbol is
* not found then return ENOENT, otherwise zero. If the symbol
* found is a common symbol, return with *address set to zero and
* *size set to the size of the common space required. Otherwise
* set *address the value of the symbol.
*/
int (*lookup_symbol)(linker_file_t, const char* name,
caddr_t* address, size_t* size);
/*
* Unload a file, releasing dependancies and freeing storage.
*/
void (*unload)(linker_file_t);
};
struct common_symbol {
STAILQ_ENTRY(common_symbol) link;
char* name;
caddr_t address;
};
struct linker_file {
int refs; /* reference count */
int userrefs; /* modload(2) count */
TAILQ_ENTRY(linker_file) link; /* list of all loaded files */
char* filename; /* file which was loaded */
int id; /* unique id */
caddr_t address; /* load address */
size_t size; /* size of file */
int ndeps; /* number of dependancies */
linker_file_t* deps; /* list of dependancies */
STAILQ_HEAD(, common_symbol) common; /* list of common symbols */
TAILQ_HEAD(, module) modules; /* modules in this file */
void* priv; /* implementation data */
struct linker_file_ops* ops;
};
/*
* Object implementing a class of file (a.out, elf, etc.)
*/
typedef struct linker_class *linker_class_t;
typedef TAILQ_HEAD(, linker_class) linker_class_list_t;
struct linker_class_ops {
/*
* Load a file, returning the new linker_file_t in *result. If
* the class does not recognise the file type, zero should be
* returned, without modifying *result. If the file is
* recognised, the file should be loaded, *result set to the new
* file and zero returned. If some other error is detected an
* appropriate errno should be returned.
*/
int (*load_file)(const char* filename, linker_file_t* result);
};
struct linker_class {
TAILQ_ENTRY(linker_class) link; /* list of all file classes */
const char* desc; /* description (e.g. "a.out") */
void* priv; /* implementation data */
struct linker_class_ops *ops;
};
/*
* The file representing the currently running kernel. This contains
* the global symbol table.
*/
linker_file_t linker_kernel_file;
/*
* The file which is currently loading. Used to register modules with
* the files which contain them.
*/
linker_file_t linker_current_file;
/*
* Add a new file class to the linker.
*/
int linker_add_class(const char* desc, void* priv,
struct linker_class_ops* ops);
/*
* Load a file, trying each file class until one succeeds.
*/
int linker_load_file(const char* filename, linker_file_t* result);
/*
* Find a currently loaded file given its filename.
*/
linker_file_t linker_find_file_by_name(const char* filename);
/*
* Find a currently loaded file given its file id.
*/
linker_file_t linker_find_file_by_id(int fileid);
/*
* Called from a class handler when a file is laoded.
*/
linker_file_t linker_make_file(const char* filename, void* priv,
struct linker_file_ops* ops);
/*
* Unload a file, freeing up memory.
*/
int linker_file_unload(linker_file_t file);
/*
* Add a dependancy to a file.
*/
int linker_file_add_dependancy(linker_file_t file, linker_file_t dep);
/*
* Lookup a symbol in a file. If deps is TRUE, look in dependancies
* if not found in file.
*/
caddr_t linker_file_lookup_symbol(linker_file_t file, const char* name,
int deps);
#ifdef KLD_DEBUG
extern int kld_debug;
#define KLD_DEBUG_FILE 1 /* file load/unload */
#define KLD_DEBUG_SYM 2 /* symbol lookup */
#define KLD_DPF(cat, args) \
do { \
if (KLD_debug & KLD_DEBUG_##cat) printf args; \
} while (0)
#else
#define KLD_DPF(cat, args)
#endif
#endif /* KERNEL */
struct kld_file_stat {
int version; /* set to sizeof(linker_file_stat) */
char name[MAXPATHLEN];
int refs;
int id;
caddr_t address; /* load address */
size_t size; /* size in bytes */
};
#ifndef KERNEL
#include <sys/cdefs.h>
__BEGIN_DECLS
int kldload(const char* file);
int kldunload(int fileid);
int kldfind(const char* file);
int kldnext(int fileid);
int kldstat(int fileid, struct kld_file_stat* stat);
int kldfirstmod(int fileid);
__END_DECLS
#endif
#endif /* !_SYS_KLD_H_ */

107
sys/sys/module.h Normal file
View File

@ -0,0 +1,107 @@
/*-
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (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$
*/
#ifndef _SYS_MODULE_H_
#define _SYS_MODULE_H_
#ifdef KERNEL
typedef enum {
MOD_LOAD,
MOD_UNLOAD,
MOD_SHUTDOWN
} modeventtype_t;
struct module;
typedef struct module *module_t;
typedef int (*modeventhand_t)(module_t mod, modeventtype_t what, void *arg);
/*
* Struct for registering modules statically via SYSINIT.
*/
typedef struct moduledata {
char* name; /* module name */
modeventhand_t evhand; /* event handler */
void* priv; /* extra data */
} moduledata_t;
#define DECLARE_MODULE(name, data, sub, order) \
SYSINIT(name##module, sub, order, module_register_static, &data)
void module_register_static(void *data);
int module_register(const char *name, modeventhand_t callback, void *arg);
module_t module_lookupbyname(const char *name);
module_t module_lookupbyid(int modid);
void module_reference(module_t mod);
void module_release(module_t mod);
int module_unload(module_t mod);
int module_getid(module_t mod);
module_t module_getfnext(module_t mod);
#ifdef MOD_DEBUG
extern int mod_debug;
#define MOD_DEBUG_REFS 1
#define MOD_DPF(cat, args) \
do { \
if (mod_debug & MOD_DEBUG_##cat) printf args; \
} while (0)
#else
#define MOD_DPF(cat, args)
#endif
#endif /* KERNEL */
#define MAXMODNAME 32
struct module_stat {
int version; /* set to sizeof(struct module_stat) */
char name[MAXMODNAME];
int refs;
int id;
};
#ifndef KERNEL
#include <sys/cdefs.h>
__BEGIN_DECLS
int modnext(int modid);
int modfnext(int modid);
int modstat(int modid, struct module_stat* stat);
int modfind(char *name);
__END_DECLS
#endif
#endif /* !_SYS_MODULE_H_ */

View File

@ -214,3 +214,13 @@ HIDE_BSD(minherit)
HIDE_BSD(rfork)
HIDE_BSD(issetugid)
HIDE_BSD(lchown)
HIDE_BSD(modnext)
HIDE_BSD(modstat)
HIDE_BSD(modfnext)
HIDE_BSD(modfind)
HIDE_BSD(kldload)
HIDE_BSD(kldunload)
HIDE_BSD(kldfind)
HIDE_BSD(kldnext)
HIDE_BSD(kldstat)
HIDE_BSD(kldfirstmod)

View File

@ -208,4 +208,14 @@
#define SYS_rfork 251
#define SYS_issetugid 253
#define SYS_lchown 254
#define SYS_MAXSYSCALL 255
#define SYS_modnext 300
#define SYS_modstat 301
#define SYS_modfnext 302
#define SYS_modfind 303
#define SYS_kldload 304
#define SYS_kldunload 305
#define SYS_kldfind 306
#define SYS_kldnext 307
#define SYS_kldstat 308
#define SYS_kldfirstmod 309
#define SYS_MAXSYSCALL 310

View File

@ -733,6 +733,38 @@ struct lchown_args {
int uid;
int gid;
};
struct modnext_args {
int modid;
};
struct modstat_args {
int modid;
struct module_stat * stat;
};
struct modfnext_args {
int modid;
};
struct modfind_args {
char * name;
};
struct kldload_args {
const char * file;
};
struct kldunload_args {
int fileid;
};
struct kldfind_args {
const char * file;
};
struct kldnext_args {
int fileid;
};
struct kldstat_args {
int fileid;
struct kld_file_stat * stat;
};
struct kldfirstmod_args {
int fileid;
};
int nosys __P((struct proc *, struct nosys_args *, int []));
void exit __P((struct proc *, struct rexit_args *, int [])) __dead2;
int fork __P((struct proc *, struct fork_args *, int []));
@ -905,6 +937,16 @@ int minherit __P((struct proc *, struct minherit_args *, int []));
int rfork __P((struct proc *, struct rfork_args *, int []));
int issetugid __P((struct proc *, struct issetugid_args *, int []));
int lchown __P((struct proc *, struct lchown_args *, int []));
int modnext __P((struct proc *, struct modnext_args *, int []));
int modstat __P((struct proc *, struct modstat_args *, int []));
int modfnext __P((struct proc *, struct modfnext_args *, int []));
int modfind __P((struct proc *, struct modfind_args *, int []));
int kldload __P((struct proc *, struct kldload_args *, int []));
int kldunload __P((struct proc *, struct kldunload_args *, int []));
int kldfind __P((struct proc *, struct kldfind_args *, int []));
int kldnext __P((struct proc *, struct kldnext_args *, int []));
int kldstat __P((struct proc *, struct kldstat_args *, int []));
int kldfirstmod __P((struct proc *, struct kldfirstmod_args *, int []));
#ifdef COMPAT_43