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:
Peter Wemm 2001-06-13 10:58:39 +00:00
parent f3a6406c66
commit f41325db5f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=78161
43 changed files with 473 additions and 390 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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 &=

View File

@ -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; \
} \

View File

@ -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, "");

View File

@ -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,

View File

@ -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, "");

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
/*

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.
#

View File

@ -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);

View File

@ -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, "");

View File

@ -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");

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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_ */

View File

@ -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);