Get a pointer to the current function in C (gcc)?

2019-01-18 05:22发布

问题:

is there a magic variable in gcc holding a pointer to the current function ?

I would like to have a kind of table containing for each function pointer a set of information.

I know there's a __func__ variable containing the name of the current function as a string but not as a function pointer.

This is not to call the function then but just to be used as an index.

EDIT Basically what i would like to do is being able to run nested functions just before the execution of the current function (and also capturing the return to perform some things.) Basically, this is like __cyg_profile_func_enter and __cyg_profile_func_exit (the instrumentation functions)... But the problem is that these instrumentation functions are global and not function-dedicated.

EDIT In the linux kernel, you can use unsigned long kallsyms_lookup_name(const char *name) from include/linux/kallsyms.h ... Note that the CONFIG_KALLSYMS option must be activated.

回答1:

Here's a trick that gets the address of the caller, it can probably be cleaned up a bit. Relies on a GCC extension for getting a label's value.

#include <stdio.h>

#define MKLABEL2(x) label ## x
#define MKLABEL(x) MKLABEL2(x)
#define CALLFOO do { MKLABEL(__LINE__): foo(&&MKLABEL(__LINE__));} while(0)

void foo(void *addr)
{
    printf("Caller address %p\n", addr);
}

int main(int argc, char **argv)
{
    CALLFOO;
    return 0;
}


回答2:

void f() {
   void (*fpointer)() = &f;
}


回答3:

#define FUNC_ADDR (dlsym(dlopen(NULL, RTLD_NOW), __func__))

And compile your program like

gcc -rdynamic -o foo foo.c -ldl


回答4:

I think you could build your table using strings (the function names) as keys, then look up by comparing with the __func__ builtin variable.

To enforce having a valid function name, you could use a macro that gets the function pointer, does some dummy operation with it (e.g. assigning it to a compatible function type temporary variable) to check that it's indeed a valid function identifier, and then stringifies (with #) the function name before being used as a key.

UPDATE:

What I mean is something like:

typedef struct {
  char[MAX_FUNC_NAME_LENGTH] func_name;
  //rest of the info here
} func_info;

func_info table[N_FUNCS];

#define CHECK_AND_GET_FUNC_NAME(f) ({void (*tmp)(int); tmp = f; #f})

void fill_it()
{
  int i = -1;
  strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(foo));
  strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(bar));
  //fill the rest
}

void lookup(char *name) {
  int i = -1;
  while(strcmp(name, table[++i]));
  //now i points to your entry, do whatever you need
}

void foo(int arg) {
  lookup(__func__);
  //do something
}

void bar(int arg) {
  lookup(__func__);
  //do something
}

(the code might need some fixes, I haven't tried to compile it, it's just to illustrate the idea)



回答5:

If you went for C++ the following information might help you:

Objects are typed, functors are functions wrapped as objects, RTTI allows the identification of type at runtime.

Functors carry a runtime overhead with them, and if this is a problem for you I would suggest hard-coding the knowledge using code-generation or leveraging a OO-heirarchy of functors.



回答6:

No, the function is not aware of itself. You will have to build the table you are talking about yourself, and then if you want a function to be aware of itself you will have to pass the index into the global table (or the pointer of the function) as a parameter.

Note: if you want to do this you should have a consistent naming scheme of the parameter.



回答7:

If you want to do this in a 'generic' way, then you should use the facilities you already mention (__cyg_profile_func*) since that is what they are designed for. Anything else will have to be as ad hoc as your profile.

Honestly, doing things the generic way (with a filter) is probably less error prone than any new method that you will insert on-the-fly.



回答8:

You can capture this information with setjmp(). Since it saves enough information to return to your current function, it must include that information in the provided jmp_buf.

This structure is highly nonportable, but you mention GCC explicitly so that's probably not a blocking issue. See this GCC/x86 example to get an idea how it roughly works.



回答9:

If you want to do code generation I would recomend GSLGen from Imatix. It uses XML to structure a model of your code and then a simple PHP like top-down generation language to spit out the code -- it has been used to generate C code.

I have personally been toying arround with lua to generate code.



回答10:

static const char * const cookie = __FUNCTION__;

__FUNCTION__ will be stored at the text segment at your binary and a pointer will always be unique and valid.



回答11:

Another option, if portability is not an issue, would be to tweak the GCC source-code... any volunteers?!



回答12:

If all you need is a unique identifier for each function, then at the start of every function, put this:

static const void * const cookie = &cookie;

The value of cookie is then guaranteed to be a value uniquely identifying that function.