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
This commit is contained in:
Brian Feldman 2001-10-30 15:21:45 +00:00
parent 08d68dda08
commit bb9fe9dd9e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=85736
5 changed files with 88 additions and 0 deletions

View File

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

View File

@ -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 @@ link_elf_lookup_set(linker_file_t lf, const char *name,
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);
}

View File

@ -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 @@ link_elf_lookup_set(linker_file_t lf, const char *name,
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);
}

View File

@ -53,6 +53,16 @@ METHOD int search_symbol {
long* diffp;
};
#
# 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.

View File

@ -46,6 +46,7 @@ typedef TAILQ_HEAD(, linker_file) linker_file_list_t;
typedef caddr_t linker_sym_t; /* opaque symbol */
typedef c_caddr_t c_linker_sym_t; /* const opaque symbol */
typedef int (*linker_function_name_callback_t)(const char *, void *);
/*
* expanded out linker_sym_t