Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用memcpy的内联线程分派_C_Inline_Interpreter_Mmap_Memcpy - Fatal编程技术网

使用memcpy的内联线程分派

使用memcpy的内联线程分派,c,inline,interpreter,mmap,memcpy,C,Inline,Interpreter,Mmap,Memcpy,我正在测试一种称为的解释器分派技术,我似乎无法在没有分段错误的情况下分支到可执行内存。我使用GCC的扩展来确定每个操作码跨度的开始和结束 test.c: #include <string.h> #include <unistd.h> #include <sys/mman.h> int main (int argc, char** argv) { int i = 0; if (argc > 0x10) { // prevent opt

我正在测试一种称为的解释器分派技术,我似乎无法在没有分段错误的情况下分支到可执行内存。我使用GCC的扩展来确定每个操作码跨度的开始和结束

test.c:

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

int main (int argc, char** argv) {

  int i = 0;

  if (argc > 0x10) {
    // prevent optimization 
    inc_start: i++; inc_end:;
    ret_start: goto end; ret_end:;
  }

  void* m = mmap(
    0,  
    getpagesize(),
    PROT_WRITE | PROT_EXEC,
    MAP_ANONYMOUS | MAP_PRIVATE,
    -1, 
    0); 

  if (!m) {
    return -1; 
  }

  {
    char* x = m;
    memcpy(x, &&inc_start, &&inc_end - &&inc_start); x += &&inc_end - &&inc_start;
    memcpy(x, &&inc_start, &&inc_end - &&inc_start); x += &&inc_end - &&inc_start;
    memcpy(x, &&ret_start, &&ret_end - &&ret_start); x += &&ret_end - &&ret_start;
  }

  goto *m; 

  end:
  return i;
}
gcc test.c -O0 && ./a.out; echo $?
gcc test.c -O3 && ./a.out; echo $?
2
我希望main返回2,但是:

Segmentation fault
139
我在64位linux机器上使用GCC4.7.2进行编译,我相信没有任何东西会被优化掉。关于如何让它工作,有什么建议吗

对x86_64和aarch64使用GCC,I来消除相对寻址和相对跳转问题。在检查生成的程序集之后,我还重新构造了标签,因为引入了不需要的跳转。此后,我使用针对x86_64-linux-gnu的gcc版本4.8.4和针对AARC64 linux android的gcc版本6.1.0编译了它,两者都产生了2的预期结果

// gcc test.c -O3 && ./a.out; echo $?
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>

#if defined(__amd64__) || defined(__x86_64__) 
register long i asm ("r15");
#elif defined(__arch64__)
register long i asm ("x16");
#else
#error Unsupported architecture. Supported: x86_64, aarch64
#endif
long main (int argc, char** argv) {
  i = 0;

  void* m = mmap(0,  getpagesize(),
                 PROT_WRITE | PROT_EXEC,
                 MAP_ANONYMOUS | MAP_PRIVATE,
                 -1, 0);

  if (!m) {
    return -1;
  }

  {
    char* x = m;
    memcpy(x, &&L00, &&L01 - &&L00); x += &&L01 - &&L00; // inc
    memcpy(x, &&L00, &&L01 - &&L00); x += &&L01 - &&L00; // inc
    memcpy(x, &&L01, &&L02 - &&L01); x += &&L02 - &&L01; // ret
  }

  goto *m;

  L00: i++;      // inc
  L01: return i; // ret
  L02:;

  return -2;
}

我将继续寻找一种不涉及将变量显式固定到寄存器的解决方案。

Youir代码不是标准的C代码,会调用未定义的行为。您的问题是什么?您是否将标签称为“值”链接?是的,它不是标准的,但大多数C编译器都支持该扩展。本白皮书的作者是如何实现内联线程调度的?请参考图2。我不会这样做,因为这是一种错误的方法,并且有充分的理由不允许这样做。我不是来教你的,只是告诉过你。(不,大多数编译器都不支持它!除了gcc、msvc和clang/llvm之外,还有更多。你根本无法复制/粘贴一些可执行代码并期望它工作。例如,代码中的
goto end;
?这可能是一个相对的跳跃。你可以考虑一下这对你的方法来说意味着什么问题来了,继续,我们等着。