Android 上的本地自修改代码

10

我正在尝试在Android上创建一些自修改的本地代码并在模拟器中运行它。 我的示例是基于android-ndk中的HelloJNI示例。 它看起来像这样:

#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
1个回答

11

猜测是nope()以Thumb模式编译,但你正在以ARM方式调用它(假设mmap返回字对齐指针)。要调用Thumb代码,地址的低位应该设置为1。尝试类似这样的操作:

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

若要正确执行此操作,您应确保分配的内存对齐(对于Thumb为2,对于ARM为4),确保您尝试运行的代码是Thumb(或ARM)并相应地设置位0。


谢谢。使用-marm选项编译代码并为内存块提供适当的对齐后,我成功地执行了代码。 - Иван

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接