Я пытаюсь написать самоизменяющийся код на C и MIPS.
Поскольку я хочу изменить код позже, я пытаюсь написать настоящие машинные инструкции (в отличие от встроенной сборки) и пытаюсь выполнить эти инструкции. Кто-то сказал мне, что можно просто выделить часть памяти, записать туда инструкции, указать на нее указатель функции C и затем перейти к ней. (я привожу пример ниже)
Я пробовал это с помощью своего кросс-компилятора (инструментарий исходного кода), и он не работает (да, в ретроспективе я полагаю, что это кажется довольно наивным). Как я мог правильно это сделать?
#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);}
Здесь я следую соглашению о вызовах gcc, где аргументы передаются в $a0, а результаты функций должны быть в $v0. На самом деле я не знаю, будет ли адрес возврата помещен в $ra (но я пока не могу это проверить, так как не могу скомпилировать. Я использую int для своих инструкций, потому что я компилирую MIPS32 (отсюда 32-битный int должно хватить)
malloc
, в int. Достаточно ли для этого int? Почему бы не использовать правильный тип указателя? Кроме того, вы уверены, что ваш int имеет правильный размер для инструкции? - person amaurea   schedule 31.10.2012mprotect
и (2) вам может потребоваться очистить кеши инструкций и данных, если архитектура имеет отдельные кэши инструкций/данных, которые не являются согласованными. - person Dietrich Epp   schedule 31.10.2012jr
выполняет инструкцию из своего слота задержки перед передачей управления на целевой адрес (в данном случае$ra
). Вам нужна безопасная инструкция (например,nop
) в*(addone + 2)
. - person Alexey Frunze   schedule 12.10.2013