Sto usando Linux con x86 (64 bit per la precisione). C'è un modo per ottenere l'indirizzo dell'istruzione corrente. In realtà voglio scrivere le mie versioni semplificate di setjmp/longjmp. Here, R .. ha pubblicato una versione semplificata di longjmp. Qualche idea su come sia implementato setjmp. Una versione semplificata che è, senza tener conto di eccezioni e segnali ecc ...Ottieni l'indirizzo dell'istruzione corrente per x86
risposta
Credo nel codice a 64 bit che puoi semplicemente fare lea rax, [rip]
.
L'idioma a 32 bit è:
call next
next: pop eax
This sito fornisce una semplice versione di setjmp e longjmp, che è la seguente.
#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
}
}
È questa la risposta alla tua domanda, @MetallicPriest? – karlphillip
Non necessariamente, posso spuntare la tua risposta, se è buona :-p! – MetallicPriest
Il registro offset in-the-corrente-segmento (EIP
) non è normalmente accessibile. Tuttavia, c'è un modo hacker di leggerlo indirettamente: si induce il programma a spingere il valore di EIP sullo stack, quindi basta leggerlo. Si potrebbe creare una subroutine che assomiglia a questo:
GetAddress:
mov eax, [esp]
ret
...
call GetAddress ; address of this line stored in eax
Oppure, ancora più semplice:
call NextLine
NextLine:
pop eax ; address of previous line stored in EAX
Se si utilizza un'istruzione CALL FAR
, il valore di segmento (CS
) sarà spinto sullo stack pure .
Se stai usando C, ci sono vari C-estensioni specifiche del compilatore è possibile utilizzare il this page. Vedi anche this interesting article.
l'OP chiede su x86_64, che ha l'indirizzamento relativo, quindi ci sono istruzioni "accessibili" a RIP –
Se si utilizza GCC, si potrebbe anche usare __builtin_return_address
Tieni presente che sarà necessario avvolgerlo in una funzione per avere l'effetto desiderato, altrimenti ti ritroverai con l'indirizzo di ritorno per il frame dello stack corrente anziché l'indirizzo dell'istruzione corrente. – Jason
se usi GCC è più facile usare ['somelabel: return && somelabel;'] (http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) –
@Jason ha ragione ed anche assicurarti che la definizione della funzione di wrapping che contiene __builtin_return_address non si trova in un file di intestazione e non sarà mai in linea. –
E 'possibile fare qualcosa di simile a 32 bit? – MetallicPriest
@MetallicPriest: risposta aggiornata. – NPE
Cool trick hun :-p! – MetallicPriest