2010-12-16 47 views
10

我想在Android上進行一些自我修改的本機代碼並在模擬器中運行它。我的示例基於android-ndk的HelloJNI示例。它看起來像這樣: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

注意:如果實際修改代碼,您需要刷新指令緩存 - ARM上的I和D緩存不相干,因此,您可以在給定位置查看值的事實並不意味着CPU將在嘗試執行時看到它們。 Dalvik在其JIT編譯器實現中使用Linux cacheflush(2)。 – fadden 2010-12-17 00:40:11

回答

11

在猜測,nope()被編譯爲Thumb,但你稱它爲ARM(假設mmap返回一個字對齊的指針)。要調用Thumb代碼,應該設置地址的低位。嘗試是這樣的:

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

要正確地做到這一點,你應該確保分配的內存(2拇指和4 ARM)對齊,確保你想運行的代碼是拇指(或ARM)並相應地設置位0。

+0

謝謝。使用-marm選項編譯代碼併爲內存塊提供了適當的對齊後,我成功執行了代碼。 – 2010-12-17 10:29:26