#1
  1. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12

    [c] get address of function


    hiyer,

    what line(s) do i need, to define a pointer to a function, and set that pointer to thefunction in this? :

    Code:
    #include <stdio.h>
    
    void thefunction(void)
    {
    	printf("hiyer\n");
    }
    
    main()
    {
    	/* define *fp to be a pointer to thefunction here somehow */
    	
    	printf("%p\n", fp);
    	
    	(*fp)();	/* call thefunction function via fp pointer? */
    
    }
    so the output i'm hoping for from that code is :
    Code:
    0x12345678
    hiyer
    where the 0x12345678 is thefunction's address

    so how to define a function pointer and set it to thefunction, and also is (*fp)(); the way to call a function from a function pointer?

    thanks.
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,593
    Rep Power
    4207
    Code:
    void (*fp)(void);
    fp = thefunction;
    
    printf("%p\n", fp);
    (*fp)();
    HTH :)
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    balance, please also note that a function pointer is only valid for the parameter list it's declared with, so your example with the void parameter list cannot be used with a function that expects an int. I'm sure that this goes for return types as well, but I haven't played with that part of it yet.

    Also, you can typedef particular types of function pointers; eg:
    Code:
    typedef void (*APF)(unsigned char *);   // ptr to funct with pointer parameter
    typedef void (*PF)(void);               // ptr to funct
    typedef void (interrupt __far *PFI)(void);  // ptr to interrupt
    typedef void (far *cmdPF)(int,char *);      // ptr to funct with (int,*char)
  6. #4
  7. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12

    caller's address


    HTH :)
    certainly does. thanks s4e :)

    oddly to me, the printed address is 0x1d0c. why a 16bit address not a 32bit one, when it's a 32bit machine?

    further, more tricky question: in c, is it possible to get the address that will be returned to, without making previous provisions to do so (like passing an address to this function) into a variable?

    example to explain what i mean:
    Code:
    void functiontwo()
    {
    	/* here */
    	return;
    }
    
    
    main()
    {
    	functiontwo();
    	return 0;
    }
    so only adding code in where marked /* here */, or at least only modifying functiontwo, not main, is it possible to get the address that the return will return to, before actually returning?

    (i've got a feeling it's something that assembly language would do well? link register/stack etc i think. thing is, once you put asm in, that's a function in itself right? so then you'd need to know 2 returns back in order to get the return to main's address?)


    i'm thinking of this from an oop point of view. i'd like to somehow always easily/automatically know which object did the calling, without making provisions in the calling object - like passing on it's address.

    the whole idea is flawed becuase the address of a function, and the address that'll be returned to are two different addresses (the return address will be some way past the function's address), but i'd still really like to know if the above is possible.

    thanks.
  8. #5
  9. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    i was reading your last post and started to do some experimenting, hopefully it is helpful to you, if not then ignore my ramblings...:)

    when a function is called, there are always a few steps that happen every time, no matter what. First, the return address of the function is pushed onto the stack, then the function is called, inside the function, the current %ebp(stack base pointer) is saved by being pushed onto the stack, then %esp(stack top pointer) is moved into %ebp. %esp is decremented to create a local frame for the functions local variables. These steps always happen when a function is called. So using this, i figured one way to calc the return address is like this:
    Code:
    #include <stdio.h>
    
    int get_esp(){  asm("mov %esp, %eax");  };
    int func()
    {
            int a = get_esp();
            int x = 4;
            // offset = size of local frame + (number of previous push'es * 4)
            printf("return is %x\n", (a + (sizeof(int) * 2) + ( 3 * 4) ) );
            return x;
    };
    
    void main()
    {
            int m = func();
    }
    -basically, the first thing you do is get the current esp. Then to find the offset of where the return address is stored you do this:
    offset = current esp + 4(from return to main being pushed) + 4(from ebp being pushed) + 4(from calling function get_esp and pushing that return) + 8(size of local stack frame which is the sum of the local variable sizes). all that adds up to an offset of 20, or 0x14 in hex.
    Last edited by infamous41md; July 5th, 2003 at 03:30 PM.
  10. #6
  11. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    also note that a function pointer is only valid for the parameter list it's declared with
    right. got ya. thanks.
    ________________________

    yeah i thought it'd be possible to get the immediate return address using assembly although i started to think of further problems because i thought using assembly would mean calling a function in itself, so to get the required return address you'd have to get the 2nd from last return address off the stack rather than the last. but it looks like from what you're saying and doing you can get any one want as there's a stack of addresses. a pointer to the base of it. and the number that are on it.

    unfortunately your code isn't working for me, because i'm on a powerpc which is incompatible with the type of assembly you've done there i think.

    i'm going to have a look to see if it'd be fairly easy to convert what you've done to ppc. just had a look at some ppc assembly stuff. there's a whole array of moves - mov being the first incompatability that my compiler picked up.

    thanks a lot
    Last edited by balance; July 5th, 2003 at 06:22 PM.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    56
    Rep Power
    11
    I was under the assumption that anything inside asm just gets passed directly as is, that it's basically a pass through that is read by the compiler. Not really a function.

    You've kind of got the notion of esp/ebp. ebp is your starting point for any variables that are sent to a function. You can access these variables by [ebp+4] for the first variable [ebp+8] for the second, etc. Since the stack pointer is changing always depending on pushes it is about the only way to reliably get these variables. Alternatively you could use ebp to access the IP (instruction pointer) by going above it. I believe you can also access labels as well.

    The command mov edx, myfunc would actually put the address of myfunc into edx. I believe it is more or less the location of the code in memory.

    (edit: sorry, using intel spec asm instead of att)
    mov %myfunc, %edx would be similar for att.
  14. #8
  15. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    i figured out another way as well, just declare an integer pointer as the first local variable and assign it to its own address, and then increment it by 2 and dereference it.
    Code:
    #include <stdio.h>
    
    void func()
    {
            int *x_ptr = &x_ptr;;
    
            x_ptr += 2;
            printf("x_ptr points @ %x\n", *x_ptr);
    }
    
    void main(int argc, char **argv)
    {               func(); }
  16. #9
  17. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    I was under the assumption that anything inside asm just gets passed directly as is, that it's basically a pass through that is read by the compiler. Not really a function.
    in line assembly has the hall marks of a function call though: asm(...); but maybe you're right. but it does look perfectly possible to look further back on the stack than the last one, so its not too important for this anyway.


    int *x_ptr = &x_ptr;
    x_ptr += 2;
    you can't do that can you ?! :) well, i can't. not with my compiler.



    i'd really like to have this confirmed please: i'm pretty sure it is the case, and this is a silly question, but just want to be absolutely sure:

    the return address, and the address of the function (that contained the function call), are two different addresses?

    so...

    Code:
    void calleefunction(void)
    {
    	// ...when here, the address on the stack points to around /*2*/, not /*1*/ ?
    	return;
    }
    
    /*1*/void callingfunction(void)
    {
    	// blah
    	// blah
    	// blah
    	calleefunction();
    	/*2*/
    }
    and there's no info in the stack so far as which function did the calling, just the return address? and there's no other seperate, different kind of stack, or calling function info attached to the stack? (!) ( :/ i dunno know, just checking)

    thanks :)
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    56
    Rep Power
    11
    Yes, the address on the stack (the instruction pointer) points to 2. Where it last left off before getting called. There may be some way to get the location of the calling function, but I'm uncertain. Someone else may know.
  20. #11
  21. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    i *knew* it was pointing to /*2*/ as i was asking :) wishful thinking. thanks v.much for confirming.


    found something about playing with the stack here : http://www.codeproject.com/tips/stac...asp?print=true

    "...The class StackDumper has a method that browses the thread's stack and allows you to save in a text file the names (or addresses in the worst case) of all functions executed before the foo is called... "

    haven't read it yet. it's in c++ unfortunately for me, but looks like its laden with useful info for the type of thing i'm on about.

IMN logo majestic logo threadwatch logo seochat tools logo