2010-12-16 7 views
10

Ich versuche, einige selbstmodifizierenden nativen Code auf Android zu machen und es im Emulator ausführen. Mein Beispiel basiert auf dem HelloJNI-Beispiel von android-ndk. Es sieht so aus:Native selbstmodifizierenden Code auf 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)(); 
    } 
} 

Das Problem ist, dass dieser Code abstürzt. Was ist falsch?

+2

Hinweis: Wenn Sie den Code tatsächlich ändern, müssen Sie den Anweisungscache leeren - die I- und D-Caches auf ARM sind nicht kohärent, daher bedeutet die Tatsache, dass Sie Werte an einem bestimmten Speicherort sehen können, nicht die CPU werden sie sehen, wenn es versucht, auszuführen. Dalvik verwendet Linux cacheflush (2) in seiner JIT-Compilerimplementierung. – fadden

Antwort

11

Bei einer Schätzung wurde nope() als Thumb kompiliert, aber Sie nennen es als ARM (vorausgesetzt, mmap gibt einen wortausgerichteten Zeiger zurück). Um den Daumencode aufzurufen, sollte das Low-Bit der Adresse gesetzt werden. so etwas wie dieses versuchen:

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

es richtig zu machen, sollten Sie die Ausrichtung des zugewiesenen Speicher (2 für Daumen und 4 für ARM) zu gewährleisten, stellen Sie sicher, dass der Code Sie versuchen Thumb zu laufen (oder ARM) und setze das Bit 0 entsprechend.

+0

Danke. Nachdem ich den Code mit der Option -marm kompiliert und die richtige Ausrichtung für den Speicherblock bereitgestellt habe, habe ich den Code erfolgreich ausgeführt. –