Just out of curiosity I wonder if it is possible to relocate a piece of code during the execution of a program. For instance, I have a function and this function should be replaced in memory each time after it has been executed. One idea that came up our mind is to use self-modifying code to do that. According to some online resources, self-modifying code can be executed on Linux, but still I am not sure if such a dynamic relocation is possible. Has anyone experience with that?
Yes dynamic relocation is definitely possible. However, you have to make sure that the code is completely self-contained, or that it accesses globals/external functions by absolute references. If your code can be completely position independent, meaning the only references it makes are relative to itself, you're set. Otherwise you will need to do the fixups yourself at loading time.
With GCC, you can use -fpic
to generate position independent code. Passing -q
or --emit-relocs
to the linker will make it emit relocation information. The ELF specification (PDF link) has information about how to use that relocation information; if you're not using ELF, you'll have to find the appropriate documentation for your format.
If all these different functions exist at compile time then you could simply use a function pointer to keep track of the next one that is to be called. If you absolutely have to modify the function at runtime and that modification can't be done in place then you could also use a function pointer that is updated with address of the new function when it is created/loaded. The rest of your system would then call the self-modifying function through the function pointer and therefore doesn't have to know or care about the self-modifying code and you only have to do the fixup in one place.
As Carl says, it can be done, but you're opening a can of worms. In practice, the only people who take the trouble to do this are academics or malware authors (now donning my flame proof cloak).
You can copy some code into a malloc'd heap region, then call it via function pointers, but depending on the OS you may have to enable execution in the segment. You can try to copy some code into the code segment (taking care not to overwrite the following function), but the OS likely has made this segment read-only. You might want to look at the Linux kernel and see how it loads its modules.