呼叫时的segfault,但不跳到rax中的地址
Segfault when calling, but not jumping to, address in rax
我正在使用类似汇编器的API(不是真的 可以发出机器代码),我正在调试和玩耍。它是专门用于系统v x86_64 abi的
由于某种原因,当我发出这样的人为代码时,用于测试目的
builder.emit_sub(rsp, 1);
builder.emit_movq_vr(reinterpret_cast<uint64_t>(&hello_world), rax);
builder.emit_call(rax);
builder.emit_add(rsp, 1);
builder.emit_ret();
在呼叫上发生分割故障(在运行时,不是在组装时),
builder.emit_movq_vr(reinterpret_cast<uint64_t>(&hello_world), rax);
builder.emit_jmp(rax);
成功。失败点似乎是在call
指令上,但是我不知道是什么在伪装。它可能会散发错误的操作数或其他内容,但我不确定。原始发射的计算机代码看起来像是这样的错误代码,以及它应该代表的opcode,如某些简单的调试语句所打印
sub 48 81 EC 01 00 00 00
movqvr 48 B8 63 80 AA 01 01 00 00 00
call FF D0
add 48 81 C4 01 00 00 00
ret C3
注释:movqvr
不是真正的指令[mnemonic];最后,vr
只是对我的调试注释,说这是一种"移动IMM64"指令。
注释:sub
和add
将在16字节边界上对齐堆栈,我认为这是此ABI的必要性。它们本可以更好地写成push rax
和pop rax
(如果需要rax
的返回值需要pop rcx
),但是请忽略,除非是这样会弄乱呼叫(例如,如果rsp
未正确修改))。
是的,在系统v ABI中,堆栈在每个call
指令之前都与16字节边界对齐。因此,在函数输入时,将需要另一个 8 bytes(而不是1)才能达到下一个16字节边界。请记住,在C中,指针差异由sizeof(type)
缩放,但在ASM中不是。
是的,push rax
/pop rcx
将是一个不错的选择,如果Clang/llvm不需要推动奇数的呼叫保存寄存器或保留任何额外的堆栈空间,则是Clang/LLVM所做的。如果您确实需要为当地人保留任何堆栈空间,请使用将使rsp
16字节对齐的偏移量。
顺便说一句,当立即拟合的8位值(即if ((int8_t)imm == imm)
)立即拟合时,您可以使用sub r/m64, imm8
编码来保存代码大小。另外,如果您需要添加/减去 128,请注意-128
适合IMM8,因此您可以add rsp, -128
(例如,在使用奇数push
指令之后)。
如果您知道代码将从何处运行的地址,则应使用call rel32
编码,而不是寄存器调用。但是您是对的,跳到任意的64位地址需要此mov r64, imm64
序列,而不是直接的call
。
您是否使用调试器来找出hello_world
在哪里崩溃了?也许如果它调用printf
(而不是puts
),则忘记了零al
(带有xor eax,eax
)表示XMM寄存器中没有FP ARG,因此也许Printf使用了一些16个字节的SSE SSE校准商店?
让RSP甚至没有qWord-cariged都非常糟糕,但是我不希望它崩溃了任何会崩溃的8个字节对齐(但不是16)。
- 将数组的地址分配给变量并删除
- 空基优化子对象的地址
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 如何在c++程序中找到函数的地址
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 被解释为低级别const的const对象的地址
- 将地址分配给本地指针后,公共对象的变量将消失
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 内联程序集printf将整数解释为地址
- 为什么指针不写入类的地址?
- 如何在C++中获取该对象的类声明中对象的地址?
- 通过按地址访问变量
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 函数名是c中该函数的第一条指令的地址吗
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- ReadProcessMemory() 不适用于像 0x2840C6C68D8 这样的长地址
- CUDA:统一内存和指针地址的更改
- 当我们从/tp地址中添加/减去一个整数时会发生什么
- 呼叫时的segfault,但不跳到rax中的地址