Reputation: 2797
I have an array of functions that have the same functionality:
func_pointer_t func_array[] = {func_1, func_2, func_3, ...};
I want to develop a program that traverses the array members and dumps the output to another .dat
data file. The output should have the following format:
func_1 func_1_output
func_2 func_2_output
func_3 func_3_output
...
So my question is - when traversing through the array members, how could we let the program know which function name the function pointer is pointing to (e.g. func_array[0]
is pointing to func_1
)?
Upvotes: 3
Views: 13783
Reputation: 365
There is a straightforward way in Linux using the DL library, if you have compiled your program with debug info. An example:
#include <iostream>
#include <dlfcn.h>
void test_fcn (int a, float b) { }
int main () {
Dl_info info;
dladdr (reinterpret_cast<void *>(&test_fcn), &info);
std::cout << info.dli_sname << std::endl;
}
info.dli_sname
contains the (mangled) function name: _Z4test_fcnif
in this case. You can also demangle the name:
#include <cxxabi.h>
...
std:: cout << abi::__cxa_demangle(info.dli_sname, NULL, NULL, NULL) << std::endl;
Upvotes: 5
Reputation: 382562
backtrace_symbols_fd
This is not perfect, but maybe it indicates a path. Adapted from How to get function's name from function's pointer in Linux kernel?
main.cpp
#include <execinfo.h>
#include <stdio.h>
#include <unistd.h>
void foo(void) {
printf("foo\n");
}
int main(int argc, char *argv[]) {
void *funptr = &foo;
backtrace_symbols_fd(&funptr, 1, STDOUT_FILENO);
printf("%p\n", foo);
return 0;
}
Compile and run:
g++ -std=c++11 main.cpp -rdynamic
./a.out
Output:
./a.out(_Z3foov+0x0)[0x562ff384893a]
0x562ff384893a
So we see the mangled name of foo
which is _Z3foov
was output:
echo _Z3foov | c++filt
The downsides of this which I don't know how to solve are:
-rdynamic
, and therefore does not work with static linking and likely has other downsidesBut I do think that looking into backtrace mechanisms is a good bet, and I have investigated them further at: print call stack in C or C++
Maybe we can also get away with debug information: Programmatically get debug information that might actually be the most stable approach if it were possible. But no one knows how to do it currently.
Tested in Ubuntu 18.04, GCC 7.4.0.
Upvotes: 1
Reputation: 41750
You can simply keep track of the name by storing an array of pair that will match the function pointer with its name:
std::pair<const char*, func_pointer_t>[] func_array = {
{"func_1", func_1},
{"func_2", func_2},
{"func_3", func_3}
};
You will now be able to use it's name too.
Is you want, you can even use a map:
std::map<std::string, func_ptr_t> func_array {
{"func_1", func_1},
{"func_2", func_2},
{"func_3", func_3}
};
Upvotes: 1
Reputation: 2514
There is no standard way of archiving what you seek. All possible solutions either involve system dependent ways to resolve function addresses to their names (and even that does not necessarily always work) or changing the func_array like so:
struct {
func_pointer_t func;
const char * name;
} func_array[] = {
{ func_1, "func_1" },
{ func_2, "func_2" },
{ func_3, "func_3" },
...
};
you can use a macro, to ease the job:
#define FUNC_DEF(func) { func, #func },
and then use it like this:
struct {
func_pointer_t func;
const char * name;
} func_array[] = {
FUNC_DEF(func_1)
FUNC_DEF(func_2)
FUNC_DEF(func_3)
...
};
So, if this is an option for you, you got your solution. If not, you gonna have to tell, what system you're targeting.
More C++ish solutions exist - like the std::map solutions hinted to by Govind Parmar where you could iterate and take the key <-> value pair.
Upvotes: 13
Reputation: 21532
You need to remember that at the assembly/machine code level there are no "function names" (unless you have debugging information in your build); there are only addresses that indicate where a function starts.
You will have to use a data structure to keep track of this stuff. If you're using C++, then use a map<string, function_pointer>
as commenter @MyUsername112358 pointed out.
Upvotes: 0