Linux 获取 x86 的当前指令地址
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7932287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get address of current instruction for x86
提问by MetallicPriest
I am using Linux with x86 (64 bit to be precise). Is there a way I can get the address of the current instruction. Actually I want to write my own simplified versions of setjmp/longjmp. Here, R.. posted a simplified version of longjmp. Any idea how setjmpis implemented. A simplified version that is, without taking into account of exceptions and signals etc...
我在 x86(准确地说是 64 位)上使用 Linux。有没有办法获得当前指令的地址。其实我想编写我自己的setjmp/longjmp的简化版本。在这里,R.. 发布了longjmp的简化版本。任何想法setjmp是如何实现的。一个简化版本,即不考虑异常和信号等...
采纳答案by NPE
I believe in 64-bit code you can simply do lea rax, [rip]
.
我相信 64 位代码你可以简单地做lea rax, [rip]
。
The 32-bit idiom is:
32 位的习惯用法是:
call next
next: pop eax
回答by MetallicPriest
Thissite gives a simple version of setjmp and longjmp, which is as follows.
该网站提供了一个简单的版本setjmp和longjmp的,这是如下。
#include "setjmp.h"
#define OFS_EBP 0
#define OFS_EBX 4
#define OFS_EDI 8
#define OFS_ESI 12
#define OFS_ESP 16
#define OFS_EIP 20
__declspec(naked) int setjmp(jmp_buf env)
{
__asm
{
mov edx, 4[esp] // Get jmp_buf pointer
mov eax, [esp] // Save EIP
mov OFS_EIP[edx], eax
mov OFS_EBP[edx], ebp // Save EBP, EBX, EDI, ESI, and ESP
mov OFS_EBX[edx], ebx
mov OFS_EDI[edx], edi
mov OFS_ESI[edx], esi
mov OFS_ESP[edx], esp
xor eax, eax // Return 0
ret
}
}
__declspec(naked) void longjmp(jmp_buf env, int value)
{
__asm
{
mov edx, 4[esp] // Get jmp_buf pointer
mov eax, 8[esp] // Get return value (eax)
mov esp, OFS_ESP[edx] // Switch to new stack position
mov ebx, OFS_EIP[edx] // Get new EIP value and set as return address
mov [esp], ebx
mov ebp, OFS_EBP[edx] // Restore EBP, EBX, EDI, and ESI
mov ebx, OFS_EBX[edx]
mov edi, OFS_EDI[edx]
mov esi, OFS_ESI[edx]
ret
}
}
回答by BlueRaja - Danny Pflughoeft
The offset-into-the-current-segment register (EIP
) is not normally accessible. However, there is a hackish-way to read it indirectly - you trick the program into pushing the value of EIP onto the stack, then just read it off. You could create a subroutine that looks like this:
偏移到当前段寄存器 ( EIP
) 通常不可访问。然而,有一种间接读取它的hackish-way - 你欺骗程序将EIP的值推送到堆栈上,然后读取它。您可以创建一个如下所示的子程序:
GetAddress:
mov eax, [esp]
ret
...
call GetAddress ; address of this line stored in eax
Or, even simpler:
或者,更简单:
call NextLine
NextLine:
pop eax ; address of previous line stored in EAX
If you use a CALL FAR
instruction, the segment value (CS
) will be pushed on the stack as well.
如果使用CALL FAR
指令,段值 ( CS
) 也将被压入堆栈。
If you're using C, there are various compiler-specific C-extensions you could use on this page. See also this interesting article.
回答by Basile Starynkevitch
If using GCC, you could also use __builtin_return_address
如果使用 GCC,您还可以使用 __builtin_return_address