2011-10-28 49 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的包裝函數的定義不在頭文件中,也不會被內聯。 –