Changing the address value of a function pointer [closed]

落爺英雄遲暮 提交于 2019-12-13 08:30:02

问题


I have the following code in C:

int addInt(int n, int m) {
    return n + m;
}

int (*functionPtr)(int, int);

functionPtr = &addInt;

functionPtr is a function pointer and it points to the specific address of the function addInt. I want to change 1 bit of its value, but I can't figure it out how.

Let's say functionPtr points to 0xABC0 (assuming a 16-bit address) after the last statement. I want to change its value to 0xABC1. I tried to OR the value with 0x1, but I guess that something is wrong with the operand conversion:

functionPtr = &addInt | 0x00000001; // addresses are of 32 bits

I know that messing around with pointers is risky, but I have to change the LSB of the address in order to enter into the Thumb state of an ARM Cortex-M4 MCU.


回答1:


To modify the value of a pointer via arithmetic operations, you would need to convert it to an integer type, perform the operation, and then convert it back. C does not define behavior for converting a function pointer to anything other than another function pointer, however, so there is no defined way to do that.

You might nevertheless write this:

typedef int (*fptr)(int, int);

functionPtr = (fptr)(((intptr_t) functionPtr) | 1);

The behavior you are looking for is one of the more plausible results, but again, the behavior of both casts is undefined. Therefore the behavior to be expected from performing a function call via the modified pointer -- if your program can even get that far -- is also undefined. The compiler is not required even to accept the code.




回答2:


Probably, it's a bad idea, but if you really need this, the following can do the trick:

functionPtr = &addInt;
*(int*)&functionPtr |= 1;

But note that this is no way portable, and may work or no work at all in your environment.




回答3:


Many mentioned that your approach is dangerous, but in some cases, this is a real issue, which I met more than once. I suspect that at the moment your code uses the BL instruction (branch and link) which does not change the mode of the CPU to thumb, in order to perform a call from ARM to thumb based on your function pointer, add the -mthumb-interwork flag to gcc when compiling your code:

Generate code that supports calling between the ARM and Thumb instruction sets. Without this option, on pre-v5 architectures, the two instruction sets cannot be reliably used inside one program. The default is -mno-thumb-interwork, since slightly larger code is generated when -mthumb-interwork is specified. In AAPCS configurations this option is meaningless.




回答4:


The function pointer format is architecture and implementation dependent.

For example, on Itanium, function pointers point to a read only data structure containing the appropriate global pointer for the module the function belongs to, and the actual function pointer.



来源:https://stackoverflow.com/questions/32975997/changing-the-address-value-of-a-function-pointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!