With this commit, I hereby pronounce gensetdefs past its use-by date.
Replace the a.out emulation of 'struct linker_set' with something a little more flexible. <sys/linker_set.h> now provides macros for accessing elements and completely hides the implementation. The linker_set.h macros have been on the back burner in various forms since 1998 and has ideas and code from Mike Smith (SET_FOREACH()), John Polstra (ELF clue) and myself (cleaned up API and the conversion of the rest of the kernel to use it). The macros declare a strongly typed set. They return elements with the type that you declare the set with, rather than a generic void *. For ELF, we use the magic ld symbols (__start_<setname> and __stop_<setname>). Thanks to Richard Henderson <rth@redhat.com> for the trick about how to force ld to provide them for kld's. For a.out, we use the old linker_set struct. NOTE: the item lists are no longer null terminated. This is why the code impact is high in certain areas. The runtime linker has a new method to find the linker set boundaries depending on which backend format is in use. linker sets are still module/kld unfriendly and should never be used for anything that may be modular one day. Reviewed by: eivind
This commit is contained in:
parent
f3a6406c66
commit
f41325db5f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=78161
@ -238,7 +238,6 @@ struct linux_sigframe {
|
||||
/*
|
||||
* Pluggable ioctl handlers
|
||||
*/
|
||||
struct linker_set;
|
||||
struct linux_ioctl_args;
|
||||
struct proc;
|
||||
|
||||
@ -250,9 +249,7 @@ struct linux_ioctl_handler {
|
||||
};
|
||||
|
||||
int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
|
||||
int linux_ioctl_register_handlers(struct linker_set *s);
|
||||
int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
|
||||
int linux_ioctl_unregister_handlers(struct linker_set *s);
|
||||
|
||||
/*
|
||||
* open/fcntl flags
|
||||
|
@ -77,7 +77,7 @@ MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
|
||||
#define SHELLMAGIC 0x2321
|
||||
#endif
|
||||
|
||||
extern struct linker_set linux_ioctl_handler_set;
|
||||
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
|
||||
|
||||
void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code);
|
||||
|
||||
@ -221,6 +221,7 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
{
|
||||
Elf64_Brandinfo **brandinfo;
|
||||
int error;
|
||||
struct linux_ioctl_handler **lihp;
|
||||
|
||||
error = 0;
|
||||
|
||||
@ -231,8 +232,8 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
if (elf_insert_brand_entry(*brandinfo) < 0)
|
||||
error = EINVAL;
|
||||
if (error == 0) {
|
||||
linux_ioctl_register_handlers(
|
||||
&linux_ioctl_handler_set);
|
||||
SET_FOREACH(lihp, linux_ioctl_handler_set)
|
||||
linux_ioctl_register_handler(*lihp);
|
||||
if (bootverbose)
|
||||
printf("Linux ELF exec handler installed\n");
|
||||
} else
|
||||
@ -250,8 +251,8 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
error = EINVAL;
|
||||
}
|
||||
if (error == 0) {
|
||||
linux_ioctl_unregister_handlers(
|
||||
&linux_ioctl_handler_set);
|
||||
SET_FOREACH(lihp, linux_ioctl_handler_set)
|
||||
linux_ioctl_unregister_handler(*lihp);
|
||||
if (bootverbose)
|
||||
printf("Linux ELF exec handler removed\n");
|
||||
} else
|
||||
|
@ -1516,37 +1516,3 @@ linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
int
|
||||
linux_ioctl_register_handlers(struct linker_set *s)
|
||||
{
|
||||
int error, i;
|
||||
|
||||
if (s == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
for (i = 0; i < s->ls_length; i++) {
|
||||
error = linux_ioctl_register_handler(s->ls_items[i]);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
linux_ioctl_unregister_handlers(struct linker_set *s)
|
||||
{
|
||||
int error, i;
|
||||
|
||||
if (s == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
for (i = 0; i < s->ls_length; i++) {
|
||||
error = linux_ioctl_unregister_handler(s->ls_items[i]);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -88,15 +88,10 @@ NORMAL_M= perl5 $S/kern/makeobjops.pl -c $<; \
|
||||
${CC} -c ${CFLAGS} ${PROF} ${.PREFIX}.c
|
||||
|
||||
GEN_CFILES= $S/$M/$M/genassym.c
|
||||
# setdef0.c and setdef1.c are intentionally
|
||||
# omitted from SYSTEM_CFILES. They include setdefs.h, a header which
|
||||
# is generated from all of ${OBJS}. We don't want to have to compile
|
||||
# everything just to do a make depend.
|
||||
SYSTEM_CFILES= param.c vnode_if.c hints.c config.c
|
||||
SYSTEM_SFILES= $S/$M/$M/locore.s
|
||||
SYSTEM_DEP= Makefile ${SYSTEM_OBJS}
|
||||
SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} param.o hints.o config.o \
|
||||
setdef1.o hack.So
|
||||
SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} param.o hints.o config.o hack.So
|
||||
SYSTEM_LD= @${LD} ${FMT} -Bdynamic -T $S/conf/ldscript.$M \
|
||||
-e locorestart \
|
||||
-export-dynamic -dynamic-linker /red/herring \
|
||||
@ -181,17 +176,6 @@ hack.So: Makefile
|
||||
${CC} ${FMT} -shared -nostdlib hack.c -o hack.So
|
||||
rm -f hack.c
|
||||
|
||||
.ORDER: setdefs.h setdef0.c setdef1.c
|
||||
|
||||
setdef0.o: setdef0.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef1.o: setdef1.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef0.c setdef1.c setdefs.h: Makefile ${OBJS}
|
||||
@perl5 $S/kern/gensetdefs.pl ${OBJS}
|
||||
|
||||
# this rule stops ./assym.s in .depend from causing problems
|
||||
./assym.s: assym.s
|
||||
|
||||
|
@ -91,15 +91,10 @@ NORMAL_M= perl5 $S/kern/makeobjops.pl -c $<; \
|
||||
${CC} -c ${CFLAGS} ${PROF} ${.PREFIX}.c
|
||||
|
||||
GEN_CFILES= $S/$M/$M/genassym.c
|
||||
# setdef0.c and setdef1.c are intentionally
|
||||
# omitted from SYSTEM_CFILES. They include setdefs.h, a header which
|
||||
# is generated from all of ${OBJS}. We don't want to have to compile
|
||||
# everything just to do a make depend.
|
||||
SYSTEM_CFILES= param.c vnode_if.c hints.c config.c
|
||||
SYSTEM_SFILES= $S/$M/$M/locore.s
|
||||
SYSTEM_DEP= Makefile ${SYSTEM_OBJS}
|
||||
SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} param.o hints.o config.o \
|
||||
setdef1.o hack.So
|
||||
SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} param.o hints.o config.o hack.So
|
||||
SYSTEM_LD= @${LD} ${FMT} -Bdynamic -T $S/conf/ldscript.$M \
|
||||
-export-dynamic -dynamic-linker /red/herring \
|
||||
-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
|
||||
@ -184,17 +179,6 @@ hack.So: Makefile
|
||||
${CC} ${FMT} -shared -nostdlib hack.c -o hack.So
|
||||
rm -f hack.c
|
||||
|
||||
.ORDER: setdefs.h setdef0.c setdef1.c
|
||||
|
||||
setdef0.o: setdef0.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef1.o: setdef1.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef0.c setdef1.c setdefs.h: Makefile ${OBJS}
|
||||
@perl5 $S/kern/gensetdefs.pl ${OBJS}
|
||||
|
||||
# this rule stops ./assym.s in .depend from causing problems
|
||||
./assym.s: assym.s
|
||||
|
||||
|
@ -101,15 +101,11 @@ NORMAL_M= perl5 $S/kern/makeobjops.pl -c $<; \
|
||||
${CC} -c ${CFLAGS} ${PROF} ${.PREFIX}.c
|
||||
|
||||
GEN_CFILES= $S/$M/$M/genassym.c
|
||||
# setdef0.c and setdef1.c are intentionally
|
||||
# omitted from SYSTEM_CFILES. They include setdefs.h, a header which
|
||||
# is generated from all of ${OBJS}. We don't want to have to compile
|
||||
# everything just to do a make depend.
|
||||
SYSTEM_CFILES= param.c vnode_if.c hints.c config.c
|
||||
SYSTEM_SFILES= $S/$M/$M/locore.s
|
||||
SYSTEM_DEP= Makefile ${SYSTEM_OBJS}
|
||||
SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} param.o hints.o config.o \
|
||||
setdef1.o # hack.So ski can't cope with dynamic relocs
|
||||
SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} param.o hints.o config.o \
|
||||
# hack.So ski can't cope with dynamic relocs
|
||||
SYSTEM_LD= @${LD} ${FMT} -Bdynamic -T $S/conf/ldscript.$M \
|
||||
-e locorestart \
|
||||
-export-dynamic -dynamic-linker /red/herring \
|
||||
@ -188,17 +184,6 @@ hack.So: Makefile
|
||||
${CC} ${FMT} -shared -nostdlib hack.c -o hack.So
|
||||
rm -f hack.c
|
||||
|
||||
.ORDER: setdefs.h setdef0.c setdef1.c
|
||||
|
||||
setdef0.o: setdef0.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef1.o: setdef1.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef0.c setdef1.c setdefs.h: Makefile ${OBJS}
|
||||
@OBJDUMP=${OBJDUMP} perl5 $S/kern/gensetdefs.pl ${OBJS}
|
||||
|
||||
# this rule stops ./assym.s in .depend from causing problems
|
||||
./assym.s: assym.s
|
||||
|
||||
|
@ -93,15 +93,10 @@ NORMAL_M= perl5 $S/kern/makeobjops.pl -c $<; \
|
||||
${CC} -c ${CFLAGS} ${PROF} ${.PREFIX}.c
|
||||
|
||||
GEN_CFILES= $S/$M/$M/genassym.c
|
||||
# setdef0.c and setdef1.c are intentionally
|
||||
# omitted from SYSTEM_CFILES. They include setdefs.h, a header which
|
||||
# is generated from all of ${OBJS}. We don't want to have to compile
|
||||
# everything just to do a make depend.
|
||||
SYSTEM_CFILES= param.c vnode_if.c hints.c config.c
|
||||
SYSTEM_SFILES= $S/$M/$M/locore.s
|
||||
SYSTEM_DEP= Makefile ${SYSTEM_OBJS}
|
||||
SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} param.o hints.o config.o \
|
||||
setdef1.o hack.So
|
||||
SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} param.o hints.o config.o hack.So
|
||||
SYSTEM_LD= @${LD} ${FMT} -Bdynamic -T $S/conf/ldscript.$M \
|
||||
-export-dynamic -dynamic-linker /red/herring \
|
||||
-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
|
||||
@ -186,17 +181,6 @@ hack.So: Makefile
|
||||
${CC} ${FMT} -shared -nostdlib hack.c -o hack.So
|
||||
rm -f hack.c
|
||||
|
||||
.ORDER: setdefs.h setdef0.c setdef1.c
|
||||
|
||||
setdef0.o: setdef0.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef1.o: setdef1.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef0.c setdef1.c setdefs.h: Makefile ${OBJS}
|
||||
@perl5 $S/kern/gensetdefs.pl ${OBJS}
|
||||
|
||||
# this rule stops ./assym.s in .depend from causing problems
|
||||
./assym.s: assym.s
|
||||
|
||||
|
@ -91,15 +91,10 @@ NORMAL_M= perl5 $S/kern/makeobjops.pl -c $<; \
|
||||
${CC} -c ${CFLAGS} ${PROF} ${.PREFIX}.c
|
||||
|
||||
GEN_CFILES= $S/$M/$M/genassym.c
|
||||
# setdef0.c and setdef1.c are intentionally
|
||||
# omitted from SYSTEM_CFILES. They include setdefs.h, a header which
|
||||
# is generated from all of ${OBJS}. We don't want to have to compile
|
||||
# everything just to do a make depend.
|
||||
SYSTEM_CFILES= param.c vnode_if.c hints.c config.c
|
||||
SYSTEM_SFILES= $S/$M/$M/locore.s
|
||||
SYSTEM_DEP= Makefile ${SYSTEM_OBJS}
|
||||
SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} param.o hints.o config.o \
|
||||
setdef1.o hack.So
|
||||
SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} param.o hints.o config.o hack.So
|
||||
SYSTEM_LD= @${LD} ${FMT} -Bdynamic -T $S/conf/ldscript.$M \
|
||||
-export-dynamic -dynamic-linker /red/herring \
|
||||
-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
|
||||
@ -184,17 +179,6 @@ hack.So: Makefile
|
||||
${CC} ${FMT} -shared -nostdlib hack.c -o hack.So
|
||||
rm -f hack.c
|
||||
|
||||
.ORDER: setdefs.h setdef0.c setdef1.c
|
||||
|
||||
setdef0.o: setdef0.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef1.o: setdef1.c setdefs.h
|
||||
${NORMAL_C}
|
||||
|
||||
setdef0.c setdef1.c setdefs.h: Makefile ${OBJS}
|
||||
@perl5 $S/kern/gensetdefs.pl ${OBJS}
|
||||
|
||||
# this rule stops ./assym.s in .depend from causing problems
|
||||
./assym.s: assym.s
|
||||
|
||||
|
@ -132,14 +132,7 @@ PROG= ${KMOD}.ko
|
||||
.endif
|
||||
|
||||
${PROG}: ${KMOD}.kld
|
||||
.if ${OBJFORMAT} == elf
|
||||
perl5 @/kern/gensetdefs.pl ${KMOD}.kld
|
||||
${CC} ${CFLAGS} -c setdef0.c
|
||||
${CC} ${CFLAGS} -c setdef1.c
|
||||
${LD} -Bshareable ${LDFLAGS} -o ${.TARGET} setdef0.o ${KMOD}.kld setdef1.o
|
||||
.else
|
||||
${LD} -Bshareable ${LDFLAGS} -o ${.TARGET} ${KMOD}.kld
|
||||
.endif
|
||||
|
||||
${KMOD}.kld: ${OBJS}
|
||||
${LD} ${LDFLAGS} -r -o ${.TARGET} ${OBJS}
|
||||
|
@ -51,13 +51,14 @@
|
||||
* Exported global variables
|
||||
*/
|
||||
boolean_t db_cmd_loop_done;
|
||||
extern struct linker_set db_cmd_set;
|
||||
db_addr_t db_dot;
|
||||
jmp_buf db_jmpbuf;
|
||||
db_addr_t db_last_addr;
|
||||
db_addr_t db_prev;
|
||||
db_addr_t db_next;
|
||||
extern struct linker_set db_show_cmd_set;
|
||||
|
||||
SET_DECLARE(db_cmd_set, struct command);
|
||||
SET_DECLARE(db_show_cmd_set, struct command);
|
||||
|
||||
static db_cmdfcn_t db_fncall;
|
||||
static db_cmdfcn_t db_gdb;
|
||||
@ -94,22 +95,26 @@ db_skip_to_eol()
|
||||
#define CMD_HELP 4
|
||||
|
||||
static void db_cmd_list __P((struct command *table,
|
||||
struct command **aux_tablep));
|
||||
struct command **aux_tablep,
|
||||
struct command **aux_tablep_end));
|
||||
static int db_cmd_search __P((char *name, struct command *table,
|
||||
struct command **aux_tablep,
|
||||
struct command **aux_tablep_end,
|
||||
struct command **cmdp));
|
||||
static void db_command __P((struct command **last_cmdp,
|
||||
struct command *cmd_table,
|
||||
struct command **aux_cmd_tablep));
|
||||
struct command **aux_cmd_tablep,
|
||||
struct command **aux_cmd_tablep_end));
|
||||
|
||||
/*
|
||||
* Search for command prefix.
|
||||
*/
|
||||
static int
|
||||
db_cmd_search(name, table, aux_tablep, cmdp)
|
||||
db_cmd_search(name, table, aux_tablep, aux_tablep_end, cmdp)
|
||||
char * name;
|
||||
struct command *table;
|
||||
struct command **aux_tablep;
|
||||
struct command **aux_tablep_end;
|
||||
struct command **cmdp; /* out */
|
||||
{
|
||||
struct command *cmd;
|
||||
@ -148,7 +153,7 @@ db_cmd_search(name, table, aux_tablep, cmdp)
|
||||
}
|
||||
if (result == CMD_NONE && aux_tablep != 0)
|
||||
/* XXX repeat too much code. */
|
||||
for (aux_cmdp = aux_tablep; *aux_cmdp != 0; aux_cmdp++) {
|
||||
for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
|
||||
register char *lp;
|
||||
register char *rp;
|
||||
register int c;
|
||||
@ -188,9 +193,10 @@ db_cmd_search(name, table, aux_tablep, cmdp)
|
||||
}
|
||||
|
||||
static void
|
||||
db_cmd_list(table, aux_tablep)
|
||||
db_cmd_list(table, aux_tablep, aux_tablep_end)
|
||||
struct command *table;
|
||||
struct command **aux_tablep;
|
||||
struct command **aux_tablep_end;
|
||||
{
|
||||
register struct command *cmd;
|
||||
register struct command **aux_cmdp;
|
||||
@ -201,17 +207,18 @@ db_cmd_list(table, aux_tablep)
|
||||
}
|
||||
if (aux_tablep == 0)
|
||||
return;
|
||||
for (aux_cmdp = aux_tablep; *aux_cmdp != 0; aux_cmdp++) {
|
||||
for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
|
||||
db_printf("%-12s", (*aux_cmdp)->name);
|
||||
db_end_line();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
db_command(last_cmdp, cmd_table, aux_cmd_tablep)
|
||||
db_command(last_cmdp, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end)
|
||||
struct command **last_cmdp; /* IN_OUT */
|
||||
struct command *cmd_table;
|
||||
struct command **aux_cmd_tablep;
|
||||
struct command **aux_cmd_tablep_end;
|
||||
{
|
||||
struct command *cmd;
|
||||
int t;
|
||||
@ -246,6 +253,7 @@ db_command(last_cmdp, cmd_table, aux_cmd_tablep)
|
||||
result = db_cmd_search(db_tok_string,
|
||||
cmd_table,
|
||||
aux_cmd_tablep,
|
||||
aux_cmd_tablep_end,
|
||||
&cmd);
|
||||
switch (result) {
|
||||
case CMD_NONE:
|
||||
@ -257,7 +265,7 @@ db_command(last_cmdp, cmd_table, aux_cmd_tablep)
|
||||
db_flush_lex();
|
||||
return;
|
||||
case CMD_HELP:
|
||||
db_cmd_list(cmd_table, aux_cmd_tablep);
|
||||
db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
|
||||
db_flush_lex();
|
||||
return;
|
||||
default:
|
||||
@ -267,12 +275,12 @@ db_command(last_cmdp, cmd_table, aux_cmd_tablep)
|
||||
/* XXX usually no more aux's. */
|
||||
aux_cmd_tablep = 0;
|
||||
if (cmd_table == db_show_cmds)
|
||||
aux_cmd_tablep =
|
||||
(struct command **)&db_show_cmd_set.ls_items[0];
|
||||
aux_cmd_tablep = SET_BEGIN(db_show_cmd_set);
|
||||
aux_cmd_tablep_end = SET_LIMIT(db_show_cmd_set);
|
||||
|
||||
t = db_read_token();
|
||||
if (t != tIDENT) {
|
||||
db_cmd_list(cmd_table, aux_cmd_tablep);
|
||||
db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
|
||||
db_flush_lex();
|
||||
return;
|
||||
}
|
||||
@ -453,7 +461,7 @@ db_command_loop()
|
||||
(void) db_read_line();
|
||||
|
||||
db_command(&db_last_command, db_command_table,
|
||||
(struct command **)&db_cmd_set.ls_items[0]);
|
||||
SET_BEGIN(db_cmd_set), SET_LIMIT(db_cmd_set));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,12 +39,15 @@
|
||||
#include <sys/module.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/fbio.h>
|
||||
#include <sys/linker_set.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <dev/fb/fbreg.h>
|
||||
|
||||
SET_DECLARE(videodriver_set, const video_driver_t);
|
||||
|
||||
/* local arrays */
|
||||
|
||||
/*
|
||||
@ -160,8 +163,8 @@ vid_register(video_adapter_t *adp)
|
||||
|
||||
adp->va_index = index;
|
||||
adp->va_token = NULL;
|
||||
list = (const video_driver_t **)videodriver_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, videodriver_set) {
|
||||
p = *list;
|
||||
if (strcmp(p->name, adp->va_name) == 0) {
|
||||
adapter[index] = adp;
|
||||
vidsw[index] = p->vidsw;
|
||||
@ -192,8 +195,8 @@ video_switch_t
|
||||
const video_driver_t **list;
|
||||
const video_driver_t *p;
|
||||
|
||||
list = (const video_driver_t **)videodriver_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, videodriver_set) {
|
||||
p = *list;
|
||||
if (strcmp(p->name, name) == 0)
|
||||
return p->vidsw;
|
||||
}
|
||||
@ -281,8 +284,8 @@ vid_configure(int flags)
|
||||
const video_driver_t **list;
|
||||
const video_driver_t *p;
|
||||
|
||||
list = (const video_driver_t **)videodriver_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, videodriver_set) {
|
||||
p = *list;
|
||||
if (p->configure != NULL)
|
||||
(*p->configure)(flags);
|
||||
}
|
||||
|
@ -148,7 +148,6 @@ typedef struct video_driver {
|
||||
|
||||
/* global variables */
|
||||
extern struct video_switch **vidsw;
|
||||
extern struct linker_set videodriver_set;
|
||||
|
||||
/* functions for the video card driver */
|
||||
int vid_register(video_adapter_t *adp);
|
||||
|
@ -54,6 +54,8 @@ typedef struct genkbd_softc {
|
||||
static SLIST_HEAD(, keyboard_driver) keyboard_drivers =
|
||||
SLIST_HEAD_INITIALIZER(keyboard_drivers);
|
||||
|
||||
SET_DECLARE(kbddriver_set, const keyboard_driver_t);
|
||||
|
||||
/* local arrays */
|
||||
|
||||
/*
|
||||
@ -199,8 +201,8 @@ kbd_register(keyboard_t *kbd)
|
||||
return index;
|
||||
}
|
||||
}
|
||||
list = (const keyboard_driver_t **)kbddriver_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, kbddriver_set) {
|
||||
p = *list;
|
||||
if (strcmp(p->name, kbd->kb_name) == 0) {
|
||||
keyboard[index] = kbd;
|
||||
kbdsw[index] = p->kbdsw;
|
||||
@ -254,8 +256,8 @@ keyboard_switch_t
|
||||
if (strcmp(p->name, driver) == 0)
|
||||
return p->kbdsw;
|
||||
}
|
||||
list = (const keyboard_driver_t **)kbddriver_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, kbddriver_set) {
|
||||
p = *list;
|
||||
if (strcmp(p->name, driver) == 0)
|
||||
return p->kbdsw;
|
||||
}
|
||||
@ -393,8 +395,8 @@ kbd_configure(int flags)
|
||||
if (p->configure != NULL)
|
||||
(*p->configure)(flags);
|
||||
}
|
||||
list = (const keyboard_driver_t **)kbddriver_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, kbddriver_set) {
|
||||
p = *list;
|
||||
if (p->configure != NULL)
|
||||
(*p->configure)(flags);
|
||||
}
|
||||
|
@ -173,7 +173,6 @@ typedef struct keyboard_driver {
|
||||
|
||||
/* global variables */
|
||||
extern keyboard_switch_t **kbdsw;
|
||||
extern struct linker_set kbddriver_set;
|
||||
|
||||
/* functions for the keyboard driver */
|
||||
int kbd_add_driver(keyboard_driver_t *driver);
|
||||
|
@ -80,8 +80,6 @@ static vr_draw_border_t vga_grborder;
|
||||
|
||||
static void vga_nop(scr_stat *scp, ...);
|
||||
|
||||
static struct linker_set vga_set;
|
||||
|
||||
static sc_rndr_sw_t txtrndrsw = {
|
||||
vga_txtclear,
|
||||
vga_txtborder,
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include <dev/syscons/syscons.h>
|
||||
#include <dev/syscons/sctermvar.h>
|
||||
|
||||
SET_DECLARE(scterm_set, sc_term_sw_t);
|
||||
|
||||
/* exported subroutines */
|
||||
|
||||
void
|
||||
@ -95,8 +97,8 @@ sc_term_sw_t
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list = (sc_term_sw_t **)scterm_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, scterm_set) {
|
||||
p = *list;
|
||||
if ((strcmp(name, p->te_name) == 0)
|
||||
|| (strcmp(name, "*") == 0)) {
|
||||
return p;
|
||||
|
@ -80,8 +80,6 @@ static vr_draw_border_t vga_grborder;
|
||||
|
||||
static void vga_nop(scr_stat *scp, ...);
|
||||
|
||||
static struct linker_set vga_set;
|
||||
|
||||
static sc_rndr_sw_t txtrndrsw = {
|
||||
vga_txtclear,
|
||||
vga_txtborder,
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include <dev/fb/fbreg.h>
|
||||
#include <dev/syscons/syscons.h>
|
||||
|
||||
SET_DECLARE(scrndr_set, const sc_renderer_t);
|
||||
|
||||
/* for compatibility with previous versions */
|
||||
/* 3.0-RELEASE used the following structure */
|
||||
typedef struct old_video_adapter {
|
||||
@ -803,8 +805,8 @@ sc_rndr_sw_t
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list = (const sc_renderer_t **)scrndr_set.ls_items;
|
||||
while ((p = *list++) != NULL) {
|
||||
SET_FOREACH(list, scrndr_set) {
|
||||
p = *list;
|
||||
if ((strcmp(p->name, name) == 0)
|
||||
&& (mode == p->mode)) {
|
||||
scp->status &=
|
||||
|
@ -342,8 +342,6 @@ typedef struct sc_term_sw {
|
||||
sc_term_input_t *te_input;
|
||||
} sc_term_sw_t;
|
||||
|
||||
extern struct linker_set scterm_set;
|
||||
|
||||
#define SCTERM_MODULE(name, sw) \
|
||||
DATA_SET(scterm_set, sw); \
|
||||
static int \
|
||||
@ -398,8 +396,6 @@ typedef struct sc_renderer {
|
||||
LIST_ENTRY(sc_renderer) link;
|
||||
} sc_renderer_t;
|
||||
|
||||
extern struct linker_set scrndr_set;
|
||||
|
||||
#define RENDERER(name, mode, sw, set) \
|
||||
static struct sc_renderer scrndr_##name##_##mode## = { \
|
||||
#name, mode, &sw \
|
||||
@ -408,25 +404,23 @@ extern struct linker_set scrndr_set;
|
||||
DATA_SET(set, scrndr_##name##_##mode##)
|
||||
|
||||
#define RENDERER_MODULE(name, set) \
|
||||
SET_DECLARE(set, sc_renderer_t); \
|
||||
static int \
|
||||
scrndr_##name##_event(module_t mod, int type, void *data) \
|
||||
{ \
|
||||
sc_renderer_t **list; \
|
||||
sc_renderer_t *p; \
|
||||
int error = 0; \
|
||||
switch (type) { \
|
||||
case MOD_LOAD: \
|
||||
list = (sc_renderer_t **)set.ls_items; \
|
||||
while ((p = *list++) != NULL) { \
|
||||
error = sc_render_add(p); \
|
||||
SET_FOREACH(list, set) { \
|
||||
error = sc_render_add(*list); \
|
||||
if (error) \
|
||||
break; \
|
||||
} \
|
||||
break; \
|
||||
case MOD_UNLOAD: \
|
||||
list = (sc_renderer_t **)set.ls_items; \
|
||||
while ((p = *list++) != NULL) { \
|
||||
error = sc_render_remove(p); \
|
||||
SET_FOREACH(list, set) { \
|
||||
error = sc_render_remove(*list);\
|
||||
if (error) \
|
||||
break; \
|
||||
} \
|
||||
|
@ -64,8 +64,6 @@
|
||||
|
||||
static int nwfs_fastlookup = 1;
|
||||
|
||||
extern struct linker_set sysctl_vfs_nwfs;
|
||||
|
||||
SYSCTL_DECL(_vfs_nwfs);
|
||||
SYSCTL_INT(_vfs_nwfs, OID_AUTO, fastlookup, CTLFLAG_RW, &nwfs_fastlookup, 0, "");
|
||||
|
||||
|
@ -71,8 +71,6 @@ MALLOC_DEFINE(M_NWFSHASH, "NWFS hash", "NWFS has table");
|
||||
|
||||
static int nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
extern struct linker_set sysctl_vfs_nwfs;
|
||||
|
||||
SYSCTL_DECL(_vfs_nwfs);
|
||||
|
||||
SYSCTL_PROC(_vfs_nwfs, OID_AUTO, vnprint, CTLFLAG_WR|CTLTYPE_OPAQUE,
|
||||
|
@ -73,8 +73,6 @@ extern int smbfs_pbuf_freecnt;
|
||||
|
||||
static int smbfs_fastlookup = 1;
|
||||
|
||||
extern struct linker_set sysctl_vfs_smbfs;
|
||||
|
||||
SYSCTL_DECL(_vfs_smbfs);
|
||||
SYSCTL_INT(_vfs_smbfs, OID_AUTO, fastlookup, CTLFLAG_RW, &smbfs_fastlookup, 0, "");
|
||||
|
||||
|
@ -69,7 +69,6 @@ static MALLOC_DEFINE(M_SMBNODENAME, "SMBFS nname", "SMBFS node name");
|
||||
int smbfs_hashprint(struct mount *mp);
|
||||
|
||||
#if 0
|
||||
extern struct linker_set sysctl_vfs_smbfs;
|
||||
#ifdef SYSCTL_DECL
|
||||
SYSCTL_DECL(_vfs_smbfs);
|
||||
#endif
|
||||
|
@ -366,7 +366,6 @@ extern struct sysentvec elf_linux_sysvec;
|
||||
/*
|
||||
* Pluggable ioctl handlers
|
||||
*/
|
||||
struct linker_set;
|
||||
struct linux_ioctl_args;
|
||||
struct proc;
|
||||
|
||||
@ -378,9 +377,7 @@ struct linux_ioctl_handler {
|
||||
};
|
||||
|
||||
int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
|
||||
int linux_ioctl_register_handlers(struct linker_set *s);
|
||||
int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
|
||||
int linux_ioctl_unregister_handlers(struct linker_set *s);
|
||||
|
||||
/*
|
||||
* open/fcntl flags
|
||||
|
@ -81,7 +81,7 @@ extern int linux_szsigcode;
|
||||
|
||||
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
|
||||
|
||||
extern struct linker_set linux_ioctl_handler_set;
|
||||
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
|
||||
|
||||
static int linux_fixup __P((register_t **stack_base,
|
||||
struct image_params *iparams));
|
||||
@ -809,6 +809,7 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
{
|
||||
Elf32_Brandinfo **brandinfo;
|
||||
int error;
|
||||
struct linux_ioctl_handler **lihp;
|
||||
|
||||
error = 0;
|
||||
|
||||
@ -819,8 +820,8 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
if (elf_insert_brand_entry(*brandinfo) < 0)
|
||||
error = EINVAL;
|
||||
if (error == 0) {
|
||||
linux_ioctl_register_handlers(
|
||||
&linux_ioctl_handler_set);
|
||||
SET_FOREACH(lihp, linux_ioctl_handler_set)
|
||||
linux_ioctl_register_handler(*lihp);
|
||||
if (bootverbose)
|
||||
printf("Linux ELF exec handler installed\n");
|
||||
} else
|
||||
@ -838,8 +839,8 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
error = EINVAL;
|
||||
}
|
||||
if (error == 0) {
|
||||
linux_ioctl_unregister_handlers(
|
||||
&linux_ioctl_handler_set);
|
||||
SET_FOREACH(lihp, linux_ioctl_handler_set)
|
||||
linux_ioctl_unregister_handler(*lihp);
|
||||
if (bootverbose)
|
||||
printf("Linux ELF exec handler removed\n");
|
||||
} else
|
||||
|
@ -77,8 +77,6 @@
|
||||
#include <sys/user.h>
|
||||
#include <sys/copyright.h>
|
||||
|
||||
extern struct linker_set sysinit_set; /* XXX */
|
||||
|
||||
void mi_startup(void); /* Should be elsewhere */
|
||||
|
||||
/* Components of the first process -- never freed. */
|
||||
@ -112,46 +110,43 @@ SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL)
|
||||
* The sysinit table itself. Items are checked off as the are run.
|
||||
* If we want to register new sysinit types, add them to newsysinit.
|
||||
*/
|
||||
struct sysinit **sysinit = (struct sysinit **)sysinit_set.ls_items;
|
||||
struct sysinit **newsysinit;
|
||||
SET_DECLARE(sysinit_set, struct sysinit);
|
||||
struct sysinit **sysinit, **sysinit_end;
|
||||
struct sysinit **newsysinit, **newsysinit_end;
|
||||
|
||||
/*
|
||||
* Merge a new sysinit set into the current set, reallocating it if
|
||||
* necessary. This can only be called after malloc is running.
|
||||
*/
|
||||
void
|
||||
sysinit_add(struct sysinit **set)
|
||||
sysinit_add(struct sysinit **set, struct sysinit **set_end)
|
||||
{
|
||||
struct sysinit **newset;
|
||||
struct sysinit **sipp;
|
||||
struct sysinit **xipp;
|
||||
int count = 0;
|
||||
int count;
|
||||
|
||||
count = set_end - set;
|
||||
if (newsysinit)
|
||||
for (sipp = newsysinit; *sipp; sipp++)
|
||||
count++;
|
||||
count += newsysinit_end - newsysinit;
|
||||
else
|
||||
for (sipp = sysinit; *sipp; sipp++)
|
||||
count++;
|
||||
for (sipp = set; *sipp; sipp++)
|
||||
count++;
|
||||
count++; /* Trailing NULL */
|
||||
count += sysinit_end - sysinit;
|
||||
newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT);
|
||||
if (newset == NULL)
|
||||
panic("cannot malloc for sysinit");
|
||||
xipp = newset;
|
||||
if (newsysinit)
|
||||
for (sipp = newsysinit; *sipp; sipp++)
|
||||
for (sipp = newsysinit; sipp < newsysinit_end; sipp++)
|
||||
*xipp++ = *sipp;
|
||||
else
|
||||
for (sipp = sysinit; *sipp; sipp++)
|
||||
for (sipp = sysinit; sipp < sysinit_end; sipp++)
|
||||
*xipp++ = *sipp;
|
||||
for (sipp = set; *sipp; sipp++)
|
||||
for (sipp = set; sipp < set_end; sipp++)
|
||||
*xipp++ = *sipp;
|
||||
*xipp = NULL;
|
||||
if (newsysinit)
|
||||
free(newsysinit, M_TEMP);
|
||||
newsysinit = newset;
|
||||
newsysinit_end = newset + count;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -173,13 +168,18 @@ mi_startup(void)
|
||||
register struct sysinit **xipp; /* interior loop of sort*/
|
||||
register struct sysinit *save; /* bubble*/
|
||||
|
||||
if (sysinit == NULL) {
|
||||
sysinit = SET_BEGIN(sysinit_set);
|
||||
sysinit_end = SET_LIMIT(sysinit_set);
|
||||
}
|
||||
|
||||
restart:
|
||||
/*
|
||||
* Perform a bubble sort of the system initialization objects by
|
||||
* their subsystem (primary key) and order (secondary key).
|
||||
*/
|
||||
for (sipp = sysinit; *sipp; sipp++) {
|
||||
for (xipp = sipp + 1; *xipp; xipp++) {
|
||||
for (sipp = sysinit; sipp < sysinit_end; sipp++) {
|
||||
for (xipp = sipp + 1; xipp < sysinit_end; xipp++) {
|
||||
if ((*sipp)->subsystem < (*xipp)->subsystem ||
|
||||
((*sipp)->subsystem == (*xipp)->subsystem &&
|
||||
(*sipp)->order <= (*xipp)->order))
|
||||
@ -197,7 +197,7 @@ mi_startup(void)
|
||||
* The last item on the list is expected to be the scheduler,
|
||||
* which will not return.
|
||||
*/
|
||||
for (sipp = sysinit; *sipp; sipp++) {
|
||||
for (sipp = sysinit; sipp < sysinit_end; sipp++) {
|
||||
|
||||
if ((*sipp)->subsystem == SI_SUB_DUMMY)
|
||||
continue; /* skip dummy task(s)*/
|
||||
@ -213,10 +213,12 @@ mi_startup(void)
|
||||
|
||||
/* Check if we've installed more sysinit items via KLD */
|
||||
if (newsysinit != NULL) {
|
||||
if (sysinit != (struct sysinit **)sysinit_set.ls_items)
|
||||
if (sysinit != SET_BEGIN(sysinit_set))
|
||||
free(sysinit, M_TEMP);
|
||||
sysinit = newsysinit;
|
||||
sysinit_end = newsysinit_end;
|
||||
newsysinit = NULL;
|
||||
newsysinit_end = NULL;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/linker_set.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <machine/globals.h>
|
||||
|
@ -54,6 +54,9 @@ int kld_debug = 0;
|
||||
static char *linker_search_path(const char *name);
|
||||
static const char *linker_basename(const char* path);
|
||||
|
||||
/* Metadata from the static kernel */
|
||||
SET_DECLARE(modmetadata_set, struct mod_metadata);
|
||||
|
||||
MALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
|
||||
|
||||
linker_file_t linker_kernel_file;
|
||||
@ -105,7 +108,7 @@ linker_add_class(linker_class_t lc)
|
||||
static void
|
||||
linker_file_sysinit(linker_file_t lf)
|
||||
{
|
||||
struct linker_set* sysinits;
|
||||
struct sysinit** start, ** stop;
|
||||
struct sysinit** sipp;
|
||||
struct sysinit** xipp;
|
||||
struct sysinit* save;
|
||||
@ -113,11 +116,7 @@ linker_file_sysinit(linker_file_t 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);
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_sysinit: SYSINITs %p\n", sysinits));
|
||||
if (!sysinits)
|
||||
if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
|
||||
return;
|
||||
/*
|
||||
* Perform a bubble sort of the system initialization objects by
|
||||
@ -126,8 +125,8 @@ linker_file_sysinit(linker_file_t lf)
|
||||
* 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++) {
|
||||
for (sipp = start; sipp < stop; sipp++) {
|
||||
for (xipp = sipp + 1; xipp < stop; xipp++) {
|
||||
if ((*sipp)->subsystem < (*xipp)->subsystem ||
|
||||
((*sipp)->subsystem == (*xipp)->subsystem &&
|
||||
(*sipp)->order <= (*xipp)->order))
|
||||
@ -143,7 +142,7 @@ linker_file_sysinit(linker_file_t lf)
|
||||
* Traverse the (now) ordered list of system initialization tasks.
|
||||
* Perform each task, and continue on to the next task.
|
||||
*/
|
||||
for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
|
||||
for (sipp = start; sipp < stop; sipp++) {
|
||||
if ((*sipp)->subsystem == SI_SUB_DUMMY)
|
||||
continue; /* skip dummy task(s)*/
|
||||
|
||||
@ -155,7 +154,7 @@ linker_file_sysinit(linker_file_t lf)
|
||||
static void
|
||||
linker_file_sysuninit(linker_file_t lf)
|
||||
{
|
||||
struct linker_set* sysuninits;
|
||||
struct sysinit** start, ** stop;
|
||||
struct sysinit** sipp;
|
||||
struct sysinit** xipp;
|
||||
struct sysinit* save;
|
||||
@ -163,11 +162,7 @@ linker_file_sysuninit(linker_file_t lf)
|
||||
KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
|
||||
lf->filename));
|
||||
|
||||
sysuninits = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, "sysuninit_set", 0);
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_sysuninit: SYSUNINITs %p\n", sysuninits));
|
||||
if (!sysuninits)
|
||||
if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop, NULL) != 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -177,8 +172,8 @@ linker_file_sysuninit(linker_file_t lf)
|
||||
* Since some things care about execution order, this is the
|
||||
* operation which ensures continued function.
|
||||
*/
|
||||
for (sipp = (struct sysinit **)sysuninits->ls_items; *sipp; sipp++) {
|
||||
for (xipp = sipp + 1; *xipp; xipp++) {
|
||||
for (sipp = start; sipp < stop; sipp++) {
|
||||
for (xipp = sipp + 1; xipp < stop; xipp++) {
|
||||
if ((*sipp)->subsystem > (*xipp)->subsystem ||
|
||||
((*sipp)->subsystem == (*xipp)->subsystem &&
|
||||
(*sipp)->order >= (*xipp)->order))
|
||||
@ -193,7 +188,7 @@ linker_file_sysuninit(linker_file_t lf)
|
||||
* Traverse the (now) ordered list of system initialization tasks.
|
||||
* Perform each task, and continue on to the next task.
|
||||
*/
|
||||
for (sipp = (struct sysinit **)sysuninits->ls_items; *sipp; sipp++) {
|
||||
for (sipp = start; sipp < stop; sipp++) {
|
||||
if ((*sipp)->subsystem == SI_SUB_DUMMY)
|
||||
continue; /* skip dummy task(s)*/
|
||||
|
||||
@ -205,64 +200,61 @@ linker_file_sysuninit(linker_file_t lf)
|
||||
static void
|
||||
linker_file_register_sysctls(linker_file_t lf)
|
||||
{
|
||||
struct linker_set* sysctls;
|
||||
struct sysctl_oid **start, **stop, **oidp;
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
|
||||
lf->filename));
|
||||
|
||||
sysctls = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, "sysctl_set", 0);
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_register_sysctls: SYSCTLs %p\n", sysctls));
|
||||
if (!sysctls)
|
||||
if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
|
||||
return;
|
||||
|
||||
sysctl_register_set(sysctls);
|
||||
for (oidp = start; oidp < stop; oidp++)
|
||||
sysctl_register_oid(*oidp);
|
||||
}
|
||||
|
||||
static void
|
||||
linker_file_unregister_sysctls(linker_file_t lf)
|
||||
{
|
||||
struct linker_set* sysctls;
|
||||
struct sysctl_oid **start, **stop, **oidp;
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs for %s\n",
|
||||
lf->filename));
|
||||
|
||||
sysctls = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, "sysctl_set", 0);
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_unregister_sysctls: SYSCTLs %p\n", sysctls));
|
||||
if (!sysctls)
|
||||
if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
|
||||
return;
|
||||
|
||||
sysctl_unregister_set(sysctls);
|
||||
for (oidp = start; oidp < stop; oidp++)
|
||||
sysctl_unregister_oid(*oidp);
|
||||
}
|
||||
|
||||
extern struct linker_set modmetadata_set;
|
||||
|
||||
static int
|
||||
linker_file_register_modules(linker_file_t lf)
|
||||
{
|
||||
int error;
|
||||
struct linker_set *modules;
|
||||
struct mod_metadata **mdpp;
|
||||
struct mod_metadata **start, **stop;
|
||||
struct mod_metadata **mdp;
|
||||
const moduledata_t *moddata;
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_register_modules: registering modules in %s\n",
|
||||
lf->filename));
|
||||
|
||||
modules = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, "modmetadata_set", 0);
|
||||
|
||||
if (!modules && lf == linker_kernel_file)
|
||||
modules = &modmetadata_set;
|
||||
|
||||
if (modules == NULL)
|
||||
return 0;
|
||||
for (mdpp = (struct mod_metadata**)modules->ls_items; *mdpp; mdpp++) {
|
||||
if ((*mdpp)->md_type != MDT_MODULE)
|
||||
if (linker_file_lookup_set(lf, "modmetadata_set", &start, &stop, 0) != 0) {
|
||||
/*
|
||||
* This fallback should be unnecessary, but if we get booted from
|
||||
* boot2 instead of loader and we are missing our metadata then
|
||||
* we have to try the best we can.
|
||||
*/
|
||||
if (lf == linker_kernel_file) {
|
||||
start = SET_BEGIN(modmetadata_set);
|
||||
stop = SET_LIMIT(modmetadata_set);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (mdp = start; mdp < stop; mdp++) {
|
||||
if ((*mdp)->md_type != MDT_MODULE)
|
||||
continue;
|
||||
moddata = (*mdpp)->md_data;
|
||||
moddata = (*mdp)->md_data;
|
||||
KLD_DPF(FILE, ("Registering module %s in %s\n",
|
||||
moddata->name, lf->filename));
|
||||
if (module_lookupbyname(moddata->name) != NULL) {
|
||||
@ -514,6 +506,19 @@ linker_file_add_dependancy(linker_file_t file, linker_file_t dep)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate a linker set and its contents.
|
||||
* This is a helper function to avoid linker_if.h exposure elsewhere.
|
||||
* Note: firstp and lastp are really void ***
|
||||
*/
|
||||
int
|
||||
linker_file_lookup_set(linker_file_t file, const char *name,
|
||||
void *firstp, void *lastp, int *countp)
|
||||
{
|
||||
|
||||
return LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
|
||||
}
|
||||
|
||||
caddr_t
|
||||
linker_file_lookup_symbol(linker_file_t file, const char* name, int deps)
|
||||
{
|
||||
@ -986,17 +991,18 @@ linker_mdt_depend(linker_file_t lf, struct mod_metadata *mp,
|
||||
}
|
||||
|
||||
static void
|
||||
linker_addmodules(linker_file_t lf, struct linker_set *deps, int preload)
|
||||
linker_addmodules(linker_file_t lf, struct mod_metadata **start,
|
||||
struct mod_metadata **stop, int preload)
|
||||
{
|
||||
struct mod_metadata *mp;
|
||||
struct mod_metadata *mp, **mdp;
|
||||
char *modname;
|
||||
int i, ver;
|
||||
int ver;
|
||||
|
||||
for (i = 0; i < deps->ls_length; i++) {
|
||||
for (mdp = start; mdp < stop; mdp++) {
|
||||
if (preload)
|
||||
mp = deps->ls_items[i];
|
||||
mp = *mdp;
|
||||
else
|
||||
mp = linker_reloc_ptr(lf, deps->ls_items[i]);
|
||||
mp = linker_reloc_ptr(lf, *mdp);
|
||||
if (mp->md_type != MDT_VERSION)
|
||||
continue;
|
||||
if (preload) {
|
||||
@ -1022,15 +1028,15 @@ linker_preload(void* arg)
|
||||
linker_file_t lf;
|
||||
linker_class_t lc;
|
||||
int error;
|
||||
struct linker_set *sysinits;
|
||||
linker_file_list_t loaded_files;
|
||||
linker_file_list_t depended_files;
|
||||
struct linker_set *deps;
|
||||
struct mod_metadata *mp, *nmp;
|
||||
struct mod_metadata **start, **stop, **mdp, **nmdp;
|
||||
struct mod_depend *verinfo;
|
||||
int i, j, nver;
|
||||
int nver;
|
||||
int resolves;
|
||||
modlist_t mod;
|
||||
struct sysinit **si_start, **si_stop;
|
||||
|
||||
TAILQ_INIT(&loaded_files);
|
||||
TAILQ_INIT(&depended_files);
|
||||
@ -1065,10 +1071,9 @@ linker_preload(void* arg)
|
||||
/*
|
||||
* First get a list of stuff in the kernel.
|
||||
*/
|
||||
deps = (struct linker_set*)
|
||||
linker_file_lookup_symbol(linker_kernel_file, MDT_SETNAME, 0);
|
||||
if (deps)
|
||||
linker_addmodules(linker_kernel_file, deps, 1);
|
||||
if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start, &stop,
|
||||
NULL) == 0)
|
||||
linker_addmodules(linker_kernel_file, start, stop, 1);
|
||||
|
||||
/*
|
||||
* this is a once-off kinky bubble sort
|
||||
@ -1076,20 +1081,19 @@ linker_preload(void* arg)
|
||||
*/
|
||||
restart:
|
||||
TAILQ_FOREACH(lf, &loaded_files, loaded) {
|
||||
deps = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, MDT_SETNAME, 0);
|
||||
error = linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, NULL);
|
||||
/*
|
||||
* First, look to see if we would successfully link with this stuff.
|
||||
*/
|
||||
resolves = 1; /* unless we know otherwise */
|
||||
if (deps) {
|
||||
for (i = 0; i < deps->ls_length; i++) {
|
||||
mp = linker_reloc_ptr(lf, deps->ls_items[i]);
|
||||
if (!error) {
|
||||
for (mdp = start; mdp < stop; mdp++) {
|
||||
mp = linker_reloc_ptr(lf, *mdp);
|
||||
if (mp->md_type != MDT_DEPEND)
|
||||
continue;
|
||||
linker_mdt_depend(lf, mp, &modname, &verinfo);
|
||||
for (j = 0; j < deps->ls_length; j++) {
|
||||
nmp = linker_reloc_ptr(lf, deps->ls_items[j]);
|
||||
for (nmdp = start; nmdp < stop; nmdp++) {
|
||||
nmp = linker_reloc_ptr(lf, *nmdp);
|
||||
if (nmp->md_type != MDT_VERSION)
|
||||
continue;
|
||||
linker_mdt_version(lf, nmp, &nmodname, NULL);
|
||||
@ -1097,7 +1101,7 @@ linker_preload(void* arg)
|
||||
if (strcmp(modname, nmodname) == 0)
|
||||
break;
|
||||
}
|
||||
if (j < deps->ls_length) /* it's a self reference */
|
||||
if (nmdp < stop) /* it's a self reference */
|
||||
continue;
|
||||
if (modlist_lookup(modname, 0) == NULL) {
|
||||
/* ok, the module isn't here yet, we are not finished */
|
||||
@ -1110,9 +1114,9 @@ linker_preload(void* arg)
|
||||
* modules inside and add it to the end of the link order list.
|
||||
*/
|
||||
if (resolves) {
|
||||
if (deps) {
|
||||
for (i = 0; i < deps->ls_length; i++) {
|
||||
mp = linker_reloc_ptr(lf, deps->ls_items[i]);
|
||||
if (!error) {
|
||||
for (mdp = start; mdp < stop; mdp++) {
|
||||
mp = linker_reloc_ptr(lf, *mdp);
|
||||
if (mp->md_type != MDT_VERSION)
|
||||
continue;
|
||||
linker_mdt_version(lf, mp, &modname, &nver);
|
||||
@ -1156,11 +1160,10 @@ linker_preload(void* arg)
|
||||
panic("cannot add dependency");
|
||||
}
|
||||
lf->userrefs++; /* so we can (try to) kldunload it */
|
||||
deps = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, MDT_SETNAME, 0);
|
||||
if (deps) {
|
||||
for (i = 0; i < deps->ls_length; i++) {
|
||||
mp = linker_reloc_ptr(lf, deps->ls_items[i]);
|
||||
error = linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, NULL);
|
||||
if (!error) {
|
||||
for (mdp = start; mdp < stop; mdp++) {
|
||||
mp = linker_reloc_ptr(lf, *mdp);
|
||||
if (mp->md_type != MDT_DEPEND)
|
||||
continue;
|
||||
linker_mdt_depend(lf, mp, &modname, &verinfo);
|
||||
@ -1172,7 +1175,10 @@ linker_preload(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Now do relocation etc using the symbol search paths established by the dependencies */
|
||||
/*
|
||||
* Now do relocation etc using the symbol search paths established by
|
||||
* the dependencies
|
||||
*/
|
||||
error = LINKER_LINK_PRELOAD_FINISH(lf);
|
||||
if (error) {
|
||||
printf("KLD file %s - could not finalize loading\n", lf->filename);
|
||||
@ -1181,10 +1187,8 @@ linker_preload(void* arg)
|
||||
}
|
||||
|
||||
linker_file_register_modules(lf);
|
||||
sysinits = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, "sysinit_set", 0);
|
||||
if (sysinits)
|
||||
sysinit_add((struct sysinit **)sysinits->ls_items);
|
||||
if (linker_file_lookup_set(lf, "sysinit_set", &si_start, &si_stop, NULL) == 0)
|
||||
sysinit_add(si_start, si_stop);
|
||||
linker_file_register_sysctls(lf);
|
||||
lf->flags |= LINKER_FILE_LINKED;
|
||||
}
|
||||
@ -1348,11 +1352,11 @@ int
|
||||
linker_load_dependancies(linker_file_t lf)
|
||||
{
|
||||
linker_file_t lfdep;
|
||||
struct linker_set *deps;
|
||||
struct mod_metadata **start, **stop, **mdp, **nmdp;
|
||||
struct mod_metadata *mp, *nmp;
|
||||
modlist_t mod;
|
||||
char *modname, *nmodname;
|
||||
int i, j, ver, error = 0;
|
||||
int ver, error = 0, count;
|
||||
|
||||
/*
|
||||
* All files are dependant on /kernel.
|
||||
@ -1364,12 +1368,10 @@ linker_load_dependancies(linker_file_t lf)
|
||||
return error;
|
||||
}
|
||||
|
||||
deps = (struct linker_set*)
|
||||
linker_file_lookup_symbol(lf, MDT_SETNAME, 0);
|
||||
if (deps == NULL)
|
||||
if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, &count) != 0)
|
||||
return 0;
|
||||
for (i = 0; i < deps->ls_length; i++) {
|
||||
mp = linker_reloc_ptr(lf, deps->ls_items[i]);
|
||||
for (mdp = start; mdp < stop; mdp++) {
|
||||
mp = linker_reloc_ptr(lf, *mdp);
|
||||
if (mp->md_type != MDT_VERSION)
|
||||
continue;
|
||||
linker_mdt_version(lf, mp, &modname, &ver);
|
||||
@ -1381,21 +1383,21 @@ linker_load_dependancies(linker_file_t lf)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < deps->ls_length; i++) {
|
||||
mp = linker_reloc_ptr(lf, deps->ls_items[i]);
|
||||
for (mdp = start; mdp < stop; mdp++) {
|
||||
mp = linker_reloc_ptr(lf, *mdp);
|
||||
if (mp->md_type != MDT_DEPEND)
|
||||
continue;
|
||||
modname = linker_reloc_ptr(lf, mp->md_cval);
|
||||
nmodname = NULL;
|
||||
for (j = 0; j < deps->ls_length; j++) {
|
||||
nmp = linker_reloc_ptr(lf, deps->ls_items[j]);
|
||||
for (nmdp = start; nmdp < stop; nmdp++) {
|
||||
nmp = linker_reloc_ptr(lf, *nmdp);
|
||||
if (nmp->md_type != MDT_VERSION)
|
||||
continue;
|
||||
nmodname = linker_reloc_ptr(lf, nmp->md_cval);
|
||||
if (strcmp(modname, nmodname) == 0)
|
||||
break;
|
||||
}
|
||||
if (j < deps->ls_length) /* early exit, it's a self reference */
|
||||
if (nmdp < stop) /* early exit, it's a self reference */
|
||||
continue;
|
||||
mod = modlist_lookup(modname, 0);
|
||||
if (mod) { /* woohoo, it's loaded already */
|
||||
@ -1416,6 +1418,6 @@ linker_load_dependancies(linker_file_t lf)
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
linker_addmodules(lf, deps, 0);
|
||||
linker_addmodules(lf, start, stop, 0);
|
||||
return error;
|
||||
}
|
||||
|
@ -366,35 +366,18 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
|
||||
return (oidp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bulk-register all the oids in a linker_set.
|
||||
*/
|
||||
void sysctl_register_set(struct linker_set *lsp)
|
||||
{
|
||||
int count = lsp->ls_length;
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
sysctl_register_oid((struct sysctl_oid *) lsp->ls_items[i]);
|
||||
}
|
||||
|
||||
void sysctl_unregister_set(struct linker_set *lsp)
|
||||
{
|
||||
int count = lsp->ls_length;
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
sysctl_unregister_oid((struct sysctl_oid *) lsp->ls_items[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the kernel's oids on startup.
|
||||
*/
|
||||
extern struct linker_set sysctl_set;
|
||||
SET_DECLARE(sysctl_set, struct sysctl_oid);
|
||||
|
||||
static void sysctl_register_all(void *arg)
|
||||
{
|
||||
sysctl_register_set(&sysctl_set);
|
||||
}
|
||||
struct sysctl_oid **oidp;
|
||||
|
||||
SET_FOREACH(oidp, sysctl_set)
|
||||
sysctl_register_oid(*oidp);
|
||||
}
|
||||
SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0);
|
||||
|
||||
/*
|
||||
|
@ -72,6 +72,8 @@ static int link_aout_search_symbol(linker_file_t lf, caddr_t value,
|
||||
c_linker_sym_t* sym, long* diffp);
|
||||
static void link_aout_unload_file(linker_file_t);
|
||||
static void link_aout_unload_preload(linker_file_t);
|
||||
static int link_aout_lookup_set(linker_file_t, const char*,
|
||||
void ***, void ***, int*);
|
||||
|
||||
static kobj_method_t link_aout_methods[] = {
|
||||
KOBJMETHOD(linker_lookup_symbol, link_aout_lookup_symbol),
|
||||
@ -81,6 +83,7 @@ static kobj_method_t link_aout_methods[] = {
|
||||
KOBJMETHOD(linker_load_file, link_aout_load_file),
|
||||
KOBJMETHOD(linker_link_preload, link_aout_link_preload),
|
||||
KOBJMETHOD(linker_link_preload_finish, link_aout_link_preload_finish),
|
||||
KOBJMETHOD(linker_lookup_set, link_aout_lookup_set),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -548,4 +551,40 @@ link_aout_search_symbol(linker_file_t lf, caddr_t value,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a linker set on an a.out + gnu LD system.
|
||||
*/
|
||||
struct generic_linker_set {
|
||||
int ls_length;
|
||||
void *ls_items[1];
|
||||
};
|
||||
static int
|
||||
link_aout_lookup_set(linker_file_t lf, const char *name,
|
||||
void ***startp, void ***stopp, int *countp)
|
||||
{
|
||||
c_linker_sym_t sym;
|
||||
linker_symval_t symval;
|
||||
void **start, **stop;
|
||||
int error, count;
|
||||
struct generic_linker_set *setp;
|
||||
|
||||
error = link_aout_lookup_symbol(lf, name, &sym);
|
||||
if (error)
|
||||
return error;
|
||||
link_aout_symbol_values(lf, sym, &symval);
|
||||
if (symval.value == 0)
|
||||
return ESRCH;
|
||||
setp = (struct generic_linker_set *)symval.value;
|
||||
count = setp->ls_length;
|
||||
start = &setp->ls_items[0];
|
||||
stop = &setp->ls_items[count];
|
||||
if (startp)
|
||||
*startp = start;
|
||||
if (stopp)
|
||||
*stopp = stop;
|
||||
if (countp)
|
||||
*countp = count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !__alpha__ */
|
||||
|
@ -108,6 +108,8 @@ static int link_elf_search_symbol(linker_file_t, caddr_t value,
|
||||
|
||||
static void link_elf_unload_file(linker_file_t);
|
||||
static void link_elf_unload_preload(linker_file_t);
|
||||
static int link_elf_lookup_set(linker_file_t, const char *,
|
||||
void ***, void ***, int *);
|
||||
|
||||
static kobj_method_t link_elf_methods[] = {
|
||||
KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
|
||||
@ -117,6 +119,7 @@ static kobj_method_t link_elf_methods[] = {
|
||||
KOBJMETHOD(linker_load_file, link_elf_load_file),
|
||||
KOBJMETHOD(linker_link_preload, link_elf_link_preload),
|
||||
KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
|
||||
KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -1075,3 +1078,61 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a linker set on an ELF system.
|
||||
*/
|
||||
static int
|
||||
link_elf_lookup_set(linker_file_t lf, const char *name,
|
||||
void ***startp, void ***stopp, int *countp)
|
||||
{
|
||||
c_linker_sym_t sym;
|
||||
linker_symval_t symval;
|
||||
char *setsym;
|
||||
void **start, **stop;
|
||||
int len, error = 0, count;
|
||||
|
||||
len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */
|
||||
setsym = malloc(len, M_LINKER, M_WAITOK);
|
||||
if (setsym == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
/* get address of first entry */
|
||||
snprintf(setsym, len, "%s%s", "__start_set_", name);
|
||||
error = link_elf_lookup_symbol(lf, setsym, &sym);
|
||||
if (error)
|
||||
goto out;
|
||||
link_elf_symbol_values(lf, sym, &symval);
|
||||
if (symval.value == 0) {
|
||||
error = ESRCH;
|
||||
goto out;
|
||||
}
|
||||
start = (void **)symval.value;
|
||||
|
||||
/* get address of last entry */
|
||||
snprintf(setsym, len, "%s%s", "__stop_set_", name);
|
||||
error = link_elf_lookup_symbol(lf, setsym, &sym);
|
||||
if (error)
|
||||
goto out;
|
||||
link_elf_symbol_values(lf, sym, &symval);
|
||||
if (symval.value == 0) {
|
||||
error = ESRCH;
|
||||
goto out;
|
||||
}
|
||||
stop = (void **)symval.value;
|
||||
|
||||
/* and the number of entries */
|
||||
count = stop - start;
|
||||
|
||||
/* and copy out */
|
||||
if (startp)
|
||||
*startp = start;
|
||||
if (stopp)
|
||||
*stopp = stop;
|
||||
if (countp)
|
||||
*countp = count;
|
||||
|
||||
out:
|
||||
free(setsym, M_LINKER);
|
||||
return error;
|
||||
}
|
||||
|
@ -108,6 +108,8 @@ static int link_elf_search_symbol(linker_file_t, caddr_t value,
|
||||
|
||||
static void link_elf_unload_file(linker_file_t);
|
||||
static void link_elf_unload_preload(linker_file_t);
|
||||
static int link_elf_lookup_set(linker_file_t, const char *,
|
||||
void ***, void ***, int *);
|
||||
|
||||
static kobj_method_t link_elf_methods[] = {
|
||||
KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
|
||||
@ -117,6 +119,7 @@ static kobj_method_t link_elf_methods[] = {
|
||||
KOBJMETHOD(linker_load_file, link_elf_load_file),
|
||||
KOBJMETHOD(linker_link_preload, link_elf_link_preload),
|
||||
KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
|
||||
KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -1075,3 +1078,61 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a linker set on an ELF system.
|
||||
*/
|
||||
static int
|
||||
link_elf_lookup_set(linker_file_t lf, const char *name,
|
||||
void ***startp, void ***stopp, int *countp)
|
||||
{
|
||||
c_linker_sym_t sym;
|
||||
linker_symval_t symval;
|
||||
char *setsym;
|
||||
void **start, **stop;
|
||||
int len, error = 0, count;
|
||||
|
||||
len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */
|
||||
setsym = malloc(len, M_LINKER, M_WAITOK);
|
||||
if (setsym == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
/* get address of first entry */
|
||||
snprintf(setsym, len, "%s%s", "__start_set_", name);
|
||||
error = link_elf_lookup_symbol(lf, setsym, &sym);
|
||||
if (error)
|
||||
goto out;
|
||||
link_elf_symbol_values(lf, sym, &symval);
|
||||
if (symval.value == 0) {
|
||||
error = ESRCH;
|
||||
goto out;
|
||||
}
|
||||
start = (void **)symval.value;
|
||||
|
||||
/* get address of last entry */
|
||||
snprintf(setsym, len, "%s%s", "__stop_set_", name);
|
||||
error = link_elf_lookup_symbol(lf, setsym, &sym);
|
||||
if (error)
|
||||
goto out;
|
||||
link_elf_symbol_values(lf, sym, &symval);
|
||||
if (symval.value == 0) {
|
||||
error = ESRCH;
|
||||
goto out;
|
||||
}
|
||||
stop = (void **)symval.value;
|
||||
|
||||
/* and the number of entries */
|
||||
count = stop - start;
|
||||
|
||||
/* and copy out */
|
||||
if (startp)
|
||||
*startp = start;
|
||||
if (stopp)
|
||||
*stopp = stop;
|
||||
if (countp)
|
||||
*countp = count;
|
||||
|
||||
out:
|
||||
free(setsym, M_LINKER);
|
||||
return error;
|
||||
}
|
||||
|
@ -53,6 +53,20 @@ METHOD int search_symbol {
|
||||
long* diffp;
|
||||
};
|
||||
|
||||
#
|
||||
# Search for a linker set in a file. Return a pointer to the first
|
||||
# entry (which is itself a pointer), and the number of entries.
|
||||
# "stop" points to the entry beyond the last valid entry.
|
||||
# If count, start or stop are NULL, they are not returned.
|
||||
#
|
||||
METHOD int lookup_set {
|
||||
linker_file_t file;
|
||||
const char* name;
|
||||
void*** start;
|
||||
void*** stop;
|
||||
int* count;
|
||||
};
|
||||
|
||||
#
|
||||
# Unload a file, releasing dependancies and freeing storage.
|
||||
#
|
||||
|
@ -99,6 +99,7 @@ static d_open_t *cn_phys_open; /* physical device open function */
|
||||
struct consdev *cn_tab; /* physical console device info */
|
||||
|
||||
CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
SET_DECLARE(cons_set, struct consdev);
|
||||
|
||||
void
|
||||
cninit()
|
||||
@ -109,8 +110,8 @@ cninit()
|
||||
* Find the first console with the highest priority.
|
||||
*/
|
||||
best_cp = NULL;
|
||||
list = (struct consdev **)cons_set.ls_items;
|
||||
while ((cp = *list++) != NULL) {
|
||||
SET_FOREACH(list, cons_set) {
|
||||
cp = *list;
|
||||
if (cp->cn_probe == NULL)
|
||||
continue;
|
||||
(*cp->cn_probe)(cp);
|
||||
|
@ -64,8 +64,6 @@ static int ncp_sysctl_connstat(SYSCTL_HANDLER_ARGS);
|
||||
static int ncp_conn_lock_any(struct ncp_conn *conn, struct proc *p,
|
||||
struct ucred *cred);
|
||||
|
||||
extern struct linker_set sysctl_net_ncp;
|
||||
|
||||
SYSCTL_DECL(_net_ncp);
|
||||
SYSCTL_INT (_net_ncp, OID_AUTO, burst_enabled, CTLFLAG_RD, &ncp_burst_enabled, 0, "");
|
||||
SYSCTL_INT (_net_ncp, OID_AUTO, conn_cnt, CTLFLAG_RD, &ncp_conn_cnt, 0, "");
|
||||
|
@ -56,8 +56,6 @@
|
||||
static struct smb_connobj smb_vclist;
|
||||
static int smb_vcnext = 1; /* next unique id for VC */
|
||||
|
||||
extern struct linker_set sysctl_net_smb;
|
||||
|
||||
SYSCTL_NODE(_net, OID_AUTO, smb, CTLFLAG_RW, NULL, "SMB protocol");
|
||||
|
||||
MALLOC_DEFINE(M_SMBCONN, "SMB conn", "SMB connection");
|
||||
|
@ -58,8 +58,6 @@ static vr_draw_border_t gdc_grborder;
|
||||
|
||||
static void gdc_nop(scr_stat *scp, ...);
|
||||
|
||||
static struct linker_set gdc_set;
|
||||
|
||||
static sc_rndr_sw_t txtrndrsw = {
|
||||
gdc_txtclear,
|
||||
gdc_txtborder,
|
||||
|
@ -58,8 +58,6 @@ static vr_draw_border_t gdc_grborder;
|
||||
|
||||
static void gdc_nop(scr_stat *scp, ...);
|
||||
|
||||
static struct linker_set gdc_set;
|
||||
|
||||
static sc_rndr_sw_t txtrndrsw = {
|
||||
gdc_txtclear,
|
||||
gdc_txtborder,
|
||||
|
@ -78,7 +78,6 @@ struct consdev {
|
||||
#define CN_REMOTE 3 /* serial interface with remote bit set */
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern struct linker_set cons_set;
|
||||
extern int cons_unavail;
|
||||
extern struct consdev *cn_tab;
|
||||
|
||||
|
@ -250,7 +250,7 @@ struct sysinit {
|
||||
C_SYSUNINIT(uniquifier, subsystem, order, \
|
||||
(sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)ident)
|
||||
|
||||
void sysinit_add __P((struct sysinit **set));
|
||||
void sysinit_add __P((struct sysinit **set, struct sysinit **set_end));
|
||||
|
||||
/*
|
||||
* Infrastructure for tunable 'constants'. Value may be specified at compile
|
||||
|
@ -138,6 +138,14 @@ int linker_file_add_dependancy(linker_file_t _file, linker_file_t _dep);
|
||||
caddr_t linker_file_lookup_symbol(linker_file_t _file, const char* _name,
|
||||
int _deps);
|
||||
|
||||
/*
|
||||
* Lookup a linker set in a file. Return pointers to the first entry,
|
||||
* last + 1, and count of entries. Use: for (p = start; p < stop; p++) {}
|
||||
* void *start is really: "struct yoursetmember ***start;"
|
||||
*/
|
||||
int linker_file_lookup_set(linker_file_t _file, const char *_name,
|
||||
void *_start, void *_stop, int *_count);
|
||||
|
||||
/*
|
||||
* This routine is responsible for finding dependencies of userland
|
||||
* initiated kldload(2)'s of files.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 John D. Polstra
|
||||
* Copyright (c) 1999,2001 Peter Wemm <peter@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -31,56 +32,109 @@
|
||||
|
||||
/*
|
||||
* The following macros are used to declare global sets of objects, which
|
||||
* are collected by the linker into a `struct linker_set' as defined below.
|
||||
* are collected by the linker into a `linker_set' as defined below.
|
||||
* For ELF, this is done by constructing a separate segment for each set.
|
||||
* For a.out, it is done automatically by the linker.
|
||||
*
|
||||
* In the MAKE_SET macros below, the lines:
|
||||
*
|
||||
* static void const * const __set_##set##_sym_##sym = &sym;
|
||||
*
|
||||
* are present only to prevent the compiler from producing bogus
|
||||
* warnings about unused symbols.
|
||||
*/
|
||||
#ifdef __ELF__
|
||||
|
||||
#if defined(__alpha__) || defined(__ia64__)
|
||||
#define MAKE_SET(set, sym) \
|
||||
static void const * const __set_##set##_sym_##sym = &sym; \
|
||||
__asm(".section .set." #set ",\"aw\""); \
|
||||
__asm(".p2align 3"); \
|
||||
__asm(".quad " #sym); \
|
||||
__asm(".previous")
|
||||
#else
|
||||
#define MAKE_SET(set, sym) \
|
||||
static void const * const __set_##set##_sym_##sym = &sym; \
|
||||
__asm(".section .set." #set ",\"aw\""); \
|
||||
__asm(".p2align 2"); \
|
||||
__asm(".long " #sym); \
|
||||
__asm(".previous")
|
||||
#endif
|
||||
#define TEXT_SET(set, sym) MAKE_SET(set, sym)
|
||||
#define DATA_SET(set, sym) MAKE_SET(set, sym)
|
||||
#if defined(__ELF__)
|
||||
/*
|
||||
* Private macros, not to be used outside this header file.
|
||||
*/
|
||||
/* this bit of h0h0magic brought to you by cpp */
|
||||
#define __GLOBL(sym) __GLOBL2(sym)
|
||||
#define __GLOBL2(sym) __asm(".globl " #sym)
|
||||
|
||||
#else
|
||||
#define __MAKE_SET(set, sym) \
|
||||
__GLOBL(__CONCAT(__start_set_,set)); \
|
||||
__GLOBL(__CONCAT(__stop_set_,set)); \
|
||||
static void const * const __set_##set##_sym_##sym \
|
||||
__attribute__((__section__("set_" #set),__unused__)) = &sym
|
||||
|
||||
/*
|
||||
* Public macros.
|
||||
*/
|
||||
#define TEXT_SET(set, sym) __MAKE_SET(set, sym)
|
||||
#define DATA_SET(set, sym) __MAKE_SET(set, sym)
|
||||
#define BSS_SET(set, sym) __MAKE_SET(set, sym)
|
||||
#define ABS_SET(set, sym) __MAKE_SET(set, sym)
|
||||
#define SET_ENTRY(set, sym) __MAKE_SET(set, sym)
|
||||
|
||||
/*
|
||||
* Initialize before referring to a give linker set
|
||||
*/
|
||||
#define SET_DECLARE(set, ptype) \
|
||||
extern ptype *__CONCAT(__start_set_,set); \
|
||||
extern ptype *__CONCAT(__stop_set_,set)
|
||||
|
||||
#define SET_BEGIN(set) \
|
||||
(&__CONCAT(__start_set_,set))
|
||||
#define SET_LIMIT(set) \
|
||||
(&__CONCAT(__stop_set_,set))
|
||||
|
||||
#else /* __ELF__ */
|
||||
|
||||
/*
|
||||
* The old way. This depends on GNU ld extensions that are not widely
|
||||
* available outside of the a.out format.
|
||||
*
|
||||
* NB: the constants defined below must match those defined in
|
||||
* ld/ld.h. Since their calculation requires arithmetic, we
|
||||
* can't name them symbolically (e.g., 23 is N_SETT | N_EXT).
|
||||
*
|
||||
* In the __MAKE_SET macro below, the line:
|
||||
* static void const * const __set_##set##_sym_##sym = &sym;
|
||||
* is present only to prevent the compiler from producing bogus
|
||||
* warnings about unused symbols.
|
||||
*/
|
||||
#define MAKE_SET(set, sym, type) \
|
||||
static void const * const __set_##set##_sym_##sym = &sym; \
|
||||
/* Private macros */
|
||||
#ifdef __UNDERSCORES__
|
||||
#define __MAKE_SET(set, sym, type) \
|
||||
static void const * const __set_##set##_sym_##sym = &sym; \
|
||||
__asm(".stabs \"_" #set "\", " #type ", 0, 0, _" #sym)
|
||||
#else
|
||||
#define __MAKE_SET(set, sym, type) \
|
||||
static void const * const __set_##set##_sym_##sym = &sym; \
|
||||
__asm(".stabs \"" #set "\", " #type ", 0, 0, " #sym)
|
||||
#define TEXT_SET(set, sym) MAKE_SET(set, sym, 23)
|
||||
#define DATA_SET(set, sym) MAKE_SET(set, sym, 25)
|
||||
|
||||
#endif
|
||||
|
||||
struct linker_set {
|
||||
int ls_length;
|
||||
void *ls_items[1]; /* really ls_length of them,
|
||||
* trailing NULL */
|
||||
};
|
||||
/* Public Macros */
|
||||
#define TEXT_SET(set, sym) __MAKE_SET(set, sym, 23)
|
||||
#define DATA_SET(set, sym) __MAKE_SET(set, sym, 25)
|
||||
#define BSS_SET(set, sym) __MAKE_SET(set, sym, 27)
|
||||
#define ABS_SET(set, sym) __MAKE_SET(set, sym, 21)
|
||||
#define SET_ENTRY(set, sym) error error must provide text/data type
|
||||
|
||||
#endif /* _SYS_LINKER_SET_H_ */
|
||||
#define SET_DECLARE(set, ptype) \
|
||||
extern struct { \
|
||||
int ls_length; \
|
||||
ptype *ls_items[1]; \
|
||||
} set
|
||||
|
||||
#define SET_BEGIN(set) \
|
||||
(&((set).ls_items[0]))
|
||||
#define SET_LIMIT(set) \
|
||||
(&((set).ls_items[(set).ls_length]))
|
||||
|
||||
#endif /* __ELF__ */
|
||||
|
||||
/*
|
||||
* Iterate over all the elements of a set.
|
||||
*
|
||||
* Sets always contain addresses of things, and "pvar" points to words
|
||||
* containing those addresses. Thus is must be declared as "type **pvar",
|
||||
* and the address of each set item is obtained inside the loop by "*pvar".
|
||||
*/
|
||||
#define SET_FOREACH(pvar, set) \
|
||||
for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
|
||||
|
||||
#define SET_ITEM(set, i) \
|
||||
((SET_BEGIN(set))[i])
|
||||
|
||||
/*
|
||||
* Provide a count of the items in a set.
|
||||
*/
|
||||
#define SET_COUNT(set) \
|
||||
(SET_LIMIT(set) - SET_BEGIN(set))
|
||||
|
||||
#endif /* _SYS_LINKER_SET_H_ */
|
||||
|
@ -557,8 +557,6 @@ extern char machine[];
|
||||
extern char osrelease[];
|
||||
extern char ostype[];
|
||||
|
||||
struct linker_set;
|
||||
|
||||
/* Dynamic oid handling */
|
||||
struct sysctl_oid *sysctl_add_oid(struct sysctl_ctx_list *clist,
|
||||
struct sysctl_oid_list *parent, int nbr, const char *name,
|
||||
@ -575,10 +573,6 @@ struct sysctl_ctx_entry *sysctl_ctx_entry_find(struct sysctl_ctx_list *clist,
|
||||
int sysctl_ctx_entry_del(struct sysctl_ctx_list *clist,
|
||||
struct sysctl_oid *oidp);
|
||||
|
||||
/* Linker set based oid handling */
|
||||
void sysctl_register_set(struct linker_set *lsp);
|
||||
void sysctl_unregister_set(struct linker_set *lsp);
|
||||
|
||||
int kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old,
|
||||
size_t *oldlenp, void *new, size_t newlen,
|
||||
size_t *retval);
|
||||
|
Loading…
Reference in New Issue
Block a user