Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Jul 2010 18:31:28 +0300
From:      Kostik Belousov <kostikbel@gmail.com>
To:        freebsd-hackers@freebsd.org
Subject:   Re: Kernel linker and undefined references in KLD
Message-ID:  <20100715153128.GW2381@deviant.kiev.zoral.com.ua>
In-Reply-To: <20100715143235.GU2381@deviant.kiev.zoral.com.ua>
References:  <AANLkTikhrbdbBEFl-I97nBzdvZx6qBaafDUsveRmYyp3@mail.gmail.com> <20100715143235.GU2381@deviant.kiev.zoral.com.ua>

next in thread | previous in thread | raw e-mail | index | archive | help

--ItroYk2LVxvwOvi/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Thu, Jul 15, 2010 at 05:32:35PM +0300, Kostik Belousov wrote:
> On Thu, Jul 15, 2010 at 06:07:36PM +0400, Dmitry Krivenok wrote:
> > Hello Hackers,
> >=20
> > I have a question about kernel linker.
> > Please take a look at an example of simple module:
> >=20
> > #######################################################################=
#####
> > #include <sys/param.h>
> > #include <sys/module.h>
> > #include <sys/kernel.h>
> > #include <sys/systm.h>
> > #include <sys/proc.h>
> > #include <sys/sched.h>
> > #include <sys/pcpu.h>
> >=20
> > /* DECLARING A FUNCTION JUST TO AVOID WARNING WHICH IS TREAT AS ERROR
> > BY DEFAULT */
> > void seltdinit(struct thread* t);
> >=20
> > static int event_handler(struct module *module, int event, void *arg)
> > {
> >   int e =3D 0;
> >   switch (event)
> >     {
> >       case MOD_LOAD:
> >         /* CALLING A FUNCTION DECLARED AS STATIC IN kern/sys_generic.c =
*/
> >         seltdinit(curthread);
> >         break;
> >       case MOD_QUIESCE:
> >         break;
> >       case MOD_UNLOAD:
> >         break;
> >       case MOD_SHUTDOWN:
> >         break;
> >       default:
> >         e =3D EOPNOTSUPP;
> >         break;
> >     }
> >=20
> >   return(e);
> > };
> > #######################################################################=
#####
> >=20
> > As you can see, this module calls seltdinit function declared as
> > _static_ in kern/sys_generic.c file.
> > I added a declaration of seltdinit function w/o static just to avoid
> > compilation error since -Werror is used
> > by default in FreeBSD.
> >=20
> > Then I successfully built the module:
> >=20
> > $ make
> > Warning: Object directory not changed from original
> > /usr/home/krived/work/freebsd/trouble
> > cc -O2 -pipe -fno-strict-aliasing -Werror -D_KERNEL -DKLD_MODULE
> > -nostdinc   -I. -I@ -I@/contrib/altq -finline-limit=3D8000 --param
> > inline-unit-growth=3D100 --param large-function-growth=3D1000 -fno-comm=
on
> > -fno-omit-frame-pointer  -mcmodel=3Dkernel -mno-red-zone  -mfpmath=3D387
> > -mno-sse -mno-sse2 -mno-sse3 -mno-mmx -mno-3dnow  -msoft-float
> > -fno-asynchronous-unwind-tables -ffreestanding -fstack-protector
> > -std=3Diso9899:1999 -fstack-protector -Wall -Wredundant-decls
> > -Wnested-externs -Wstrict-prototypes  -Wmissing-prototypes
> > -Wpointer-arith -Winline -Wcast-qual  -Wundef -Wno-pointer-sign
> > -fformat-extensions -c trouble.c
> > ld  -d -warn-common -r -d -o trouble.ko trouble.o
> > :> export_syms
> > awk -f /sys/conf/kmod_syms.awk trouble.ko  export_syms | xargs -J%
> > objcopy % trouble.ko
> > objcopy --strip-debug trouble.ko
> > $
> >=20
> > As expected, seltdinit symbol is undefined in trouble.ko file:
> > $ nm trouble.ko | grep seltdinit
> >                  U seltdinit
> > $
> > and is local in kernel binary file:
> > $ nm /boot/kernel/kernel | grep seltdinit
> > ffffffff805fda50 t seltdinit
> > $
> >=20
> > I expected to get something like "undefined reference to seltdinit"
> > error, but the module was loaded w/o any errors:
> >=20
> > $ sudo make load
> > /sbin/kldload -v /usr/home/krived/work/freebsd/trouble/trouble.ko
> > Loaded /usr/home/krived/work/freebsd/trouble/trouble.ko, id=3D2
> > $ kldstat | grep trouble
> >  2    1 0xffffffff81212000 126      trouble.ko
> > $ sudo make unload
> > /sbin/kldunload -v trouble.ko
> > Unloading trouble.ko, id=3D2
> > $
> >=20
> > Could you please explain why the linker (or whatever is loading
> > modules in FreeBSD) doesn't complain?
> >=20
> > For example, ld tool complains for the similar user-space example:
> >=20
> > #######################################################################=
#####
> > $ cat seltdinit.c
> > static void seltdinit(void* td)
> > {
> >   return;
> > }
> > $ cat main.c
> > void seltdinit(void* td);
> >=20
> > int main()
> > {
> >   seltdinit(0);
> >   return 0;
> > }
> > $ gcc -Wall -c seltdinit.c
> > seltdinit.c:2: warning: 'seltdinit' defined but not used
> > $ gcc -Wall -c main.c
> > $ gcc seltdinit.o main.o -o sel
> > main.o: In function `main':
> > main.c:(.text+0xa): undefined reference to `seltdinit'
> > collect2: ld returned 1 exit status
> > $
> > #######################################################################=
#####
> >=20
> > Thanks in advance!
> The kernel linker ignores weak attribute of the symbol, as you see.
> There is more bugs in this department, in regard of the list of
> exported symbols from the modules.
>=20
> I have a patch that fixes the issues, but I am leery to commit it, since
> the fix effectively breaks significant set of the modules.

Ok, below is the patch. I updated it to the latest HEAD, but did not
verified even the build.

diff --git a/sys/conf/kmod_syms.awk b/sys/conf/kmod_syms.awk
index 677d813..98940c6 100644
--- a/sys/conf/kmod_syms.awk
+++ b/sys/conf/kmod_syms.awk
@@ -12,7 +12,10 @@ BEGIN {
=20
 # De-list symbols from the export list.
 {
-        delete syms[$0]
+	split($0, exports)
+	for (member in exports) {
+		delete syms[$member]
+	}
 }
=20
 # Strip commons, make everything else local.
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index dd29302..f3da962 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -855,7 +855,7 @@ linker_debug_lookup(const char *symstr, c_linker_sym_t =
*sym)
 	linker_file_t lf;
=20
 	TAILQ_FOREACH(lf, &linker_files, link) {
-		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) =3D=3D 0)
+		if (LINKER_LOOKUP_DEBUG_SYMBOL(lf, symstr, sym) =3D=3D 0)
 			return (0);
 	}
 	return (ENOENT);
@@ -899,7 +899,7 @@ linker_debug_symbol_values(c_linker_sym_t sym, linker_s=
ymval_t *symval)
 	linker_file_t lf;
=20
 	TAILQ_FOREACH(lf, &linker_files, link) {
-		if (LINKER_SYMBOL_VALUES(lf, sym, symval) =3D=3D 0)
+		if (LINKER_DEBUG_SYMBOL_VALUES(lf, sym, symval) =3D=3D 0)
 			return (0);
 	}
 	return (ENOENT);
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index b389ace..f494fa5 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -127,25 +127,28 @@ typedef struct elf_file {
=20
 static int	link_elf_link_common_finish(linker_file_t);
 static int	link_elf_link_preload(linker_class_t cls,
-				      const char*, linker_file_t*);
+		    const char*, linker_file_t*);
 static int	link_elf_link_preload_finish(linker_file_t);
 static int	link_elf_load_file(linker_class_t, const char*, linker_file_t*);
 static int	link_elf_lookup_symbol(linker_file_t, const char*,
-				       c_linker_sym_t*);
-static int	link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_sy=
mval_t*);
+		    c_linker_sym_t*);
+static int	link_elf_lookup_debug_symbol(linker_file_t, const char*,
+		    c_linker_sym_t*);
+static int	link_elf_symbol_values(linker_file_t, c_linker_sym_t,
+		    linker_symval_t*);
+static int	link_elf_debug_symbol_values(linker_file_t, c_linker_sym_t,
+		    linker_symval_t*);
 static int	link_elf_search_symbol(linker_file_t, caddr_t value,
-				       c_linker_sym_t* sym, long* diffp);
+		    c_linker_sym_t* sym, long* diffp);
=20
 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 int	link_elf_each_function_name(linker_file_t,
-				int (*)(const char *, void *),
-				void *);
+		     int (*)(const char *, void *), void *);
 static int	link_elf_each_function_nameval(linker_file_t,
-				linker_function_nameval_callback_t,
-				void *);
+		     linker_function_nameval_callback_t, void *);
 static void	link_elf_reloc_local(linker_file_t);
 static long	link_elf_symtab_get(linker_file_t, const Elf_Sym **);
 static long	link_elf_strtab_get(linker_file_t, caddr_t *);
@@ -153,7 +156,9 @@ static Elf_Addr	elf_lookup(linker_file_t lf, Elf_Size s=
ymidx, int deps);
=20
 static kobj_method_t link_elf_methods[] =3D {
     KOBJMETHOD(linker_lookup_symbol,	link_elf_lookup_symbol),
+    KOBJMETHOD(linker_lookup_debug_symbol, link_elf_lookup_debug_symbol),
     KOBJMETHOD(linker_symbol_values,	link_elf_symbol_values),
+    KOBJMETHOD(linker_debug_symbol_values, link_elf_debug_symbol_values),
     KOBJMETHOD(linker_search_symbol,	link_elf_search_symbol),
     KOBJMETHOD(linker_unload,		link_elf_unload_file),
     KOBJMETHOD(linker_load_file,	link_elf_load_file),
@@ -1160,14 +1165,14 @@ elf_hash(const char *name)
 }
=20
 static int
-link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t*=
 sym)
+link_elf_lookup_symbol1(linker_file_t lf, const char* name, c_linker_sym_t=
* sym,
+    int see_local)
 {
     elf_file_t ef =3D (elf_file_t) lf;
     unsigned long symnum;
     const Elf_Sym* symp;
     const char *strp;
     unsigned long hash;
-    int i;
=20
     /* If we don't have a hash, bail. */
     if (ef->buckets =3D=3D NULL || ef->nbuckets =3D=3D 0) {
@@ -1194,60 +1199,101 @@ link_elf_lookup_symbol(linker_file_t lf, const cha=
r* name, c_linker_sym_t* sym)
 	strp =3D ef->strtab + symp->st_name;
=20
 	if (strcmp(name, strp) =3D=3D 0) {
-	    if (symp->st_shndx !=3D SHN_UNDEF ||
-		(symp->st_value !=3D 0 &&
-		 ELF_ST_TYPE(symp->st_info) =3D=3D STT_FUNC)) {
-		*sym =3D (c_linker_sym_t) symp;
-		return 0;
-	    } else
-		return ENOENT;
+		if (symp->st_shndx !=3D SHN_UNDEF ||
+		    (symp->st_value !=3D 0 &&
+		     ELF_ST_TYPE(symp->st_info) =3D=3D STT_FUNC)) {
+			if (see_local || ELF_ST_BIND(symp->st_info) !=3D STB_LOCAL) {
+				*sym =3D (c_linker_sym_t) symp;
+				return (0);
+			} else
+				return (ENOENT);
+		} else
+			return (ENOENT);
 	}
=20
 	symnum =3D ef->chains[symnum];
     }
=20
-    /* If we have not found it, look at the full table (if loaded) */
-    if (ef->symtab =3D=3D ef->ddbsymtab)
-	return ENOENT;
+    return (ENOENT);
+}
=20
-    /* Exhaustive search */
-    for (i =3D 0, symp =3D ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
-	strp =3D ef->ddbstrtab + symp->st_name;
-	if (strcmp(name, strp) =3D=3D 0) {
-	    if (symp->st_shndx !=3D SHN_UNDEF ||
-		(symp->st_value !=3D 0 &&
-		 ELF_ST_TYPE(symp->st_info) =3D=3D STT_FUNC)) {
-		*sym =3D (c_linker_sym_t) symp;
-		return 0;
-	    } else
-		return ENOENT;
+static int
+link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t*=
 sym)
+{
+
+	return (link_elf_lookup_symbol1(lf, name, sym, 0));
+}
+
+static int
+link_elf_lookup_debug_symbol(linker_file_t lf, const char *name,
+    c_linker_sym_t *sym)
+{
+	elf_file_t ef =3D (elf_file_t) lf;
+	const Elf_Sym* symp;
+	const char *strp;
+	int i;
+
+	if (link_elf_lookup_symbol1(lf, name, sym, 1) =3D=3D 0)
+		return (0);
+
+	for (i =3D 0, symp =3D ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
+		strp =3D ef->ddbstrtab + symp->st_name;
+		if (strcmp(name, strp) =3D=3D 0) {
+			if (symp->st_shndx !=3D SHN_UNDEF ||
+			    (symp->st_value !=3D 0 &&
+			     ELF_ST_TYPE(symp->st_info) =3D=3D STT_FUNC)) {
+				*sym =3D (c_linker_sym_t) symp;
+				return (0);
+			} else
+				return (ENOENT);
+		}
 	}
-    }
=20
-    return ENOENT;
+	return (ENOENT);
 }
=20
 static int
-link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval=
_t* symval)
+link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
+    linker_symval_t *symval, int see_local)
 {
 	elf_file_t ef =3D (elf_file_t) lf;
 	const Elf_Sym* es =3D (const Elf_Sym*) sym;
=20
 	if (es >=3D ef->symtab && es < (ef->symtab + ef->nchains)) {
-	    symval->name =3D ef->strtab + es->st_name;
-	    symval->value =3D (caddr_t) ef->address + es->st_value;
-	    symval->size =3D es->st_size;
-	    return 0;
+		if (!see_local && ELF_ST_BIND(es->st_info) =3D=3D STB_LOCAL)
+			return (ENOENT);
+		symval->name =3D ef->strtab + es->st_name;
+		symval->value =3D (caddr_t) ef->address + es->st_value;
+		symval->size =3D es->st_size;
+		return (0);
 	}
-	if (ef->symtab =3D=3D ef->ddbsymtab)
-	    return ENOENT;
+	return (ENOENT);
+}
+
+static int
+link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+    linker_symval_t *symval)
+{
+
+	return (link_elf_symbol_values1(lf, sym, symval, 0));
+}
+
+static int
+link_elf_debug_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+    linker_symval_t* symval)
+{
+	elf_file_t ef =3D (elf_file_t) lf;
+	const Elf_Sym* es =3D (const Elf_Sym*) sym;
+
+	if (link_elf_symbol_values1(lf, sym, symval, 1) =3D=3D 0)
+		return (0);
 	if (es >=3D ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
-	    symval->name =3D ef->ddbstrtab + es->st_name;
-	    symval->value =3D (caddr_t) ef->address + es->st_value;
-	    symval->size =3D es->st_size;
-	    return 0;
+		symval->name =3D ef->ddbstrtab + es->st_name;
+		symval->value =3D (caddr_t) ef->address + es->st_value;
+		symval->size =3D es->st_size;
+		return (0);
 	}
-	return ENOENT;
+	return (ENOENT);
 }
=20
 static int
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index a337fd0..ae8ea04 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -127,8 +127,12 @@ static int	link_elf_link_preload_finish(linker_file_t);
 static int	link_elf_load_file(linker_class_t, const char *, linker_file_t =
*);
 static int	link_elf_lookup_symbol(linker_file_t, const char *,
 		    c_linker_sym_t *);
+static int	link_elf_lookup_debug_symbol(linker_file_t, const char *,
+		    c_linker_sym_t *);
 static int	link_elf_symbol_values(linker_file_t, c_linker_sym_t,
 		    linker_symval_t *);
+static int	link_elf_debug_symbol_values(linker_file_t, c_linker_sym_t,
+		    linker_symval_t *);
 static int	link_elf_search_symbol(linker_file_t, caddr_t value,
 		    c_linker_sym_t *sym, long *diffp);
=20
@@ -148,7 +152,9 @@ static Elf_Addr elf_obj_lookup(linker_file_t lf, Elf_Si=
ze symidx, int deps);
=20
 static kobj_method_t link_elf_methods[] =3D {
 	KOBJMETHOD(linker_lookup_symbol,	link_elf_lookup_symbol),
+	KOBJMETHOD(linker_lookup_debug_symbol,	link_elf_lookup_debug_symbol),
 	KOBJMETHOD(linker_symbol_values,	link_elf_symbol_values),
+	KOBJMETHOD(linker_debug_symbol_values,	link_elf_debug_symbol_values),
 	KOBJMETHOD(linker_search_symbol,	link_elf_search_symbol),
 	KOBJMETHOD(linker_unload,		link_elf_unload_file),
 	KOBJMETHOD(linker_load_file,		link_elf_load_file),
@@ -1067,7 +1073,8 @@ relocate_file(elf_file_t ef)
 }
=20
 static int
-link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t =
*sym)
+link_elf_lookup_symbol1(linker_file_t lf, const char *name, c_linker_sym_t=
 *sym,
+    int see_local)
 {
 	elf_file_t ef =3D (elf_file_t) lf;
 	const Elf_Sym *symp;
@@ -1077,27 +1084,64 @@ link_elf_lookup_symbol(linker_file_t lf, const char=
 *name, c_linker_sym_t *sym)
 	for (i =3D 0, symp =3D ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
 		strp =3D ef->ddbstrtab + symp->st_name;
 		if (symp->st_shndx !=3D SHN_UNDEF && strcmp(name, strp) =3D=3D 0) {
-			*sym =3D (c_linker_sym_t) symp;
-			return 0;
+			if (see_local ||
+			    ELF_ST_BIND(symp->st_info) =3D=3D STB_GLOBAL) {
+				*sym =3D (c_linker_sym_t) symp;
+				return (0);
+			} else
+				return (ENOENT);
 		}
 	}
-	return ENOENT;
+	return (ENOENT);
 }
=20
 static int
-link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
-    linker_symval_t *symval)
+link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t =
*sym)
+{
+
+	return (link_elf_lookup_symbol1(lf, name, sym, 0));
+}
+
+static int
+link_elf_lookup_debug_symbol(linker_file_t lf, const char *name,
+    c_linker_sym_t *sym)
+{
+
+	return (link_elf_lookup_symbol1(lf, name, sym, 1));
+}
+
+static int
+link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
+    linker_symval_t *symval, int see_local)
 {
 	elf_file_t ef =3D (elf_file_t) lf;
 	const Elf_Sym *es =3D (const Elf_Sym*) sym;
=20
 	if (es >=3D ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
+		if (!see_local && ELF_ST_BIND(es->st_info) =3D=3D STB_LOCAL)
+			return (ENOENT);
 		symval->name =3D ef->ddbstrtab + es->st_name;
 		symval->value =3D (caddr_t)es->st_value;
 		symval->size =3D es->st_size;
-		return 0;
+		return (0);
 	}
-	return ENOENT;
+	return (ENOENT);
+}
+
+static int
+link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+    linker_symval_t *symval)
+{
+
+	return (link_elf_symbol_values1(lf, sym, symval, 0));
+}
+
+static int
+link_elf_debug_symbol_values(linker_file_t lf, c_linker_sym_t sym,
+    linker_symval_t *symval)
+{
+
+	return (link_elf_symbol_values1(lf, sym, symval, 1));
 }
=20
 static int
diff --git a/sys/kern/linker_if.m b/sys/kern/linker_if.m
index 3df592c..030e8eb 100644
--- a/sys/kern/linker_if.m
+++ b/sys/kern/linker_if.m
@@ -40,12 +40,24 @@ METHOD int lookup_symbol {
     c_linker_sym_t*	symp;
 };
=20
+METHOD int lookup_debug_symbol {
+    linker_file_t	file;
+    const char*		name;
+    c_linker_sym_t*	symp;
+};
+
 METHOD int symbol_values {
     linker_file_t	file;
     c_linker_sym_t	sym;
     linker_symval_t*	valp;
 };
=20
+METHOD int debug_symbol_values {
+    linker_file_t	file;
+    c_linker_sym_t	sym;
+    linker_symval_t*	valp;
+};
+
 METHOD int search_symbol {
     linker_file_t	file;
     caddr_t		value;
@@ -63,6 +75,12 @@ METHOD int each_function_name {
 	void*		opaque;
 };
=20
+METHOD int each_debug_function_name {
+	linker_file_t	file;
+	linker_function_name_callback_t	callback;
+	void*		opaque;
+};
+
 #
 # Call the callback with each specified function and it's value
 # defined in the file.
@@ -74,6 +92,12 @@ METHOD int each_function_nameval {
 	void*		opaque;
 };
=20
+METHOD int each_debug_function_nameval {
+	linker_file_t	file;
+	linker_function_nameval_callback_t	callback;
+	void*		opaque;
+};
+
 #
 # 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.
diff --git a/sys/modules/ata/atacore/Makefile b/sys/modules/ata/atacore/Mak=
efile
index 7b8d9e2..30a4ccb 100644
--- a/sys/modules/ata/atacore/Makefile
+++ b/sys/modules/ata/atacore/Makefile
@@ -6,4 +6,6 @@ KMOD=3D	ata
 SRCS=3D	ata-all.c ata-lowlevel.c ata-queue.c ata_if.c
 SRCS+=3D	opt_ata.h ata_if.h device_if.h bus_if.h
=20
+EXPORT_SYMS=3D	YES
+
 .include <bsd.kmod.mk>
diff --git a/sys/modules/mii/Makefile b/sys/modules/mii/Makefile
index 6232b5e..9740cf2 100644
--- a/sys/modules/mii/Makefile
+++ b/sys/modules/mii/Makefile
@@ -12,7 +12,11 @@ SRCS+=3D	rgephy.c rlphy.c ruephy.c tdkphy.c tlphy.c true=
phy.c ukphy.c
 SRCS+=3D	ukphy_subr.c
 SRCS+=3D	xmphy.c
=20
-EXPORT_SYMS=3D	mii_mediachg	\
+EXPORT_SYMS=3D	miibus_devclass	\
+		miibus_driver	\
+		miibus_readreg_desc \
+		miibus_writereg_desc \
+		mii_mediachg	\
 		mii_phy_probe	\
 		mii_phy_reset	\
 		mii_pollstat	\
diff --git a/sys/modules/pseudofs/Makefile b/sys/modules/pseudofs/Makefile
index d5696c5..ea7b112 100644
--- a/sys/modules/pseudofs/Makefile
+++ b/sys/modules/pseudofs/Makefile
@@ -11,6 +11,7 @@ SRCS=3D	opt_pseudofs.h \
 	pseudofs_vnops.c
=20
 EXPORT_SYMS=3D	pfs_mount	\
+		pfs_cmount	\
 		pfs_unmount	\
 		pfs_root	\
 		pfs_statfs	\

--ItroYk2LVxvwOvi/
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (FreeBSD)

iEYEARECAAYFAkw/Kc8ACgkQC3+MBN1Mb4iSpACbBe0l9Xy0cbXDidyeeaoEF+Q1
rfgAnjUtFmHLJc893selq/jjF6OJsyfq
=3Gwr
-----END PGP SIGNATURE-----

--ItroYk2LVxvwOvi/--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100715153128.GW2381>