views:

605

answers:

12

Hi,

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.

A: 

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.

Hassan Syed
+2  A: 
void f() {
   void (*fpointer)() = &f;
}
David Rodríguez - dribeas
yep , that's how you would hard code the information inside the function :D swings and roundabouts really. This solution is not as elegant as doing this work outside the function --- than that work can potentially be code generated.
Hassan Syed
:-D... I wanted something more generic...without knowing the name of f. a kind of generic line you could in any function ...
LB
@LB yep this solution is messy, generating out a framework is probably your best bet (but explain the problem further please).
Hassan Syed
With more info on what you are actually trying to achieve you could get alternatives.
David Rodríguez - dribeas
@LB Post some code in your question that illustrates what you would like your usage of such a feature (if it existed) to look like.
anon
I'm sorry I cannot post code as is..
LB
@LB, Neil is not asking to see your actual code, but a mock-up to illustrate what you would like to be able to do.
Trent
+1  A: 

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.

Hassan Syed
A: 

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.

caf
another trick hard coded inside the function rather then externally.
Hassan Syed
This will break if the compiler optimizes for space by giving two cookies the same address - given that the cookies are const, I am pretty sure this optimization would be allowed.
Justin Smith
I'm sure the compiler wouldn't -- two different objects must have addresses that compare non-equal.
ephemient
As ephemient points out, we prevent that optimisation when we take the address of the object. The only exception to the rule about distinct objects having unique addresses is string literals, which may be merged - but that is *explicitly* allowed.
caf
A: 

More of a question than an answer, but could you use ASM to look at the instruction pointer?

John
yep even if it's really ad hoc, i guess i could do it.
LB
That's going to be quite hard...
Stefano Borini
@Stefano, could you elaborate why ?
LB
That would be a hack, and you are going to have to write these hacks for every architecture you port to :D
Hassan Syed
How many architectures does code typically run on in real life? I'd hazard a guess most developers never write C/C++ that is run on anything other than x86.
John
because the instruction pointer will refer to the current executed instruction, not to the start of the function. If you put asm, the instruction pointer will refer to the current asm instruction. You will then have to backtrack the start of the function, which is hard if not impossible, and in any case highly fragile due to unpredictable compiler optimization strategies.
Stefano Borini
He just needs an index; no need to backtrack.
MSalters
listen if your going to try and track which function correspond with which instruction your hard-coding knowledge , if your going to hard-code knowledge why not use the other methods mentioned ? Methods that don't introduce a hack, such as the cookie (from caf) or the hard coded function dereference (david). I personally prefer some simple code generation though.
Hassan Syed
I'm not defending my approach as best. I personally wouldn't recommend it, it was only posted as an alternative. The cookie-based approach I'd use, probably combined with a macro for ease-of use.
John
ok, i didn't realize it would be so troublesome and so painful. Code generation is typically what i'm looking for.
LB
I have posted an answer about code generation.
Hassan Syed
A: 

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.

ezpz
sure, but there's no way to select a different behavior for different behavior and the instrument-functions flag is not something i want to turn everywhere...
LB
+1  A: 

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)

fortran
I'm not sure to understand what you mean. I may be wrong but __FUNC__ is a string (AFAIK this is not a preprocessor variable but part of the C standard) and node an identifier, this is equals to the name of the function with quotes. What is the macro that gets the function pointer ?
LB
@LB The preprocessor *is* part of the C standard. AFAIK `__FUNC__` is a preprocessor variable/macro, just as `__FILE__` and `__LINE__`. About getting the pointer, that is what my solution tries to avoid. I'll update the answer to make it clearer.
fortran
It's actually `__func__`, and unlike `__FILE__` and `__LINE__` it's a predefined identifier (not macro). It has to be done at the compiling stage rather than preprocessing, because the extent of a function (and therefore which one you're inside, if any) depends on the result of preprocessing.
caf
good to know, but there actually is a macro called `__FUNCTION__` that is what I meant... I got confused by reading `__func__` in the question. I'll update the answer.
fortran
Bear in mind that `__FUNCTION__` is an MSVC extension, whereas `__func__` is standard C.
caf
I'd swear that I used that in GCC once, but now you're making me doubt... I'll check it out... update: definitively it works with GCC too (tested with 4.4.1)
fortran
I don't understand why, but one of my previous comments was removed. To know more about \__FUNCTION__ go to : http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
LB
@LB good link, anyway, it doesn't make any difference here how is it implemented, the idea was about to get the table indexed by function name, whatever the means or keyword used. I'd update the answer though, to accommodate it better to the C99 standard (even the braced expression used in the check macro is a GCC extension).
fortran
A: 

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.

MSalters
+1  A: 
#define FUNC_ADDR (dlsym(dlopen(NULL, RTLD_NOW), __func__))

And compile your program like

gcc -rdynamic -o foo foo.c -ldl
qrdl
:-)... sneaky, but i fear that changing the compilation flag to include all the symbols + the inclusion of dlfcn.h, is not possible.
LB
A: 

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.

Hassan Syed
+1  A: 

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;
}
Hasturkun
Using `__builtin_return_address(0)` inside `foo()`, instead of passing the address of a label, is a simpler way of doing pretty much the same thing. (That gives the address of the instruction after the call to `foo()`, rather than the address of a constant load just before the call; but neither of those are the actual address of the function anyway...)
Matthew Slattery
@Matthew: That's so much nicer than this hack.
Hasturkun
A: 

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

John
I've done that, i want to avoid that.
LB