How to get function's name from function's pointer in Linux kernel?
I'm surprised why everybody says it is not possible. It is possible on Linux for non-static functions.
I know at least two ways to achieve this.
There are GNU functions for backtrace printing: backtrace()
and backtrace_symbols()
(See man
). In your case you don't need backtrace()
as you already have function pointer, you just pass it to backtrace_symbols()
.
Example (working code):
#include <stdio.h>
#include <execinfo.h>
void foo(void) {
printf("foo\n");
}
int main(int argc, char *argv[]) {
void *funptr = &foo;
backtrace_symbols_fd(&funptr, 1, 1);
return 0;
}
Compile with gcc test.c -rdynamic
Output: ./a.out(foo+0x0)[0x8048634]
It gives you binary name, function name, pointer offset from function start and pointer value so you can parse it.
Another way is to use dladdr()
(another extension), I guess print_backtrace()
uses dladdr()
. dladdr()
returns Dl_info
structure that has function name in dli_sname
field. I don't provide code example here but it is obvious - see man dladdr
for details.
NB! Both approaches require function to be non-static!
Well, there is one more way - use debug information using libdwarf
but it would require unstripped binary and not very easy to do so I don't recommend it.
That's not directly possible without additional assistance.
You could:
maintain a table in your program mapping function pointers to names
examine the executable's symbol table, if it has one.
The latter, however, is hard, and is not portable. The method will depend on the operating system's binary format (ELF, a.out, .exe, etc), and also on any relocation done by the linker.
EDIT: Since you've now explained what your real use case is, the answer is actually not that hard. The kernel symbol table is available in /proc/kallsyms
, and there's an API for accessing it:
#include <linux/kallsyms.h>
const char *kallsyms_lookup(unsigned long addr, unsigned long *symbolsize,
unsigned long *ofset, char **modname, char *namebuf)
void print_symbol(const char *fmt, unsigned long addr)
For simple debug purposes the latter will probably do exactly what you need - it takes the address, formats it, and sends it to printk
, or you can use printk
with the %pF
format specifier.
In the Linux kernel, you can use directly "%pF" format of printk !
void *func = &foo;
printk("func: %pF at address: %p\n", func, func);