简体   繁体   English

在移动平台上执行自行生成的机器代码

[英]Executing self generated machine code on mobile platforms

There are a couple of questions already on SO assessing the possibility of executing self generated code. SO评估执行自生成代码的可能性已经有几个问题。 The generic answer is that it's possible, it's being done in JIT compilers and with dynamic library loading.一般的答案是它是可能的,它是在 JIT 编译器和动态库加载中完成的。

The application is in optimisation of sparse convolutions where the sparse structure should be embedded in the code, since skipping multiplication by zeros conditionally is slower than multiplying by zeros.应用程序用于优化稀疏卷积,其中稀疏结构应嵌入代码中,因为有条件地跳过乘以零比乘零慢。 Neither it's feasible in terms of performance to encode the structure in data:在性能方面对数据结构进行编码也是不可行的:

 do { // actually: don't do this
     auto offset = *encoded_offset++;
     auto coeff = *encoded_coefficient++;
     accum += data[offset] * coeff;
 } while (end_of_data);   // e.g. offset < 0, or offset == previous offset

Vs.比。

...
ldr     q5, [x1], 16   ; load data
fmla    v0.4s, v5.4s, v8.s[0]
fmla    v1.4s, v5.4s, v8.s[1]
fmla    v2.4s, v5.4s, v8.s[2]
// fmla    v3.4s, v5.4s, v8.s[3]   ; omitted, when |weight| < threshold
fmla    v4.4s, v5.4s, v8.s[3]      ; we reuse the v8.s[3] with a weight that matters
ldr     q5, [x1], 16
// fmla    v0.4s, v5.4s, v9.s[0] ; omitted, when |weight| < threshold
// fmla    v1.4s, v5.4s, v9.s[0] ; omitted
fmla    v2.4s, v5.4s, v9.s[0]    
fmla    v3.4s, v5.4s, v9.s[1]
fmla    v4.4s, v5.4s, v9.s[2]

; + several kilobytes of instructions

It's possible to generate the code by templates, but it would be far more efficient (and marginally more secure reverse engineering in mind) if the code was generated on the fly.可以通过模板生成代码,但如果代码是动态生成的,它会更有效(并且考虑到逆向工程的安全性)。

Now the question is, how to exactly call the generated function in some of the most important mobile ecosystems: Ios, android and possibly webassembly (using off course WASM (SIMD) bytecode).现在的问题是,如何在一些最重要的移动生态系统中准确调用生成的 function:Ios、android 和可能的 Web 程序集(使用非课程 WASM(SIMD)。

What exact system calls need to be issued to be able to execute the block of memory filled with the code -- legally?需要发出什么确切的系统调用才能合法地执行充满代码的 memory 块?

The only problem you will stumble upon is that "normal" memory is usually protected against execution.您会偶然发现的唯一问题是“正常” memory 通常受到保护以防止执行。 You just need to set on that memory the execute permission.您只需要在 memory 上设置执行权限。

After that you can set any sort of instructions you want.之后,您可以设置任何您想要的指令。 See for example the top fizzbuzz bandwidth winner, who uses a simple JIT machine.例如,请参阅使用简单 JIT 机器的顶级 fizzbuzz 带宽赢家。

https://codegolf.stackexchange.com/a/236630/108147 https://codegolf.stackexchange.com/a/236630/108147

But the basic code is this:但基本代码是这样的:

#include <string>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>

uint8_t code[] = { 0x89, 0xf8,       // mov eax, edi
                   0x0f, 0xaf, 0xc6, // imul eax, esi
                   0xc3 };           // ret

int main() {
    using multifn = int( int a, int b);
    size_t pagesize = getpagesize();
    size_t codesize = ((sizeof(code)-1)/pagesize+1)*pagesize;
    uint64_t codeaddr = uint64_t(code);
    codeaddr -= codeaddr % pagesize;
    mprotect((void*)codeaddr, codesize, PROT_READ | PROT_WRITE |PROT_EXEC);   
    multifn* m = reinterpret_cast<multifn*>(code);
    std::cout << "Result:" << m(2,3) << std::endl;
    return 0;
}

I just ran it in my Linux box as a regular user and the result is:我只是作为普通用户在我的 Linux 框中运行它,结果是:

Program stdout
Result:6

I assume that as Android is basically Linux, the result will be the same.我假设 Android 基本上是 Linux,结果将是相同的。 As per IOS I have to speculate here.根据 IOS 我必须在这里推测。

Also Godbolt: https://godbolt.org/z/hsMKWsjM9还有神栓: https://godbolt.org/z/hsMKWsjM9

If you are really picky about not messing up with regular memory, you can create a separate page for your generated code如果你真的很挑剔不搞乱常规的 memory,你可以为你生成的代码创建一个单独的页面

#include <string>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>

void* createExecPage( size_t size ) {
    size_t pagesize = getpagesize();
    size = ((size-1)/pagesize+1)*pagesize;
    std::cout << "Pagesize:" << pagesize << " size:" << size << std::endl;
    void* temp = nullptr;
    int res = posix_memalign(&temp, pagesize, size );
    if ( res!=0 ) {
        perror("posix_memalign");
    }
    res = mprotect(temp, size, PROT_READ | PROT_WRITE |PROT_EXEC);
    if ( res!=0 ) {
        perror( "mprotect" );
    }
    return temp;
}

uint8_t code[] = { 0x89, 0xf8,       // mov eax, edi
                   0x0f, 0xaf, 0xc6, // imul eax, esi
                   0xc3 };           // ret

int main()
{
    using multifn = int( int a, int b);
    void* xpage = createExecPage(sizeof(code));
    memcpy( xpage, code, sizeof(code));
    multifn* m = reinterpret_cast<multifn*>(xpage);
    std::cout << "Result:" << m(2,3) << std::endl;
    return 0;
}

https://godbolt.org/z/ebW76o1KP https://godbolt.org/z/ebW76o1KP

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM