2010-12-16 2 views
10

Я пытаюсь сделать собственный самонастраивающийся собственный код на Android и запустить его в эмуляторе. Мой образец основан на примере HelloJNI от android-ndk. Это выглядит так:Собственный самомодифицирующийся код на Android

#define NOPE_LENGTH 4 

typedef void (*FUNC) (void); 

// 00000be4 <nope>: 
//  be4: 46c0  nop   (mov r8, r8) 
//  be6: 4770  bx lr 
void nope(void) { 
    __asm__ __volatile__ ("nop"); 
} 

void execute(void){ 
    void *code = mmap(NULL, NOPE_LENGTH, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 

    if (code != MAP_FAILED) { 
     memcpy(code, nope, NOPE_LENGTH); 

     ((FUNC)code)(); 
    } 
} 

Проблема в том, что этот код сбой. Что не так?

+2

Примечание: если вы действительно изменяете код, необходимый для очистки кэша команд - кеши I и D на ARM не являются согласованными, поэтому факт, что вы можете видеть значения в определенном месте, не означает, что CPU увидит их при попытке выполнить. Dalvik использует Linux cacheflush (2) в реализации JIT-компилятора. – fadden 2010-12-17 00:40:11

ответ

11

В предположении, что nope() был скомпилирован как Thumb, но вы называете его ARM (при условии, что mmap возвращает указатель, выровненный по словам). Для вызова Thumb-кода должен быть установлен младший бит адреса. Попробуйте что-то вроде этого:

((FUNC)(((unsigned int)code)|1))(); 

Чтобы сделать это правильно, вы должны обеспечить выравнивание выделенной памяти (2 для большого пальца и 4 для ARM), убедитесь, что код, который вы пытаетесь запустить это Thumb (или ARM) и установить бит 0 соответственно.

+0

Спасибо. Скомпилировав код с параметром -marm и предоставив правильное выравнивание для блока памяти, я успешно выполнил код. – 2010-12-17 10:29:26

Смежные вопросы