ReactOS  0.4.12-dev-75-g00dd17e
unwind.c File Reference
#include <rtl.h>
#include <debug.h>
Include dependency graph for unwind.c:

Go to the source code of this file.

Classes

union  _UNWIND_CODE
 
struct  _UNWIND_INFO
 

Macros

#define NDEBUG
 
#define UNWIND_HISTORY_TABLE_NONE   0
 
#define UNWIND_HISTORY_TABLE_GLOBAL   1
 
#define UNWIND_HISTORY_TABLE_LOCAL   2
 
#define UWOP_PUSH_NONVOL   0
 
#define UWOP_ALLOC_LARGE   1
 
#define UWOP_ALLOC_SMALL   2
 
#define UWOP_SET_FPREG   3
 
#define UWOP_SAVE_NONVOL   4
 
#define UWOP_SAVE_NONVOL_FAR   5
 
#define UWOP_SAVE_XMM   6
 
#define UWOP_SAVE_XMM_FAR   7
 
#define UWOP_SAVE_XMM128   8
 
#define UWOP_SAVE_XMM128_FAR   9
 
#define UWOP_PUSH_MACHFRAME   10
 

Typedefs

typedef unsigned char UBYTE
 
typedef union _UNWIND_CODE UNWIND_CODE
 
typedef union _UNWIND_CODEPUNWIND_CODE
 
typedef struct _UNWIND_INFO UNWIND_INFO
 
typedef struct _UNWIND_INFOPUNWIND_INFO
 

Functions

PRUNTIME_FUNCTION NTAPI RtlLookupFunctionTable (IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PULONG Length)
 Locates the table of RUNTIME_FUNCTION entries for a code address. More...
 
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry (IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PUNWIND_HISTORY_TABLE HistoryTable)
 Locates the RUNTIME_FUNCTION entry corresponding to a code address. http://msdn.microsoft.com/en-us/library/ms680597(VS.85).aspx. More...
 
BOOLEAN NTAPI RtlAddFunctionTable (IN PRUNTIME_FUNCTION FunctionTable, IN DWORD EntryCount, IN DWORD64 BaseAddress)
 
BOOLEAN NTAPI RtlDeleteFunctionTable (IN PRUNTIME_FUNCTION FunctionTable)
 
BOOLEAN NTAPI RtlInstallFunctionTableCallback (IN DWORD64 TableIdentifier, IN DWORD64 BaseAddress, IN DWORD Length, IN PGET_RUNTIME_FUNCTION_CALLBACK Callback, IN PVOID Context, IN PCWSTR OutOfProcessCallbackDll)
 
void FORCEINLINE SetReg (PCONTEXT Context, BYTE Reg, DWORD64 Value)
 
DWORD64 FORCEINLINE GetReg (PCONTEXT Context, BYTE Reg)
 
void FORCEINLINE PopReg (PCONTEXT Context, BYTE Reg)
 
static BOOLEAN __inline RtlpTryToUnwindEpilog (PCONTEXT Context, ULONG64 ImageBase, PRUNTIME_FUNCTION FunctionEntry)
 Helper function that tries to unwind epilog instructions. More...
 
PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind (_In_ ULONG HandlerType, _In_ ULONG64 ImageBase, _In_ ULONG64 ControlPc, _In_ PRUNTIME_FUNCTION FunctionEntry, _Inout_ PCONTEXT Context, _Outptr_ PVOID *HandlerData, _Out_ PULONG64 EstablisherFrame, _Inout_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
 
VOID NTAPI RtlUnwindEx (_In_opt_ PVOID TargetFrame, _In_opt_ PVOID TargetIp, _In_opt_ PEXCEPTION_RECORD ExceptionRecord, _In_ PVOID ReturnValue, _In_ PCONTEXT ContextRecord, _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable)
 
VOID NTAPI RtlUnwind (IN PVOID TargetFrame, IN PVOID TargetIp, IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID ReturnValue)
 
ULONG NTAPI RtlWalkFrameChain (OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags)
 
VOID NTAPI RtlGetCallersAddress (OUT PVOID *CallersAddress, OUT PVOID *CallersCaller)
 
VOID NTAPI RtlRaiseException (IN PEXCEPTION_RECORD ExceptionRecord)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file unwind.c.

◆ UNWIND_HISTORY_TABLE_GLOBAL

#define UNWIND_HISTORY_TABLE_GLOBAL   1

Definition at line 16 of file unwind.c.

◆ UNWIND_HISTORY_TABLE_LOCAL

#define UNWIND_HISTORY_TABLE_LOCAL   2

Definition at line 17 of file unwind.c.

◆ UNWIND_HISTORY_TABLE_NONE

#define UNWIND_HISTORY_TABLE_NONE   0

Definition at line 15 of file unwind.c.

◆ UWOP_ALLOC_LARGE

#define UWOP_ALLOC_LARGE   1

Definition at line 20 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_ALLOC_SMALL

#define UWOP_ALLOC_SMALL   2

Definition at line 21 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_PUSH_MACHFRAME

#define UWOP_PUSH_MACHFRAME   10

Definition at line 29 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_PUSH_NONVOL

#define UWOP_PUSH_NONVOL   0

Definition at line 19 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_SAVE_NONVOL

#define UWOP_SAVE_NONVOL   4

Definition at line 23 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_SAVE_NONVOL_FAR

#define UWOP_SAVE_NONVOL_FAR   5

Definition at line 24 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_SAVE_XMM

#define UWOP_SAVE_XMM   6

Definition at line 25 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_SAVE_XMM128

#define UWOP_SAVE_XMM128   8

Definition at line 27 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_SAVE_XMM128_FAR

#define UWOP_SAVE_XMM128_FAR   9

Definition at line 28 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_SAVE_XMM_FAR

#define UWOP_SAVE_XMM_FAR   7

Definition at line 26 of file unwind.c.

Referenced by RtlVirtualUnwind().

◆ UWOP_SET_FPREG

#define UWOP_SET_FPREG   3

Definition at line 22 of file unwind.c.

Referenced by RtlVirtualUnwind().

Typedef Documentation

◆ PUNWIND_CODE

typedef union _UNWIND_CODE * PUNWIND_CODE

◆ PUNWIND_INFO

◆ UBYTE

typedef unsigned char UBYTE

Definition at line 32 of file unwind.c.

◆ UNWIND_CODE

typedef union _UNWIND_CODE UNWIND_CODE

◆ UNWIND_INFO

Function Documentation

◆ GetReg()

DWORD64 FORCEINLINE GetReg ( PCONTEXT  Context,
BYTE  Reg 
)

Definition at line 205 of file unwind.c.

Referenced by RtlpTryToUnwindEpilog().

206 {
207  return ((DWORD64*)(&Context->Rax))[Reg];
208 }
uint64_t DWORD64
Definition: typedefs.h:65

◆ PopReg()

void FORCEINLINE PopReg ( PCONTEXT  Context,
BYTE  Reg 
)

Definition at line 212 of file unwind.c.

Referenced by RtlpTryToUnwindEpilog().

213 {
214  DWORD64 Value = *(DWORD64*)Context->Rsp;
215  Context->Rsp += 8;
216  SetReg(Context, Reg, Value);
217 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
void FORCEINLINE SetReg(PCONTEXT Context, BYTE Reg, DWORD64 Value)
Definition: unwind.c:198
uint64_t DWORD64
Definition: typedefs.h:65

◆ RtlAddFunctionTable()

BOOLEAN NTAPI RtlAddFunctionTable ( IN PRUNTIME_FUNCTION  FunctionTable,
IN DWORD  EntryCount,
IN DWORD64  BaseAddress 
)

Definition at line 164 of file unwind.c.

168 {
170  return FALSE;
171 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlDeleteFunctionTable()

BOOLEAN NTAPI RtlDeleteFunctionTable ( IN PRUNTIME_FUNCTION  FunctionTable)

Definition at line 175 of file unwind.c.

177 {
179  return FALSE;
180 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlGetCallersAddress()

VOID NTAPI RtlGetCallersAddress ( OUT PVOID CallersAddress,
OUT PVOID CallersCaller 
)

RtlGetCallersAddress http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Debug/RtlGetCallersAddress.html

Definition at line 608 of file unwind.c.

611 {
612  PVOID Callers[4];
613  ULONG Number;
614 
615  /* Get callers:
616  * RtlWalkFrameChain -> RtlGetCallersAddress -> x -> y */
617  Number = RtlWalkFrameChain(Callers, 4, 0);
618 
619  *CallersAddress = (Number >= 3) ? Callers[2] : NULL;
620  *CallersCaller = (Number == 4) ? Callers[3] : NULL;
621 
622  return;
623 }
ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags)
Definition: unwind.c:522
smooth NULL
Definition: ftsmooth.c:416
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
unsigned int ULONG
Definition: retypes.h:1

◆ RtlInstallFunctionTableCallback()

BOOLEAN NTAPI RtlInstallFunctionTableCallback ( IN DWORD64  TableIdentifier,
IN DWORD64  BaseAddress,
IN DWORD  Length,
IN PGET_RUNTIME_FUNCTION_CALLBACK  Callback,
IN PVOID  Context,
IN PCWSTR  OutOfProcessCallbackDll 
)

Definition at line 184 of file unwind.c.

191 {
193  return FALSE;
194 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlLookupFunctionEntry()

PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry ( IN DWORD64  ControlPc,
OUT PDWORD64  ImageBase,
OUT PUNWIND_HISTORY_TABLE  HistoryTable 
)

Locates the RUNTIME_FUNCTION entry corresponding to a code address. http://msdn.microsoft.com/en-us/library/ms680597(VS.85).aspx.

RtlLookupFunctionEntry

Todo:
Implement HistoryTable

Definition at line 112 of file unwind.c.

Referenced by RtlRaiseException(), and RtlWalkFrameChain().

116 {
117  PRUNTIME_FUNCTION FunctionTable, FunctionEntry;
118  ULONG TableLength;
119  ULONG IndexLo, IndexHi, IndexMid;
120 
121  /* Find the corresponding table */
122  FunctionTable = RtlLookupFunctionTable(ControlPc, ImageBase, &TableLength);
123 
124  /* Fail, if no table is found */
125  if (!FunctionTable)
126  {
127  return NULL;
128  }
129 
130  /* Use relative virtual address */
131  ControlPc -= *ImageBase;
132 
133  /* Do a binary search */
134  IndexLo = 0;
135  IndexHi = TableLength;
136  while (IndexHi > IndexLo)
137  {
138  IndexMid = (IndexLo + IndexHi) / 2;
139  FunctionEntry = &FunctionTable[IndexMid];
140 
141  if (ControlPc < FunctionEntry->BeginAddress)
142  {
143  /* Continue search in lower half */
144  IndexHi = IndexMid;
145  }
146  else if (ControlPc >= FunctionEntry->EndAddress)
147  {
148  /* Continue search in upper half */
149  IndexLo = IndexMid + 1;
150  }
151  else
152  {
153  /* ControlPc is within limits, return entry */
154  return FunctionEntry;
155  }
156  }
157 
158  /* Nothing found, return NULL */
159  return NULL;
160 }
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionTable(IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PULONG Length)
Locates the table of RUNTIME_FUNCTION entries for a code address.
Definition: unwind.c:77
smooth NULL
Definition: ftsmooth.c:416
unsigned int ULONG
Definition: retypes.h:1
static WLX_DISPATCH_VERSION_1_4 FunctionTable
Definition: wlx.c:736

◆ RtlLookupFunctionTable()

PRUNTIME_FUNCTION NTAPI RtlLookupFunctionTable ( IN DWORD64  ControlPc,
OUT PDWORD64  ImageBase,
OUT PULONG  Length 
)

Locates the table of RUNTIME_FUNCTION entries for a code address.

RtlLookupFunctionTable

Parameters
ControlPcAddress of the code, for which the table should be searched.
ImageBasePointer to a DWORD64 that receives the base address of the corresponding executable image.
LengthPointer to an ULONG that receives the number of table entries present in the table.

Definition at line 77 of file unwind.c.

Referenced by RtlLookupFunctionEntry().

81 {
82  PVOID Table;
83  ULONG Size;
84 
85  /* Find corresponding file header from code address */
86  if (!RtlPcToFileHeader((PVOID)ControlPc, (PVOID*)ImageBase))
87  {
88  /* Nothing found */
89  return NULL;
90  }
91 
92  /* Locate the exception directory */
93  Table = RtlImageDirectoryEntryToData((PVOID)*ImageBase,
94  TRUE,
96  &Size);
97 
98  /* Return the number of entries */
99  *Length = Size / sizeof(RUNTIME_FUNCTION);
100 
101  /* Return the address of the table */
102  return Table;
103 }
ASMGENDATA Table[]
Definition: genincdata.c:61
#define TRUE
Definition: types.h:120
struct _RUNTIME_FUNCTION RUNTIME_FUNCTION
PVOID NTAPI RtlPcToFileHeader(IN PVOID PcValue, PVOID *BaseOfImage)
Definition: libsupp.c:616
smooth NULL
Definition: ftsmooth.c:416
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define RtlImageDirectoryEntryToData
Definition: compat.h:460
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
unsigned int ULONG
Definition: retypes.h:1
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION
Definition: pedump.c:262

◆ RtlpTryToUnwindEpilog()

static BOOLEAN __inline RtlpTryToUnwindEpilog ( PCONTEXT  Context,
ULONG64  ImageBase,
PRUNTIME_FUNCTION  FunctionEntry 
)
static

Helper function that tries to unwind epilog instructions.

RtlpTryToUnwindEpilog

Returns
TRUE if we have been in an epilog and it could be unwound. FALSE if the instructions were not allowed for an epilog. http://msdn.microsoft.com/en-us/library/8ydc79k6(VS.80).aspx http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx
Todo:
  • Test and compare with Windows behaviour

Definition at line 232 of file unwind.c.

Referenced by RtlVirtualUnwind().

236 {
237  CONTEXT LocalContext;
238  BYTE *InstrPtr;
239  DWORD Instr;
240  BYTE Reg, Mod;
241  ULONG64 EndAddress;
242 
243  /* Make a local copy of the context */
244  LocalContext = *Context;
245 
246  InstrPtr = (BYTE*)LocalContext.Rip;
247 
248  /* Check if first instruction of epilog is "add rsp, x" */
249  Instr = *(DWORD*)InstrPtr;
250  if ( (Instr & 0x00fffdff) == 0x00c48148 )
251  {
252  if ( (Instr & 0x0000ff00) == 0x8300 )
253  {
254  /* This is "add rsp, 0x??" */
255  LocalContext.Rsp += Instr >> 24;
256  InstrPtr += 4;
257  }
258  else
259  {
260  /* This is "add rsp, 0x???????? */
261  LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
262  InstrPtr += 7;
263  }
264  }
265  /* Check if first instruction of epilog is "lea rsp, ..." */
266  else if ( (Instr & 0x38fffe) == 0x208d48 )
267  {
268  /* Get the register */
269  Reg = ((Instr << 8) | (Instr >> 16)) & 0x7;
270 
271  LocalContext.Rsp = GetReg(&LocalContext, Reg);
272 
273  /* Get adressing mode */
274  Mod = (Instr >> 22) & 0x3;
275  if (Mod == 0)
276  {
277  /* No displacement */
278  InstrPtr += 3;
279  }
280  else if (Mod == 1)
281  {
282  /* 1 byte displacement */
283  LocalContext.Rsp += Instr >> 24;
284  InstrPtr += 4;
285  }
286  else if (Mod == 2)
287  {
288  /* 4 bytes displacement */
289  LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
290  InstrPtr += 7;
291  }
292  }
293 
294  /* Loop the following instructions before the ret */
295  EndAddress = FunctionEntry->EndAddress + ImageBase - 1;
296  while ((DWORD64)InstrPtr < EndAddress)
297  {
298  Instr = *(DWORD*)InstrPtr;
299 
300  /* Check for a simple pop */
301  if ( (Instr & 0xf8) == 0x58 )
302  {
303  /* Opcode pops a basic register from stack */
304  Reg = Instr & 0x7;
305  PopReg(&LocalContext, Reg);
306  InstrPtr++;
307  continue;
308  }
309 
310  /* Check for REX + pop */
311  if ( (Instr & 0xf8fb) == 0x5841 )
312  {
313  /* Opcode is pop r8 .. r15 */
314  Reg = ((Instr >> 8) & 0x7) + 8;
315  PopReg(&LocalContext, Reg);
316  InstrPtr += 2;
317  continue;
318  }
319 
320  /* Opcode not allowed for Epilog */
321  return FALSE;
322  }
323 
324  /* Check if we are at the ret instruction */
325  if ((DWORD64)InstrPtr != EndAddress)
326  {
327  /* If we went past the end of the function, something is broken! */
328  ASSERT((DWORD64)InstrPtr <= EndAddress);
329  return FALSE;
330  }
331 
332  /* Make sure this is really a ret instruction */
333  if (*InstrPtr != 0xc3)
334  {
335  ASSERT(FALSE);
336  return FALSE;
337  }
338 
339  /* Unwind is finished, pop new Rip from Stack */
340  LocalContext.Rip = *(DWORD64*)LocalContext.Rsp;
341  LocalContext.Rsp += sizeof(DWORD64);
342 
343  *Context = LocalContext;
344  return TRUE;
345 }
#define TRUE
Definition: types.h:120
void FORCEINLINE PopReg(PCONTEXT Context, BYTE Reg)
Definition: unwind.c:212
unsigned long DWORD
Definition: ntddk_ex.h:95
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned char BYTE
Definition: ntddk_ex.h:96
uint64_t DWORD64
Definition: typedefs.h:65
DWORD64 FORCEINLINE GetReg(PCONTEXT Context, BYTE Reg)
Definition: unwind.c:205
struct tagContext Context
Definition: acpixf.h:1027

◆ RtlRaiseException()

VOID NTAPI RtlRaiseException ( IN PEXCEPTION_RECORD  ExceptionRecord)

Definition at line 628 of file unwind.c.

629 {
632  ULONG64 ImageBase;
633  PRUNTIME_FUNCTION FunctionEntry;
634  PVOID HandlerData;
636 
637  /* Capture the context */
638  RtlCaptureContext(&Context);
639 
640  /* Get the function entry for this function */
641  FunctionEntry = RtlLookupFunctionEntry(Context.Rip,
642  &ImageBase,
643  NULL);
644 
645  /* Check if we found it */
646  if (FunctionEntry)
647  {
648  /* Unwind to the caller of this function */
650  ImageBase,
651  Context.Rip,
652  FunctionEntry,
653  &Context,
654  &HandlerData,
655  &EstablisherFrame,
656  NULL);
657 
658  /* Save the exception address */
659  ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip;
660 
661  /* Write the context flag */
662  Context.ContextFlags = CONTEXT_FULL;
663 
664  /* Check if user mode debugger is active */
666  {
667  /* Raise an exception immediately */
668  Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
669  }
670  else
671  {
672  /* Dispatch the exception and check if we should continue */
673  if (!RtlDispatchException(ExceptionRecord, &Context))
674  {
675  /* Raise the exception */
676  Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
677  }
678  else
679  {
680  /* Continue, go back to previous context */
681  Status = ZwContinue(&Context, FALSE);
682  }
683  }
684  }
685 
686  /* If we returned, raise a status */
687  RtlRaiseStatus(Status);
688 }
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
#define TRUE
Definition: types.h:120
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:660
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI NTSTATUS NTAPI ZwRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames)
PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind(_In_ ULONG HandlerType, _In_ ULONG64 ImageBase, _In_ ULONG64 ControlPc, _In_ PRUNTIME_FUNCTION FunctionEntry, _Inout_ PCONTEXT Context, _Outptr_ PVOID *HandlerData, _Out_ PULONG64 EstablisherFrame, _Inout_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
Definition: unwind.c:349
#define CONTEXT_FULL
Definition: compat.h:270
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
NTSYSAPI NTSTATUS NTAPI ZwContinue(_In_ PCONTEXT Context, _In_ BOOLEAN TestAlert)
#define STATUS_INVALID_DISPOSITION
Definition: ntstatus.h:261
smooth NULL
Definition: ftsmooth.c:416
void * PVOID
Definition: retypes.h:9
ULONG ContextFlags
Definition: compat.h:331
NTSYSAPI BOOLEAN NTAPI RtlDispatchException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: except.c:34
if(!(yy_init))
Definition: macro.lex.yy.c:717
unsigned __int64 ULONG64
Definition: imports.h:198
BOOLEAN NTAPI RtlpCheckForActiveDebugger(VOID)
Definition: libsupp.c:25
Status
Definition: gdiplustypes.h:24
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry(IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PUNWIND_HISTORY_TABLE HistoryTable)
Locates the RUNTIME_FUNCTION entry corresponding to a code address. http://msdn.microsoft.com/en-us/library/ms680597(VS.85).aspx.
Definition: unwind.c:112
struct tagContext Context
Definition: acpixf.h:1027
#define UNW_FLAG_NHANDLER
Definition: gs_support.c:32

◆ RtlUnwind()

VOID NTAPI RtlUnwind ( IN PVOID TargetFrame  ,
IN PVOID TargetIp  ,
IN PEXCEPTION_RECORD ExceptionRecord  ,
IN PVOID  ReturnValue 
)

Definition at line 510 of file unwind.c.

515 {
517  return;
518 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlUnwindEx()

VOID NTAPI RtlUnwindEx ( _In_opt_ PVOID  TargetFrame,
_In_opt_ PVOID  TargetIp,
_In_opt_ PEXCEPTION_RECORD  ExceptionRecord,
_In_ PVOID  ReturnValue,
_In_ PCONTEXT  ContextRecord,
_In_opt_ struct _UNWIND_HISTORY_TABLE HistoryTable 
)

Definition at line 496 of file unwind.c.

503 {
504  __debugbreak();
505  return;
506 }
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698

◆ RtlVirtualUnwind()

PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind ( _In_ ULONG  HandlerType,
_In_ ULONG64  ImageBase,
_In_ ULONG64  ControlPc,
_In_ PRUNTIME_FUNCTION  FunctionEntry,
_Inout_ PCONTEXT  Context,
_Outptr_ PVOID HandlerData,
_Out_ PULONG64  EstablisherFrame,
_Inout_ PKNONVOLATILE_CONTEXT_POINTERS  ContextPointers 
)

Definition at line 349 of file unwind.c.

Referenced by RtlRaiseException(), and RtlWalkFrameChain().

358 {
359  PUNWIND_INFO UnwindInfo;
360  ULONG_PTR CodeOffset;
361  ULONG i;
362  UNWIND_CODE UnwindCode;
363  BYTE Reg;
364 
365  /* Use relative virtual address */
366  ControlPc -= ImageBase;
367 
368  /* Sanity checks */
369  if ( (ControlPc < FunctionEntry->BeginAddress) ||
370  (ControlPc >= FunctionEntry->EndAddress) )
371  {
372  return NULL;
373  }
374 
375  /* Get a pointer to the unwind info */
376  UnwindInfo = RVA(ImageBase, FunctionEntry->UnwindData);
377 
378  /* Calculate relative offset to function start */
379  CodeOffset = ControlPc - FunctionEntry->BeginAddress;
380 
381  /* Check if we are in the function epilog and try to finish it */
382  if (CodeOffset > UnwindInfo->SizeOfProlog)
383  {
384  if (RtlpTryToUnwindEpilog(Context, ImageBase, FunctionEntry))
385  {
386  /* There's no exception routine */
387  return NULL;
388  }
389  }
390 
391  /* Skip all Ops with an offset greater than the current Offset */
392  i = 0;
393  while (i < UnwindInfo->CountOfCodes &&
394  CodeOffset < UnwindInfo->UnwindCode[i].CodeOffset)
395  {
396  UnwindCode = UnwindInfo->UnwindCode[i];
397  switch (UnwindCode.UnwindOp)
398  {
399  case UWOP_SAVE_NONVOL:
400  case UWOP_SAVE_XMM:
401  case UWOP_SAVE_XMM128:
402  i += 2;
403  break;
404 
406  case UWOP_SAVE_XMM_FAR:
408  i += 3;
409  break;
410 
411  case UWOP_ALLOC_LARGE:
412  i += UnwindCode.OpInfo ? 3 : 2;
413  break;
414 
415  default:
416  i++;
417  }
418  }
419 
420  /* Process the remaining unwind ops */
421  while (i < UnwindInfo->CountOfCodes)
422  {
423  UnwindCode = UnwindInfo->UnwindCode[i];
424  switch (UnwindCode.UnwindOp)
425  {
426  case UWOP_PUSH_NONVOL:
427  Reg = UnwindCode.OpInfo;
428  SetReg(Context, Reg, *(DWORD64*)Context->Rsp);
429  Context->Rsp += sizeof(DWORD64);
430  i++;
431  break;
432 
433  case UWOP_ALLOC_LARGE:
434  if (UnwindCode.OpInfo)
435  {
436  ULONG Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i+1]);
437  Context->Rsp += Offset;
438  i += 3;
439  }
440  else
441  {
442  USHORT Offset = UnwindInfo->UnwindCode[i+1].FrameOffset;
443  Context->Rsp += Offset * 8;
444  i += 2;
445  }
446  break;
447 
448  case UWOP_ALLOC_SMALL:
449  Context->Rsp += (UnwindCode.OpInfo + 1) * 8;
450  i++;
451  break;
452 
453  case UWOP_SET_FPREG:
454  i++;
455  break;
456 
457  case UWOP_SAVE_NONVOL:
458  i += 2;
459  break;
460 
462  i += 3;
463  break;
464 
465  case UWOP_SAVE_XMM:
466  i += 2;
467  break;
468 
469  case UWOP_SAVE_XMM_FAR:
470  i += 3;
471  break;
472 
473  case UWOP_SAVE_XMM128:
474  i += 2;
475  break;
476 
478  i += 3;
479  break;
480 
481  case UWOP_PUSH_MACHFRAME:
482  i += 1;
483  break;
484  }
485  }
486 
487  /* Unwind is finished, pop new Rip from Stack */
488  Context->Rip = *(DWORD64*)Context->Rsp;
489  Context->Rsp += sizeof(DWORD64);
490 
491  return 0;
492 }
#define UWOP_ALLOC_LARGE
Definition: unwind.c:20
static BOOLEAN __inline RtlpTryToUnwindEpilog(PCONTEXT Context, ULONG64 ImageBase, PRUNTIME_FUNCTION FunctionEntry)
Helper function that tries to unwind epilog instructions.
Definition: unwind.c:232
void FORCEINLINE SetReg(PCONTEXT Context, BYTE Reg, DWORD64 Value)
Definition: unwind.c:198
BYTE UnwindOp
Definition: cpu_x86_64.c:54
#define UWOP_SAVE_XMM
Definition: unwind.c:25
uint32_t ULONG_PTR
Definition: typedefs.h:63
GLenum GLclampf GLint i
Definition: glfuncs.h:14
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define UWOP_SAVE_XMM_FAR
Definition: unwind.c:26
smooth NULL
Definition: ftsmooth.c:416
#define UWOP_SET_FPREG
Definition: unwind.c:22
#define UWOP_PUSH_NONVOL
Definition: unwind.c:19
#define UWOP_SAVE_XMM128_FAR
Definition: unwind.c:28
UNWIND_CODE UnwindCode[1]
Definition: cpu_x86_64.c:68
unsigned char BYTE
Definition: ntddk_ex.h:96
#define RVA(m, b)
Definition: freeldr.h:24
#define UWOP_PUSH_MACHFRAME
Definition: unwind.c:29
BYTE SizeOfProlog
Definition: cpu_x86_64.c:64
USHORT FrameOffset
Definition: cpu_x86_64.c:57
#define UWOP_SAVE_XMM128
Definition: unwind.c:27
uint64_t DWORD64
Definition: typedefs.h:65
unsigned short USHORT
Definition: pedump.c:61
#define UWOP_SAVE_NONVOL
Definition: unwind.c:23
#define UWOP_ALLOC_SMALL
Definition: unwind.c:21
#define UWOP_SAVE_NONVOL_FAR
Definition: unwind.c:24
unsigned int ULONG
Definition: retypes.h:1

◆ RtlWalkFrameChain()

ULONG NTAPI RtlWalkFrameChain ( OUT PVOID Callers,
IN ULONG  Count,
IN ULONG  Flags 
)

Definition at line 522 of file unwind.c.

Referenced by RtlGetCallersAddress().

525 {
527  ULONG64 ControlPc, ImageBase, EstablisherFrame;
528  ULONG64 StackLow, StackHigh;
529  PVOID HandlerData;
530  ULONG i, FramesToSkip;
531  PRUNTIME_FUNCTION FunctionEntry;
532 
533  DPRINT("Enter RtlWalkFrameChain\n");
534 
535  /* The upper bits in Flags define how many frames to skip */
536  FramesToSkip = Flags >> 8;
537 
538  /* Capture the current Context */
539  RtlCaptureContext(&Context);
540  ControlPc = Context.Rip;
541 
542  /* Get the stack limits */
543  RtlpGetStackLimits(&StackLow, &StackHigh);
544 
545  /* Check if we want the user-mode stack frame */
546  if (Flags & 1)
547  {
548  }
549 
550  /* Loop the frames */
551  for (i = 0; i < FramesToSkip + Count; i++)
552  {
553  /* Lookup the FunctionEntry for the current ControlPc */
554  FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
555 
556  /* Is this a leaf function? */
557  if (!FunctionEntry)
558  {
559  Context.Rip = *(DWORD64*)Context.Rsp;
560  Context.Rsp += sizeof(DWORD64);
561  DPRINT("leaf funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
562  }
563  else
564  {
566  ImageBase,
567  ControlPc,
568  FunctionEntry,
569  &Context,
570  &HandlerData,
571  &EstablisherFrame,
572  NULL);
573  DPRINT("normal funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
574  }
575 
576  /* Check if new Rip is valid */
577  if (!Context.Rip)
578  {
579  break;
580  }
581 
582  /* Check, if we have left our stack */
583  if ((Context.Rsp < StackLow) || (Context.Rsp > StackHigh))
584  {
585  break;
586  }
587 
588  /* Continue with new Rip */
589  ControlPc = Context.Rip;
590 
591  /* Save value, if we are past the frames to skip */
592  if (i >= FramesToSkip)
593  {
594  Callers[i - FramesToSkip] = (PVOID)ControlPc;
595  }
596  }
597 
598  DPRINT("RtlWalkFrameChain returns %ld\n", i);
599  return i;
600 }
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:660
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind(_In_ ULONG HandlerType, _In_ ULONG64 ImageBase, _In_ ULONG64 ControlPc, _In_ PRUNTIME_FUNCTION FunctionEntry, _Inout_ PCONTEXT Context, _Outptr_ PVOID *HandlerData, _Out_ PULONG64 EstablisherFrame, _Inout_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
Definition: unwind.c:349
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLenum GLclampf GLint i
Definition: glfuncs.h:14
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
void * PVOID
Definition: retypes.h:9
unsigned __int64 ULONG64
Definition: imports.h:198
VOID NTAPI RtlpGetStackLimits(PULONG_PTR StackBase, PULONG_PTR StackLimit)
uint64_t DWORD64
Definition: typedefs.h:65
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry(IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PUNWIND_HISTORY_TABLE HistoryTable)
Locates the RUNTIME_FUNCTION entry corresponding to a code address. http://msdn.microsoft.com/en-us/library/ms680597(VS.85).aspx.
Definition: unwind.c:112
struct tagContext Context
Definition: acpixf.h:1027
unsigned int ULONG
Definition: retypes.h:1

◆ SetReg()

void FORCEINLINE SetReg ( PCONTEXT  Context,
BYTE  Reg,
DWORD64  Value 
)

Definition at line 198 of file unwind.c.

Referenced by PopReg(), and RtlVirtualUnwind().

199 {
200  ((DWORD64*)(&Context->Rax))[Reg] = Value;
201 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
uint64_t DWORD64
Definition: typedefs.h:65