summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2001-10-30 15:21:45 +0000
committergreen <green@FreeBSD.org>2001-10-30 15:21:45 +0000
commite44401b785a1fffb6524e85f215bd99bfc778bf1 (patch)
tree04f5856e0de49a87ff73562b3145a85347ee7bcc /sys/kern
parent8e31d7b2f43865c102269c5fe77a83fbc5fad376 (diff)
downloadFreeBSD-src-e44401b785a1fffb6524e85f215bd99bfc778bf1.zip
FreeBSD-src-e44401b785a1fffb6524e85f215bd99bfc778bf1.tar.gz
Add the sysctl "kern.function_list", which currently exports all
function symbols in the kernel in a list of C strings, with an extra nul-termination at the end. This sysctl requires addition of a new linker operation. Now, linker_file_t's need to respond to "each_function_name" to export their function symbols. Note that the sysctl doesn't currently allow distinguishing multiple symbols with the same name from different modules, but could quite easily without a change to the linker operation. This will be a nicety to have when it can be used. Obtained from: NAI Labs CBOSS project Funded by: DARPA
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_linker.c31
-rw-r--r--sys/kern/link_elf.c23
-rw-r--r--sys/kern/link_elf_obj.c23
-rw-r--r--sys/kern/linker_if.m10
4 files changed, 87 insertions, 0 deletions
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 353d811..7c2b59d 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -1702,3 +1702,34 @@ linker_load_dependancies(linker_file_t lf)
linker_addmodules(lf, start, stop, 0);
return error;
}
+
+static int
+sysctl_kern_function_list_iterate(const char *name, void *opaque)
+{
+ struct sysctl_req *req;
+
+ req = opaque;
+ return (SYSCTL_OUT(req, name, strlen(name) + 1));
+}
+
+/*
+ * Export a nul-separated, double-nul-terminated list of all function names
+ * in the kernel.
+ */
+static int
+sysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
+{
+ linker_file_t lf;
+ int error;
+
+ TAILQ_FOREACH(lf, &linker_files, link) {
+ error = LINKER_EACH_FUNCTION_NAME(lf,
+ sysctl_kern_function_list_iterate, req);
+ if (error)
+ return (error);
+ }
+ return (SYSCTL_OUT(req, "", 1));
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
+ NULL, 0, sysctl_kern_function_list, "", "kernel function list");
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index 888ce5e..5da9a83 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -113,6 +113,9 @@ 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 *);
static kobj_method_t link_elf_methods[] = {
KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
@@ -123,6 +126,7 @@ static kobj_method_t link_elf_methods[] = {
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),
+ KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
{ 0, 0 }
};
@@ -1149,3 +1153,22 @@ out:
free(setsym, M_LINKER);
return error;
}
+
+static int
+link_elf_each_function_name(linker_file_t file,
+ int (*callback)(const char *, void *), void *opaque) {
+ elf_file_t ef = (elf_file_t)file;
+ const Elf_Sym* symp;
+ int i, error;
+
+ /* Exhaustive search */
+ for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
+ if (symp->st_value != 0 &&
+ ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
+ error = callback(ef->ddbstrtab + symp->st_name, opaque);
+ if (error)
+ return (error);
+ }
+ }
+ return (0);
+}
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 888ce5e..5da9a83 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -113,6 +113,9 @@ 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 *);
static kobj_method_t link_elf_methods[] = {
KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
@@ -123,6 +126,7 @@ static kobj_method_t link_elf_methods[] = {
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),
+ KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
{ 0, 0 }
};
@@ -1149,3 +1153,22 @@ out:
free(setsym, M_LINKER);
return error;
}
+
+static int
+link_elf_each_function_name(linker_file_t file,
+ int (*callback)(const char *, void *), void *opaque) {
+ elf_file_t ef = (elf_file_t)file;
+ const Elf_Sym* symp;
+ int i, error;
+
+ /* Exhaustive search */
+ for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
+ if (symp->st_value != 0 &&
+ ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
+ error = callback(ef->ddbstrtab + symp->st_name, opaque);
+ if (error)
+ return (error);
+ }
+ }
+ return (0);
+}
diff --git a/sys/kern/linker_if.m b/sys/kern/linker_if.m
index be84b9e..9dafb57 100644
--- a/sys/kern/linker_if.m
+++ b/sys/kern/linker_if.m
@@ -54,6 +54,16 @@ METHOD int search_symbol {
};
#
+# Call the callback with each specified function defined in the file.
+# Stop and return the error if the callback returns an error.
+#
+METHOD int each_function_name {
+ linker_file_t file;
+ linker_function_name_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.
# "stop" points to the entry beyond the last valid entry.
OpenPOWER on IntegriCloud