Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function pointer with GCC, assigning an address

I have encountered something I thoroughly don't understand. There is a function prototype:

typedef void ( * TMain ) ( void );

and a function variable:

TMain myFunc = MyFunc;
...
myFunc ();

This works fine, of course. Why should it not.

From the MAP-file I know that "MyFunc" is at location 0x20100. And now the funny thing. After the assignment "myFunc = MyFunc;" the variable "myFunc" does not contain the value 0x20100 but rather 0x20101!

My problem is, that I need to call a function of which I know the address from a table. So I thought I could do it like that

myFunc = ( TMain ) myTable [ 5 ];    // that would be 0x20100
myFunc ();                           // which produces a proper crash

However If I do

myFunc = ( TMain ) ( ( Int8 * ) myTable [ 5 ] + 1 );  
myFunc ();

then it works.

What happens here? Do I always have to add an offset of 1 or is this more or less accidental? Or is there a better (and working) way to accomplish the task?

Thanks a lot for any hint. Walter

like image 466
Walter Avatar asked Feb 01 '12 09:02

Walter


People also ask

How do you assign a pointer to a function?

int foo(int); Here foo is a function that returns int and takes one argument of int type. So as a logical guy will think, by putting a * operator between int and foo(int) should create a pointer to a function i.e. int * foo(int);

How do you declare a function pointer that takes an integer argument and returns a character?

Function Pointer Syntaxvoid (*foo)( int ); In this example, foo is a pointer to a function taking one argument, an integer, and that returns void. It's as if you're declaring a function called "*foo", which takes an int and returns void; now, if *foo is a function, then foo must be a pointer to a function.


1 Answers

My guess is you're on an ARM target and you've built your program in Thumb mode? (Thumb is default on ARM Ubuntu or Linaro.)

The bottom bit of a function's address tell the CPU in which instruction set it should interpret the function. 0 is ARM mode. 1 is Thumb mode. Thus all Thumb-mode function pointers will be odd.

Other architectures use this idiom also, in one way or another. Usually it safe to just zero the bottom two bits of an address (making it 4-byte aligned) and assume that that is the true location of the function.

like image 189
ams Avatar answered Oct 01 '22 02:10

ams