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:
parent
08d68dda08
commit
bb9fe9dd9e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=85736
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user