I'm trying to write some self modifying code in C and MIPS.
Since I want to modify the code later on, I'm trying to write actual machine instructions (as opposed to inline assembly) and am trying to execute those instructions. Someone told me that it would be possible to just malloc some memory, write the instructions there, point a C function pointer to it and then jump to it. (I include the example below)
I've tried this with my cross compiler (sourcery codebench toolchain) and it doesn't work (yes, in hind sight I suppose it does seem rather naive). How could I properly do this?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void inc(){
int i = 41;
uint32_t *addone = malloc(sizeof(*addone) * 2); //we malloc space for our asm function
*(addone) = 0x20820001; // this is addi $v0 $a0 1, which adds one to our arg (gcc calling con)
*(addone + 1) = 0x23e00000; //this is jr $ra
int (*f)(int x) = addone; //our function pointer
i = (*f)(i);
printf("%d",i);
}
int main(){
inc();
exit(0);}
I follow the gcc calling convention here, where the arguments are passed to $a0 and the results of the functions are expected to be in $v0. I don't actually know if the return address will be put into $ra (but I can't test it yet since I can't compile. I use int for my instructions because I'm compiling MIPS32(hence a 32 bit int should be enough)
mallocin an int. Is the int large enough for this? Why not use a proper pointer type? Also, are you sure that your int is the correct size for an instruction? - amaureamprotectand (2) you may need to flush the instruction and data caches if the architecture has separate instruction/data caches that aren't coherent. - Dietrich Eppjrexecutes an instruction from its delay slot before transferring control to the target address ($rain this case). You want a "safe" instruction (e.g.nop) at*(addone + 2). - Alexey Frunze