From f41325db5f16640212574a03b9a34e5ed4a884ca Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Wed, 13 Jun 2001 10:58:39 +0000 Subject: [PATCH] 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. 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_ and __stop_). Thanks to Richard Henderson 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 --- sys/alpha/linux/linux.h | 3 - sys/alpha/linux/linux_sysvec.c | 11 +- sys/compat/linux/linux_ioctl.c | 34 ------ sys/conf/Makefile.alpha | 18 +--- sys/conf/Makefile.i386 | 18 +--- sys/conf/Makefile.ia64 | 19 +--- sys/conf/Makefile.pc98 | 18 +--- sys/conf/Makefile.powerpc | 18 +--- sys/conf/kmod.mk | 7 -- sys/ddb/db_command.c | 36 ++++--- sys/dev/fb/fb.c | 15 +-- sys/dev/fb/fbreg.h | 1 - sys/dev/kbd/kbd.c | 14 +-- sys/dev/kbd/kbdreg.h | 1 - sys/dev/syscons/scgfbrndr.c | 2 - sys/dev/syscons/scterm.c | 6 +- sys/dev/syscons/scvgarndr.c | 2 - sys/dev/syscons/scvidctl.c | 6 +- sys/dev/syscons/syscons.h | 16 +-- sys/fs/nwfs/nwfs_io.c | 2 - sys/fs/nwfs/nwfs_node.c | 2 - sys/fs/smbfs/smbfs_io.c | 2 - sys/fs/smbfs/smbfs_node.c | 1 - sys/i386/linux/linux.h | 3 - sys/i386/linux/linux_sysvec.c | 11 +- sys/kern/init_main.c | 44 ++++---- sys/kern/kern_ktr.c | 1 - sys/kern/kern_linker.c | 190 +++++++++++++++++---------------- sys/kern/kern_sysctl.c | 27 +---- sys/kern/link_aout.c | 39 +++++++ sys/kern/link_elf.c | 61 +++++++++++ sys/kern/link_elf_obj.c | 61 +++++++++++ sys/kern/linker_if.m | 14 +++ sys/kern/tty_cons.c | 5 +- sys/netncp/ncp_conn.c | 2 - sys/netsmb/smb_conn.c | 2 - sys/pc98/cbus/scgdcrndr.c | 2 - sys/pc98/pc98/scgdcrndr.c | 2 - sys/sys/cons.h | 1 - sys/sys/kernel.h | 2 +- sys/sys/linker.h | 8 ++ sys/sys/linker_set.h | 130 +++++++++++++++------- sys/sys/sysctl.h | 6 -- 43 files changed, 473 insertions(+), 390 deletions(-) diff --git a/sys/alpha/linux/linux.h b/sys/alpha/linux/linux.h index a11baaa579f2..af3f3acef230 100644 --- a/sys/alpha/linux/linux.h +++ b/sys/alpha/linux/linux.h @@ -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 diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c index f0b12497a5c0..6f93dc8f6f83 100644 --- a/sys/alpha/linux/linux_sysvec.c +++ b/sys/alpha/linux/linux_sysvec.c @@ -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 diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 1cf76cf80d0e..3b14eb23e437 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -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); -} diff --git a/sys/conf/Makefile.alpha b/sys/conf/Makefile.alpha index eb79ab78b197..5f02ae813f9b 100644 --- a/sys/conf/Makefile.alpha +++ b/sys/conf/Makefile.alpha @@ -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 diff --git a/sys/conf/Makefile.i386 b/sys/conf/Makefile.i386 index ec4b719ad597..7e70fd1bd6d2 100644 --- a/sys/conf/Makefile.i386 +++ b/sys/conf/Makefile.i386 @@ -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 diff --git a/sys/conf/Makefile.ia64 b/sys/conf/Makefile.ia64 index 174c72774576..e52be5d29816 100644 --- a/sys/conf/Makefile.ia64 +++ b/sys/conf/Makefile.ia64 @@ -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 diff --git a/sys/conf/Makefile.pc98 b/sys/conf/Makefile.pc98 index f194f8757754..a3a9f56a1864 100644 --- a/sys/conf/Makefile.pc98 +++ b/sys/conf/Makefile.pc98 @@ -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 diff --git a/sys/conf/Makefile.powerpc b/sys/conf/Makefile.powerpc index ec4b719ad597..7e70fd1bd6d2 100644 --- a/sys/conf/Makefile.powerpc +++ b/sys/conf/Makefile.powerpc @@ -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 diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 7b1f7c814f9a..54f5bff2c037 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -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} diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c index 201d1f1bbb09..39378e9c7d01 100644 --- a/sys/ddb/db_command.c +++ b/sys/ddb/db_command.c @@ -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)); } } diff --git a/sys/dev/fb/fb.c b/sys/dev/fb/fb.c index 3d927617369c..056988dc02b5 100644 --- a/sys/dev/fb/fb.c +++ b/sys/dev/fb/fb.c @@ -39,12 +39,15 @@ #include #include #include +#include #include #include #include +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); } diff --git a/sys/dev/fb/fbreg.h b/sys/dev/fb/fbreg.h index 7070f19d52f4..ba6c0e1322c3 100644 --- a/sys/dev/fb/fbreg.h +++ b/sys/dev/fb/fbreg.h @@ -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); diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c index 8ebba7ee29d2..ce55b65fa417 100644 --- a/sys/dev/kbd/kbd.c +++ b/sys/dev/kbd/kbd.c @@ -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); } diff --git a/sys/dev/kbd/kbdreg.h b/sys/dev/kbd/kbdreg.h index de7d9419c910..55e0cefbbca0 100644 --- a/sys/dev/kbd/kbdreg.h +++ b/sys/dev/kbd/kbdreg.h @@ -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); diff --git a/sys/dev/syscons/scgfbrndr.c b/sys/dev/syscons/scgfbrndr.c index 85c4418e1036..6767610279b2 100644 --- a/sys/dev/syscons/scgfbrndr.c +++ b/sys/dev/syscons/scgfbrndr.c @@ -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, diff --git a/sys/dev/syscons/scterm.c b/sys/dev/syscons/scterm.c index 99fad9857118..5b9c2f40ce7a 100644 --- a/sys/dev/syscons/scterm.c +++ b/sys/dev/syscons/scterm.c @@ -36,6 +36,8 @@ #include #include +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; diff --git a/sys/dev/syscons/scvgarndr.c b/sys/dev/syscons/scvgarndr.c index 85c4418e1036..6767610279b2 100644 --- a/sys/dev/syscons/scvgarndr.c +++ b/sys/dev/syscons/scvgarndr.c @@ -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, diff --git a/sys/dev/syscons/scvidctl.c b/sys/dev/syscons/scvidctl.c index be9d1e66f30d..72dc7db13045 100644 --- a/sys/dev/syscons/scvidctl.c +++ b/sys/dev/syscons/scvidctl.c @@ -40,6 +40,8 @@ #include #include +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 &= diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index d2d605d13038..ef10f4da110f 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -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; \ } \ diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c index 8e73cf09c635..0529158104a5 100644 --- a/sys/fs/nwfs/nwfs_io.c +++ b/sys/fs/nwfs/nwfs_io.c @@ -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, ""); diff --git a/sys/fs/nwfs/nwfs_node.c b/sys/fs/nwfs/nwfs_node.c index 0700b76bb749..c708e1dc97a1 100644 --- a/sys/fs/nwfs/nwfs_node.c +++ b/sys/fs/nwfs/nwfs_node.c @@ -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, diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c index 3913f1aa8969..1033e8e39bc7 100644 --- a/sys/fs/smbfs/smbfs_io.c +++ b/sys/fs/smbfs/smbfs_io.c @@ -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, ""); diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c index 35be6a3763a1..cd8ffe9237e9 100644 --- a/sys/fs/smbfs/smbfs_node.c +++ b/sys/fs/smbfs/smbfs_node.c @@ -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 diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index fab3e298c02c..b4eec0985717 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -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 diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index de82774f7edc..4dd664bc6e78 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -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 diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 9698983feded..aa1fa74cd1fe 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -77,8 +77,6 @@ #include #include -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 @@ restart: * 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 @@ restart: /* 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; } } diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c index 80af2ab75faf..8902ca57c294 100644 --- a/sys/kern/kern_ktr.c +++ b/sys/kern/kern_ktr.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index affc1dc3fecc..abd7fdd9232d 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -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 @@ restart: 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 @@ restart: * 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 @@ restart: 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 @@ restart: } } - /* 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 @@ restart: } 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; } diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index b3bf555c4665..3256cfdb2357 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -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); /* diff --git a/sys/kern/link_aout.c b/sys/kern/link_aout.c index f9e45d747d57..1218e2293e76 100644 --- a/sys/kern/link_aout.c +++ b/sys/kern/link_aout.c @@ -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__ */ diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 32f45ce3ef48..da7462a86895 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -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; +} diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 32f45ce3ef48..da7462a86895 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -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; +} diff --git a/sys/kern/linker_if.m b/sys/kern/linker_if.m index 5f6f239eba5b..be84b9e18a2a 100644 --- a/sys/kern/linker_if.m +++ b/sys/kern/linker_if.m @@ -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. # diff --git a/sys/kern/tty_cons.c b/sys/kern/tty_cons.c index a40db4babf0e..478c7e9e64eb 100644 --- a/sys/kern/tty_cons.c +++ b/sys/kern/tty_cons.c @@ -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); diff --git a/sys/netncp/ncp_conn.c b/sys/netncp/ncp_conn.c index f1f6983db240..dc255f20ac25 100644 --- a/sys/netncp/ncp_conn.c +++ b/sys/netncp/ncp_conn.c @@ -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, ""); diff --git a/sys/netsmb/smb_conn.c b/sys/netsmb/smb_conn.c index 54f5c0b82879..1d56d8571c77 100644 --- a/sys/netsmb/smb_conn.c +++ b/sys/netsmb/smb_conn.c @@ -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"); diff --git a/sys/pc98/cbus/scgdcrndr.c b/sys/pc98/cbus/scgdcrndr.c index b37de738d11d..f1dcec51a390 100644 --- a/sys/pc98/cbus/scgdcrndr.c +++ b/sys/pc98/cbus/scgdcrndr.c @@ -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, diff --git a/sys/pc98/pc98/scgdcrndr.c b/sys/pc98/pc98/scgdcrndr.c index b37de738d11d..f1dcec51a390 100644 --- a/sys/pc98/pc98/scgdcrndr.c +++ b/sys/pc98/pc98/scgdcrndr.c @@ -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, diff --git a/sys/sys/cons.h b/sys/sys/cons.h index 48be3712d3c3..a99c21038162 100644 --- a/sys/sys/cons.h +++ b/sys/sys/cons.h @@ -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; diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 7e8ea63eaa4a..79c57e111bae 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -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 diff --git a/sys/sys/linker.h b/sys/sys/linker.h index 87a2a83df8cf..671bbe8fd315 100644 --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -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. diff --git a/sys/sys/linker_set.h b/sys/sys/linker_set.h index 2bffa9bfbdfe..0fa115f115e1 100644 --- a/sys/sys/linker_set.h +++ b/sys/sys/linker_set.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 1999 John D. Polstra + * Copyright (c) 1999,2001 Peter Wemm * 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_ */ diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index d43c89f80e01..1b6657ba24cd 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.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);