[comp.lang.c] How do I get the address of the current function?

writer@me.utoronto.ca (Tim Writer) (06/29/90)

This is a question that has puzzled me for some time.  It may be more
appropriate in comp.unix.wizards but I thought I'd try my luck here first.

Is there a way to get the address of the function which is currently
executing?  For example:

char	*fcn;

void
foo()
{
	...

	fcn=current_function();

	... do something with fcn
}

You may ask why?  Or why not just "fcn=(char *) foo"?  I am using setjmp()
and longjmp() to do some error handling.  When I use longjmp() it may jump
out of the current function or it may not.  Sometimes I want to jump back
to where I used longjmp().  I do this with another setjmp(), longjmp() pair.
However,  I can only do the second longjmp() if the first remained within
the current function.  In short, I am trying to discern if a longjmp()
would jump into a function that has already returned.  I thought that a
function like current_function() would be helpful.

On some systems, if longjmp() encounters a problem, it calls a user
definable function, longjmperror().  Mine doesn't.

If someone has a solution to this longjmp() problem which doesn't involve
something like current_function(), I'd be happy to hear from you.  But, I'd
still like to know if it is possible to do something like
current_function().

Thanks in advance.

Tim

P.S I'm using a sparcStation running Sun 4.0.

diamond@tkou02.enet.dec.com (diamond@tkovoa) (06/29/90)

In article <90Jun28.195353edt.19442@me.utoronto.ca> writer@me.utoronto.ca (Tim Writer) writes:

>Is there a way to get the address of the function which is currently
>executing?

If you know the name of the function, if it is foo, you just say &foo

>char	*fcn;
>void foo() {
>	fcn=current_function();
>}

Your compiler might or might not let you convert a function pointer to a
char pointer.  If it lets you, the result might or might not be usable.
And if you can convert back, it might again be unusable.  Safer is:
void (*fcn)();
void foo() {
	fcn = &foo;
}
-- 
Norman Diamond, Nihon DEC     diamond@tkou02.enet.dec.com
This is me speaking.  If you want to hear the company speak, you need DECtalk.

writer@me.utoronto.ca (Tim Writer) (06/29/90)

In article <1823@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com (diamond@tkovoa) writes:

>In article <90Jun28.195353edt.19442@me.utoronto.ca> writer@me.utoronto.ca (Tim Writer) writes:

>If you know the name of the function, if it is foo, you just say &foo

I don't want to need to know the name of the function.

>void (*fcn)();
>void foo() {
>	fcn = &foo;
>}

Actually, it would just be `fcn=foo'.

As I feared, you misunderstood me.  I want to *compute* the address of the
currently executing function.  In other words, I want the computer to tell
me what is the address of the function it is executing.

Consider the following pseudocode.

     1	jmp_buf	buf1,
     2		buf2,
     3		buf3;
     4	
     5	main()
     6	{
     7		if (setjmp(buf1)) {
     8			... stuff ...
     9			longjmp(buf3,1);
    10		}
    11		... stuff ...
    12		fcn()
    13		... stuff ...
    14	}
    15	
    16	fcn()
    17	{
    18		if (setjmp(buf2)) {
    19			... stuff ...
    20			longjmp(buf3,1);
    21		}
    22		... stuff ...
    23		if (... condition ...) {
    24			void setjmp(buf3);
    25			longjmp(... buf1 or buf2, I don't know ...,1)
    26		}
    27		... stuff ...
    28	}

Longjmp() on line 25 may jump to line 19, or it may jump to line 8; I don't
know which.  If it jumps to line 19, longjmp() on line 19 is fine.  However,
if it jumps to 8, the longjmp() on line 9 would be jumping into fcn() which
has returned.  The problem is how to detect this.

I have a written a fairly general exception handling facility which includes
several macros which generate code similar to the above.  That is why
I don't know where the longjmp() of line 25 is going to jump to.  When I use
these macros I want them to be able to detect a bad longjmp() without needing
to pass them extra arguments which differ from function to function.

I figured if there was a way to compute the address of the currently
executing function, I could have my macros set and examine a global function
pointer.  So, before line 25, I would set it, and I would check it against
the address of the currently executing function before lines 9 and 20.
That way, I could tell where the longjmp() was going to go.

I hope this makes things a bit more clear.

Any suggestions?

Tim

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/29/90)

In article <90Jun29.013400edt.20194@me.utoronto.ca>, writer@me.utoronto.ca (Tim Writer) writes:
> As I feared, you misunderstood me.  I want to *compute* the address of the
> currently executing function.  In other words, I want the computer to tell
> me what is the address of the function it is executing.

The things you are guaranteed about function pointers are
	(1) every function has a definite unique "address" which is not NULL
	(2) "all function pointers smell the same"
	(3) given the address of a function, you can call it.
That's about it.  In particular, there is no reason to expect the
"function address" used by C to be or to resemble any hardware address
within the machine code generated for the function.  C's "function pointer"
might be any of the following:
	(a) An address near the beginning of the machine code
	(b) An address near the end of the machine code
	(c) An index into an array of addresses or ECBs
	(d) The (data) address of an Entry Control Block (Apollo, PR1ME)
	(e) The address of an instruction which is initially a trap, and
	    then gets overwritten by a jump to dynamically loaded code
	(f) The address of a location somewhere in the literal pool for
	    a function (IBM RT PC)
	...
If the C compiler you're using goes in for literal pools, you may be
in luck.  The address of the literal pool is likely to be around in a
register.  I don't know whether SPARC compilers do this.

It's important to realise that you have *two* problems:
-- how does this COMPILER represent a function pointer?
-- how do I get one of those at run-time on this HARWARE?

-- 
"private morality" is an oxymoron, like "peaceful war".

cspw@quagga.uucp (Peter Wentworth) (07/03/90)

I solved a similar problem by using a macro expansion to generate
the function headings:  in my case all the routines had the same
prototypes, and I was generating the C code automatically from 
another compiler.  As part of the macro expansion you can
'undef' a compile time name, say CURR_FN, and redefine it.

The expanded code for every function looked something like this

#undef CURR_FN
#define CURR_FN   f
void f(...)
{
    use the address of CURR_FN as    &CURR_FN
}  

This is a horrible work-around, but it worked nicely for cases when
I was generating the function bodies automatically.  I don't believe
there is any way to directly reference the current function without
using its name.

Pete 
-- 
EP Wentworth - Dept. of Computer Science - Rhodes University - Grahamstown.
Internet: cspw.quagga@f4.n494.z5.fidonet.org          
Uninet: cspw@quagga      
uucp: ..uunet!m2xenix!quagga!cspw