2011-10-28 75 views
8

我正在使用Linux和x86(64位准确)。有没有办法可以得到当前指令的地址?其实我想写我自己的简化版本setjmp/longjmpHere,R ..发布简化版本longjmp。任何想法如何实现setjmp。一个简化的版本,即不考虑异常和信号等...获取x86当前指令的地址

回答

24

我相信在64位代码,你可以简单地做lea rax, [rip]

32位成语是:

 call next 
next: pop eax 
+0

,并有可能做这样的事情,在32位? – MetallicPriest

+1

@MetallicPriest:答案已更新。 – NPE

+0

酷招hp :-p! – MetallicPriest

0

This网站给出了一个简单版本的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 
    } 
} 
+3

这是你的问题的答案,@MetallicPriest? – karlphillip

+0

不一定,我可以在你的答案中打勾,如果它很好:-p! – MetallicPriest

4

偏移 - 到 - 的电流段寄存器(EIP)是不正常访问。但是,间接读取它存在一种骇人听闻的方式 - 诱骗程序将EIP的值推入堆栈,然后将其读取。如果您使用的是CALL FAR指令,段值(CS

call NextLine 
NextLine: 
    pop eax    ; address of previous line stored in EAX 

将被压入堆栈,以及:您可以创建一个子程序,看起来像这样:

GetAddress: 
    mov eax, [esp] 
    ret 
... 
    call GetAddress  ; address of this line stored in eax 

甚至更​​简单。


如果你使用C,还有你可以在this page使用各种编译器相关的C-扩展。另见this interesting article

+0

OP询问关于具有相对寻址的x86_64,所以有指令“可访问”到RIP –

8

如果使用GCC,你也可以使用__builtin_return_address

+2

请记住,您需要将它包装在一个函数中才能达到预期的效果,否则最终会当前堆栈帧的返回地址,而不是当前指令的地址。 – Jason

+2

如果使用GCC,它更易于使用['somelabel:return && somelabel;'](http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) –

+1

@Jason是正确的,并且确保包含__builtin_return_address的包装函数的定义不在头文件中,也不会被内联。 –