Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.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
C 如何获取动态生成的X86_64以返回相对于RIP/RBP的值_C_Assembly_Code Generation_X86 64 - Fatal编程技术网

C 如何获取动态生成的X86_64以返回相对于RIP/RBP的值

C 如何获取动态生成的X86_64以返回相对于RIP/RBP的值,c,assembly,code-generation,x86-64,C,Assembly,Code Generation,X86 64,我正在尝试读取内存中与X86_64上的%rip相关的值。在我的第一个示例中,我只想阅读 如果我用C编写下面的代码,我可以调用它并得到正确的结果(\x….C3C9): 生成的代码如下所示: 0000000000400624 <test>: 400624: 55 push %rbp 400625: 48 89 e5 mov %rsp,%rbp 400628: 48 8b 05 00

我正在尝试读取内存中与X86_64上的
%rip
相关的值。在我的第一个示例中,我只想阅读

如果我用C编写下面的代码,我可以调用它并得到正确的结果(
\x….C3C9
):

生成的代码如下所示:

0000000000400624 <test>:
  400624:   55                      push   %rbp
  400625:   48 89 e5                mov    %rsp,%rbp
  400628:   48 8b 05 00 00 00 00    mov    0x0(%rip),%rax        # 40062f <test+0xb>
  40062f:   c9                      leaveq 
  400630:   c3                      retq 
我做错了什么

编辑 答案是,我不应该使用
malloc
而是
mmap
来分配页面对齐的内存区域:

(unsigned char*)mmap(NULL, 1024, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_SHARED, -1, 0);

当然,我应该检查调用
mprotect
的返回值。它返回-1标记它已失败。

在mprotect()调用期间,很可能会收到SIGSEGV。如果操作系统不允许执行malloc()返回的内存的代码(很可能是因为您没有使用某个古老的内核),那么mprotect()只会执行segfaults。这不是一个bug,而是一个特性。

ret指令基本上是堆栈中的一个
pop值;转到值

当您
goto
ret
最终被执行时,问题是堆栈上有垃圾(可能
ret
指令试图
goto 9
,因为codesize是堆栈顶部的变量,谁知道呢…)

基本上,它不起作用,因为您错误地使用了asm代码段

请问你想做什么?我可以帮忙:)


获取rip的测试程序:

static inline unsigned long get_rip(void)
{
    unsigned long val;
    asm volatile(
        "call 1f\n"
        "1: popq %0\n"
        : "=r"(val));
    return val;
}

int main()
{
    printf("rip = %p\n", (void *)get_rip());
    return 0;
}

m保护
将不会出现故障。实际上,它会成功,但如果不能成功,它将返回-1并设置
errno
。实际上,如果参数没有对齐页面,它将返回错误,而不是segfault。随后的代码出现了故障。是的,就我所知,这就是问题所在。我只是习惯于使用静态字符串而不是
malloc
ing,这似乎很管用。我猜静态字符串是页面对齐的,但malloced字符串不是。这个程序刚用gdb启动,在返回mprotect()后它会出现故障,即使我在mprotect()后填充了一些无害的代码。无论如何,mprotect()不应该与malloc()一起使用,而应该与mmap()一起使用。在这里,在执行
m保护后,它从未出现故障。我确实放了
printf
s。但是你是对的,我应该使用
mmap
:)我收到了一条评论,有人再次删除了他的评论,但是他把我引向了正确的方向。他说的
mprotect
失败是对的(愚蠢的我,我应该检查一下)。我猜
malloc
(显然)不会返回与页面边界对齐的内存。通过使用
(unsigned char*)mmap(NULL,1024,PROT_WRITE,PROT_READ,MAP_ANONYMOUS,MAP_SHARED,-1,0)它确实有效。如果您将
PROT_-EXEC
添加到
mmap
调用中,您就不需要
mprotect
。我没有这样做,因为我在某个地方读到一些内核不允许同时使用
PROT_-WRITE
PROT_-EXEC
。我误会了吗?嗯,也许是吧,虽然我会认为这是一个bug…为什么会有垃圾在堆栈上?当我转到
时,我还没有接触堆栈,所以我只是在运行它,就好像它直接在
函数中一样。我正在开发Smalltalk->ASM编译器(用Smalltalk编写),因为我想完全摆脱虚拟机。X86_64似乎是一个很好的起点。要学习的东西很多,但也很有趣:)发布了一个代码片段,向您展示如何获取rip值:)在
retq
之前的
leaveq
指令应该让堆栈指针指向
main()
的返回地址,假设
main()
使用了正常的函数序言。对,因为我的代码应该在代码中运行,所以我自己生成的序言将完全符合我的预期。例如,如果您开始在GCC中进行优化,这显然是行不通的。好提示;)
(unsigned char*)mmap(NULL, 1024, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
static inline unsigned long get_rip(void)
{
    unsigned long val;
    asm volatile(
        "call 1f\n"
        "1: popq %0\n"
        : "=r"(val));
    return val;
}

int main()
{
    printf("rip = %p\n", (void *)get_rip());
    return 0;
}