ReactOS  0.4.15-dev-5131-g311fcc6
unwind.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS system libraries
4  * PURPOSE: Unwinding related functions
5  * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
6  */
7 
8 /* INCLUDES *****************************************************************/
9 
10 #include <rtl.h>
11 
12 #define NDEBUG
13 #include <debug.h>
14 
15 #define UNWIND_HISTORY_TABLE_NONE 0
16 #define UNWIND_HISTORY_TABLE_GLOBAL 1
17 #define UNWIND_HISTORY_TABLE_LOCAL 2
18 
19 #define UWOP_PUSH_NONVOL 0
20 #define UWOP_ALLOC_LARGE 1
21 #define UWOP_ALLOC_SMALL 2
22 #define UWOP_SET_FPREG 3
23 #define UWOP_SAVE_NONVOL 4
24 #define UWOP_SAVE_NONVOL_FAR 5
25 #if 0 // These are deprecated / not for x64
26 #define UWOP_SAVE_XMM 6
27 #define UWOP_SAVE_XMM_FAR 7
28 #else
29 #define UWOP_EPILOG 6
30 #define UWOP_SPARE_CODE 7
31 #endif
32 #define UWOP_SAVE_XMM128 8
33 #define UWOP_SAVE_XMM128_FAR 9
34 #define UWOP_PUSH_MACHFRAME 10
35 
36 
37 typedef unsigned char UBYTE;
38 
39 typedef union _UNWIND_CODE
40 {
41  struct
42  {
46  };
49 
50 typedef struct _UNWIND_INFO
51 {
59 /* union {
60  OPTIONAL ULONG ExceptionHandler;
61  OPTIONAL ULONG FunctionEntry;
62  };
63  OPTIONAL ULONG ExceptionData[];
64 */
66 
67 /* FUNCTIONS *****************************************************************/
68 
81 NTAPI
83  IN DWORD64 ControlPc,
84  OUT PDWORD64 ImageBase,
86 {
87  PVOID Table;
88  ULONG Size;
89 
90  /* Find corresponding file header from code address */
91  if (!RtlPcToFileHeader((PVOID)ControlPc, (PVOID*)ImageBase))
92  {
93  /* Nothing found */
94  return NULL;
95  }
96 
97  /* Locate the exception directory */
99  TRUE,
101  &Size);
102 
103  /* Return the number of entries */
104  *Length = Size / sizeof(RUNTIME_FUNCTION);
105 
106  /* Return the address of the table */
107  return Table;
108 }
109 
111 NTAPI
113  _In_ DWORD64 ControlPc,
114  _Out_ PDWORD64 ImageBase,
115  _In_ PUNWIND_HISTORY_TABLE HistoryTable);
116 
123 NTAPI
125  IN DWORD64 ControlPc,
126  OUT PDWORD64 ImageBase,
127  OUT PUNWIND_HISTORY_TABLE HistoryTable)
128 {
129  PRUNTIME_FUNCTION FunctionTable, FunctionEntry;
130  ULONG TableLength;
131  ULONG IndexLo, IndexHi, IndexMid;
132 
133  /* Find the corresponding table */
134  FunctionTable = RtlLookupFunctionTable(ControlPc, ImageBase, &TableLength);
135 
136  /* If no table is found, try dynamic function tables */
137  if (!FunctionTable)
138  {
139  return RtlpLookupDynamicFunctionEntry(ControlPc, ImageBase, HistoryTable);
140  }
141 
142  /* Use relative virtual address */
143  ControlPc -= *ImageBase;
144 
145  /* Do a binary search */
146  IndexLo = 0;
147  IndexHi = TableLength;
148  while (IndexHi > IndexLo)
149  {
150  IndexMid = (IndexLo + IndexHi) / 2;
151  FunctionEntry = &FunctionTable[IndexMid];
152 
153  if (ControlPc < FunctionEntry->BeginAddress)
154  {
155  /* Continue search in lower half */
156  IndexHi = IndexMid;
157  }
158  else if (ControlPc >= FunctionEntry->EndAddress)
159  {
160  /* Continue search in upper half */
161  IndexLo = IndexMid + 1;
162  }
163  else
164  {
165  /* ControlPc is within limits, return entry */
166  return FunctionEntry;
167  }
168  }
169 
170  /* Nothing found, return NULL */
171  return NULL;
172 }
173 
174 static
175 __inline
176 ULONG
178  _In_ UNWIND_CODE UnwindCode)
179 {
180  static const UCHAR UnwindOpExtraSlotTable[] =
181  {
182  0, // UWOP_PUSH_NONVOL
183  1, // UWOP_ALLOC_LARGE (or 3, special cased in lookup code)
184  0, // UWOP_ALLOC_SMALL
185  0, // UWOP_SET_FPREG
186  1, // UWOP_SAVE_NONVOL
187  2, // UWOP_SAVE_NONVOL_FAR
188  1, // UWOP_EPILOG // previously UWOP_SAVE_XMM
189  2, // UWOP_SPARE_CODE // previously UWOP_SAVE_XMM_FAR
190  1, // UWOP_SAVE_XMM128
191  2, // UWOP_SAVE_XMM128_FAR
192  0, // UWOP_PUSH_MACHFRAME
193  2, // UWOP_SET_FPREG_LARGE
194  };
195 
196  if ((UnwindCode.UnwindOp == UWOP_ALLOC_LARGE) &&
197  (UnwindCode.OpInfo != 0))
198  {
199  return 3;
200  }
201  else
202  {
203  return UnwindOpExtraSlotTable[UnwindCode.UnwindOp] + 1;
204  }
205 }
206 
207 static
208 __inline
209 void
212  _In_ BYTE Reg,
214 {
215  ((DWORD64*)(&Context->Rax))[Reg] = Value;
216 }
217 
218 static
219 __inline
220 void
223  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
224  _In_ BYTE Reg,
225  _In_ PDWORD64 ValuePointer)
226 {
227  SetReg(Context, Reg, *ValuePointer);
228  if (ContextPointers != NULL)
229  {
230  ContextPointers->IntegerContext[Reg] = ValuePointer;
231  }
232 }
233 
234 static
235 __inline
236 DWORD64
239  _In_ BYTE Reg)
240 {
241  return ((DWORD64*)(&Context->Rax))[Reg];
242 }
243 
244 static
245 __inline
246 void
249  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
250  _In_ BYTE Reg)
251 {
252  SetRegFromStackValue(Context, ContextPointers, Reg, (PDWORD64)Context->Rsp);
253  Context->Rsp += sizeof(DWORD64);
254 }
255 
256 static
257 __inline
258 void
261  _In_ BYTE Reg,
262  _In_ M128A Value)
263 {
264  ((M128A*)(&Context->Xmm0))[Reg] = Value;
265 }
266 
267 static
268 __inline
269 void
272  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
273  _In_ BYTE Reg,
274  _In_ M128A *ValuePointer)
275 {
276  SetXmmReg(Context, Reg, *ValuePointer);
277  if (ContextPointers != NULL)
278  {
279  ContextPointers->FloatingContext[Reg] = ValuePointer;
280  }
281 }
282 
283 static
284 __inline
285 M128A
287 {
288  return ((M128A*)(&Context->Xmm0))[Reg];
289 }
290 
301 static
302 __inline
303 BOOLEAN
306  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
307  _In_ ULONG64 ImageBase,
308  _In_ PRUNTIME_FUNCTION FunctionEntry)
309 {
310  CONTEXT LocalContext;
311  BYTE *InstrPtr;
312  DWORD Instr;
313  BYTE Reg, Mod;
314  ULONG64 EndAddress;
315 
316  /* Make a local copy of the context */
317  LocalContext = *Context;
318 
319  InstrPtr = (BYTE*)LocalContext.Rip;
320 
321  /* Check if first instruction of epilog is "add rsp, x" */
322  Instr = *(DWORD*)InstrPtr;
323  if ( (Instr & 0x00fffdff) == 0x00c48148 )
324  {
325  if ( (Instr & 0x0000ff00) == 0x8300 )
326  {
327  /* This is "add rsp, 0x??" */
328  LocalContext.Rsp += Instr >> 24;
329  InstrPtr += 4;
330  }
331  else
332  {
333  /* This is "add rsp, 0x???????? */
334  LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
335  InstrPtr += 7;
336  }
337  }
338  /* Check if first instruction of epilog is "lea rsp, ..." */
339  else if ( (Instr & 0x38fffe) == 0x208d48 )
340  {
341  /* Get the register */
342  Reg = ((Instr << 8) | (Instr >> 16)) & 0x7;
343 
344  LocalContext.Rsp = GetReg(&LocalContext, Reg);
345 
346  /* Get adressing mode */
347  Mod = (Instr >> 22) & 0x3;
348  if (Mod == 0)
349  {
350  /* No displacement */
351  InstrPtr += 3;
352  }
353  else if (Mod == 1)
354  {
355  /* 1 byte displacement */
356  LocalContext.Rsp += Instr >> 24;
357  InstrPtr += 4;
358  }
359  else if (Mod == 2)
360  {
361  /* 4 bytes displacement */
362  LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
363  InstrPtr += 7;
364  }
365  }
366 
367  /* Loop the following instructions before the ret */
368  EndAddress = FunctionEntry->EndAddress + ImageBase - 1;
369  while ((DWORD64)InstrPtr < EndAddress)
370  {
371  Instr = *(DWORD*)InstrPtr;
372 
373  /* Check for a simple pop */
374  if ( (Instr & 0xf8) == 0x58 )
375  {
376  /* Opcode pops a basic register from stack */
377  Reg = Instr & 0x7;
378  PopReg(&LocalContext, ContextPointers, Reg);
379  InstrPtr++;
380  continue;
381  }
382 
383  /* Check for REX + pop */
384  if ( (Instr & 0xf8fb) == 0x5841 )
385  {
386  /* Opcode is pop r8 .. r15 */
387  Reg = ((Instr >> 8) & 0x7) + 8;
388  PopReg(&LocalContext, ContextPointers, Reg);
389  InstrPtr += 2;
390  continue;
391  }
392 
393  /* Opcode not allowed for Epilog */
394  return FALSE;
395  }
396 
397  // check for popfq
398 
399  // also allow end with jmp imm, jmp [target], iretq
400 
401  /* Check if we are at the ret instruction */
402  if ((DWORD64)InstrPtr != EndAddress)
403  {
404  /* If we went past the end of the function, something is broken! */
405  ASSERT((DWORD64)InstrPtr <= EndAddress);
406  return FALSE;
407  }
408 
409  /* Make sure this is really a ret instruction */
410  if (*InstrPtr != 0xc3)
411  {
412  ASSERT(FALSE);
413  return FALSE;
414  }
415 
416  /* Unwind is finished, pop new Rip from Stack */
417  LocalContext.Rip = *(DWORD64*)LocalContext.Rsp;
418  LocalContext.Rsp += sizeof(DWORD64);
419 
420  *Context = LocalContext;
421  return TRUE;
422 }
423 
428 static
429 ULONG64
432  _In_ PUNWIND_INFO UnwindInfo,
433  _In_ ULONG_PTR CodeOffset)
434 {
435  ULONG i;
436 
437  /* Check if we have a frame register */
438  if (UnwindInfo->FrameRegister == 0)
439  {
440  /* No frame register means we use Rsp */
441  return Context->Rsp;
442  }
443 
444  if ((CodeOffset >= UnwindInfo->SizeOfProlog) ||
445  ((UnwindInfo->Flags & UNW_FLAG_CHAININFO) != 0))
446  {
447  return GetReg(Context, UnwindInfo->FrameRegister) -
448  UnwindInfo->FrameOffset * 16;
449  }
450 
451  /* Loop all unwind ops */
452  for (i = 0;
453  i < UnwindInfo->CountOfCodes;
454  i += UnwindOpSlots(UnwindInfo->UnwindCode[i]))
455  {
456  /* Check for SET_FPREG */
457  if (UnwindInfo->UnwindCode[i].UnwindOp == UWOP_SET_FPREG)
458  {
459  return GetReg(Context, UnwindInfo->FrameRegister) -
460  UnwindInfo->FrameOffset * 16;
461  }
462  }
463 
464  return Context->Rsp;
465 }
466 
468 NTAPI
471  _In_ ULONG64 ImageBase,
472  _In_ ULONG64 ControlPc,
473  _In_ PRUNTIME_FUNCTION FunctionEntry,
475  _Outptr_ PVOID *HandlerData,
477  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
478 {
479  PUNWIND_INFO UnwindInfo;
480  ULONG_PTR CodeOffset;
481  ULONG i, Offset;
482  UNWIND_CODE UnwindCode;
483  BYTE Reg;
484  PULONG LanguageHandler;
485 
486  /* Use relative virtual address */
487  ControlPc -= ImageBase;
488 
489  /* Sanity checks */
490  if ( (ControlPc < FunctionEntry->BeginAddress) ||
491  (ControlPc >= FunctionEntry->EndAddress) )
492  {
493  return NULL;
494  }
495 
496  /* Get a pointer to the unwind info */
497  UnwindInfo = RVA(ImageBase, FunctionEntry->UnwindData);
498 
499  /* The language specific handler data follows the unwind info */
500  LanguageHandler = ALIGN_UP_POINTER_BY(&UnwindInfo->UnwindCode[UnwindInfo->CountOfCodes], sizeof(ULONG));
501  *HandlerData = (LanguageHandler + 1);
502 
503  /* Calculate relative offset to function start */
504  CodeOffset = ControlPc - FunctionEntry->BeginAddress;
505 
506  *EstablisherFrame = GetEstablisherFrame(Context, UnwindInfo, CodeOffset);
507 
508  /* Check if we are in the function epilog and try to finish it */
509  if (CodeOffset > UnwindInfo->SizeOfProlog)
510  {
511  if (RtlpTryToUnwindEpilog(Context, ContextPointers, ImageBase, FunctionEntry))
512  {
513  /* There's no exception routine */
514  return NULL;
515  }
516  }
517 
518  /* Skip all Ops with an offset greater than the current Offset */
519  i = 0;
520  while ((i < UnwindInfo->CountOfCodes) &&
521  (UnwindInfo->UnwindCode[i].CodeOffset > CodeOffset))
522  {
523  i += UnwindOpSlots(UnwindInfo->UnwindCode[i]);
524  }
525 
526 RepeatChainedInfo:
527 
528  /* Process the remaining unwind ops */
529  while (i < UnwindInfo->CountOfCodes)
530  {
531  UnwindCode = UnwindInfo->UnwindCode[i];
532  switch (UnwindCode.UnwindOp)
533  {
534  case UWOP_PUSH_NONVOL:
535  Reg = UnwindCode.OpInfo;
536  PopReg(Context, ContextPointers, Reg);
537  i++;
538  break;
539 
540  case UWOP_ALLOC_LARGE:
541  if (UnwindCode.OpInfo)
542  {
543  Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i+1]);
544  Context->Rsp += Offset;
545  i += 3;
546  }
547  else
548  {
549  Offset = UnwindInfo->UnwindCode[i+1].FrameOffset;
550  Context->Rsp += Offset * 8;
551  i += 2;
552  }
553  break;
554 
555  case UWOP_ALLOC_SMALL:
556  Context->Rsp += (UnwindCode.OpInfo + 1) * 8;
557  i++;
558  break;
559 
560  case UWOP_SET_FPREG:
561  Reg = UnwindInfo->FrameRegister;
562  Context->Rsp = GetReg(Context, Reg) - UnwindInfo->FrameOffset * 16;
563  i++;
564  break;
565 
566  case UWOP_SAVE_NONVOL:
567  Reg = UnwindCode.OpInfo;
568  Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
569  SetRegFromStackValue(Context, ContextPointers, Reg, (DWORD64*)Context->Rsp + Offset);
570  i += 2;
571  break;
572 
574  Reg = UnwindCode.OpInfo;
575  Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i + 1]);
576  SetRegFromStackValue(Context, ContextPointers, Reg, (DWORD64*)Context->Rsp + Offset);
577  i += 3;
578  break;
579 
580  case UWOP_EPILOG:
581  i += 1;
582  break;
583 
584  case UWOP_SPARE_CODE:
585  ASSERT(FALSE);
586  i += 2;
587  break;
588 
589  case UWOP_SAVE_XMM128:
590  Reg = UnwindCode.OpInfo;
591  Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
592  SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
593  i += 2;
594  break;
595 
597  Reg = UnwindCode.OpInfo;
598  Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i + 1]);
599  SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
600  i += 3;
601  break;
602 
603  case UWOP_PUSH_MACHFRAME:
604  /* OpInfo is 1, when an error code was pushed, otherwise 0. */
605  Context->Rsp += UnwindCode.OpInfo * sizeof(DWORD64);
606 
607  /* Now pop the MACHINE_FRAME (Yes, "magic numbers", deal with it) */
608  Context->Rip = *(PDWORD64)(Context->Rsp + 0x00);
609  Context->SegCs = *(PDWORD64)(Context->Rsp + 0x08);
610  Context->EFlags = *(PDWORD64)(Context->Rsp + 0x10);
611  Context->SegSs = *(PDWORD64)(Context->Rsp + 0x20);
612  Context->Rsp = *(PDWORD64)(Context->Rsp + 0x18);
613  ASSERT((i + 1) == UnwindInfo->CountOfCodes);
614  goto Exit;
615  }
616  }
617 
618  /* Check for chained info */
619  if (UnwindInfo->Flags & UNW_FLAG_CHAININFO)
620  {
621  /* See https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-160#chained-unwind-info-structures */
622  FunctionEntry = (PRUNTIME_FUNCTION)&(UnwindInfo->UnwindCode[(UnwindInfo->CountOfCodes + 1) & ~1]);
623  UnwindInfo = RVA(ImageBase, FunctionEntry->UnwindData);
624  i = 0;
625  goto RepeatChainedInfo;
626  }
627 
628  /* Unwind is finished, pop new Rip from Stack */
629  if (Context->Rsp != 0)
630  {
631  Context->Rip = *(DWORD64*)Context->Rsp;
632  Context->Rsp += sizeof(DWORD64);
633  }
634 
635 Exit:
636 
637  /* Check if we have a handler and return it */
638  if (UnwindInfo->Flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
639  {
640  return RVA(ImageBase, *LanguageHandler);
641  }
642 
643  return NULL;
644 }
645 
657 BOOLEAN
658 NTAPI
660  _In_opt_ PVOID TargetFrame,
661  _In_opt_ PVOID TargetIp,
662  _In_ PEXCEPTION_RECORD ExceptionRecord,
665  _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable,
667 {
669  PEXCEPTION_ROUTINE ExceptionRoutine;
671  PRUNTIME_FUNCTION FunctionEntry;
672  ULONG_PTR StackLow, StackHigh;
673  ULONG64 ImageBase, EstablisherFrame;
674  CONTEXT UnwindContext;
675 
676  /* Get the current stack limits and registration frame */
677  RtlpGetStackLimits(&StackLow, &StackHigh);
678 
679  /* If we have a target frame, then this is our high limit */
680  if (TargetFrame != NULL)
681  {
682  StackHigh = (ULONG64)TargetFrame + 1;
683  }
684 
685  /* Copy the context */
686  UnwindContext = *ContextRecord;
687 
688  /* Set up the constant fields of the dispatcher context */
689  DispatcherContext.ContextRecord = ContextRecord;
690  DispatcherContext.HistoryTable = HistoryTable;
691  DispatcherContext.TargetIp = (ULONG64)TargetIp;
692 
693  /* Start looping */
694  while (TRUE)
695  {
696  /* Lookup the FunctionEntry for the current RIP */
697  FunctionEntry = RtlLookupFunctionEntry(UnwindContext.Rip, &ImageBase, NULL);
698  if (FunctionEntry == NULL)
699  {
700  /* No function entry, so this must be a leaf function. Pop the return address from the stack.
701  Note: this can happen after the first frame as the result of an exception */
702  UnwindContext.Rip = *(DWORD64*)UnwindContext.Rsp;
703  UnwindContext.Rsp += sizeof(DWORD64);
704 
705  /* Copy the context back for the next iteration */
706  *ContextRecord = UnwindContext;
707  continue;
708  }
709 
710  /* Save Rip before the virtual unwind */
711  DispatcherContext.ControlPc = UnwindContext.Rip;
712 
713  /* Do a virtual unwind to get the next frame */
714  ExceptionRoutine = RtlVirtualUnwind(HandlerType,
715  ImageBase,
716  UnwindContext.Rip,
717  FunctionEntry,
718  &UnwindContext,
719  &DispatcherContext.HandlerData,
721  NULL);
722 
723  /* Check, if we are still within the stack boundaries */
724  if ((EstablisherFrame < StackLow) ||
725  (EstablisherFrame >= StackHigh) ||
726  (EstablisherFrame & 7))
727  {
729 
730  /* If we are handling an exception, we are done here. */
732  {
733  ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
734  return FALSE;
735  }
736 
737  __debugbreak();
739  }
740 
741  /* Check if we have an exception routine */
742  if (ExceptionRoutine != NULL)
743  {
744  /* Check if this is the target frame */
745  if (EstablisherFrame == (ULONG64)TargetFrame)
746  {
747  /* Set flag to inform the language handler */
748  ExceptionRecord->ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
749  }
750 
751  /* Log the exception if it's enabled */
752  RtlpCheckLogException(ExceptionRecord,
755  sizeof(DispatcherContext));
756 
757  /* Set up the variable fields of the dispatcher context */
758  DispatcherContext.ImageBase = ImageBase;
759  DispatcherContext.FunctionEntry = FunctionEntry;
760  DispatcherContext.LanguageHandler = ExceptionRoutine;
761  DispatcherContext.EstablisherFrame = EstablisherFrame;
762  DispatcherContext.ScopeIndex = 0;
763 
764  /* Store the return value in the unwind context */
765  UnwindContext.Rax = (ULONG64)ReturnValue;
766 
767  /* Loop all nested handlers */
768  do
769  {
771  /* Call the language specific handler */
772  Disposition = ExceptionRoutine(ExceptionRecord,
774  &UnwindContext,
776 
777  /* Clear exception flags for the next iteration */
778  ExceptionRecord->ExceptionFlags &= ~(EXCEPTION_TARGET_UNWIND |
780 
781  /* Check if we do exception handling */
783  {
785  {
786  /* Check if it was non-continuable */
787  if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
788  {
789  __debugbreak();
791  }
792 
793  /* Execution continues */
794  return TRUE;
795  }
797  {
799  __debugbreak();
800  }
801  }
802 
804  {
806  __debugbreak();
807  }
808 
809  /* This must be ExceptionContinueSearch now */
811  {
812  __debugbreak();
814  }
815  } while (ExceptionRecord->ExceptionFlags & EXCEPTION_COLLIDED_UNWIND);
816  }
817 
818  /* Check, if we have left our stack (8.) */
819  if ((EstablisherFrame < StackLow) ||
820  (EstablisherFrame > StackHigh) ||
821  (EstablisherFrame & 7))
822  {
824  __debugbreak();
825 
826  if (UnwindContext.Rip == ContextRecord->Rip)
827  {
829  }
830  else
831  {
832  ZwRaiseException(ExceptionRecord, ContextRecord, FALSE);
833  }
834  }
835 
836  if (EstablisherFrame == (ULONG64)TargetFrame)
837  {
838  break;
839  }
840 
841  /* We have successfully unwound a frame. Copy the unwind context back. */
842  *ContextRecord = UnwindContext;
843  }
844 
845  if (ExceptionRecord->ExceptionCode != STATUS_UNWIND_CONSOLIDATE)
846  {
847  ContextRecord->Rip = (ULONG64)TargetIp;
848  }
849 
850  /* Set the return value */
852 
853  /* Restore the context */
854  RtlRestoreContext(ContextRecord, ExceptionRecord);
855 
856  /* Should never get here! */
857  ASSERT(FALSE);
858  return FALSE;
859 }
860 
861 VOID
862 NTAPI
864  _In_opt_ PVOID TargetFrame,
865  _In_opt_ PVOID TargetIp,
866  _In_opt_ PEXCEPTION_RECORD ExceptionRecord,
869  _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable)
870 {
871  EXCEPTION_RECORD LocalExceptionRecord;
872 
873  /* Capture the current context */
875 
876  /* Check if we have an exception record */
877  if (ExceptionRecord == NULL)
878  {
879  /* No exception record was passed, so set up a local one */
880  LocalExceptionRecord.ExceptionCode = STATUS_UNWIND;
881  LocalExceptionRecord.ExceptionAddress = (PVOID)ContextRecord->Rip;
882  LocalExceptionRecord.ExceptionRecord = NULL;
883  LocalExceptionRecord.NumberParameters = 0;
884  ExceptionRecord = &LocalExceptionRecord;
885  }
886 
887  /* Call the internal function */
888  RtlpUnwindInternal(TargetFrame,
889  TargetIp,
890  ExceptionRecord,
891  ReturnValue,
893  HistoryTable,
895 }
896 
897 VOID
898 NTAPI
900  IN PVOID TargetFrame,
901  IN PVOID TargetIp,
902  IN PEXCEPTION_RECORD ExceptionRecord,
904 {
906  return;
907 }
908 
909 ULONG
910 NTAPI
912  IN ULONG Count,
913  IN ULONG Flags)
914 {
916  ULONG64 ControlPc, ImageBase, EstablisherFrame;
917  ULONG64 StackLow, StackHigh;
918  PVOID HandlerData;
919  ULONG i, FramesToSkip;
920  PRUNTIME_FUNCTION FunctionEntry;
921 
922  DPRINT("Enter RtlWalkFrameChain\n");
923 
924  /* The upper bits in Flags define how many frames to skip */
925  FramesToSkip = Flags >> 8;
926 
927  /* Capture the current Context */
929  ControlPc = Context.Rip;
930 
931  /* Get the stack limits */
932  RtlpGetStackLimits(&StackLow, &StackHigh);
933 
934  /* Check if we want the user-mode stack frame */
935  if (Flags & 1)
936  {
937  }
938 
939  _SEH2_TRY
940  {
941  /* Loop the frames */
942  for (i = 0; i < FramesToSkip + Count; i++)
943  {
944  /* Lookup the FunctionEntry for the current ControlPc */
945  FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
946 
947  /* Is this a leaf function? */
948  if (!FunctionEntry)
949  {
950  Context.Rip = *(DWORD64*)Context.Rsp;
951  Context.Rsp += sizeof(DWORD64);
952  DPRINT("leaf funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
953  }
954  else
955  {
957  ImageBase,
958  ControlPc,
959  FunctionEntry,
960  &Context,
961  &HandlerData,
963  NULL);
964  DPRINT("normal funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
965  }
966 
967  /* Check if we are in kernel mode */
968  if (RtlpGetMode() == KernelMode)
969  {
970  /* Check if we left the kernel range */
971  if (!(Flags & 1) && (Context.Rip < 0xFFFF800000000000ULL))
972  {
973  break;
974  }
975  }
976  else
977  {
978  /* Check if we left the user range */
979  if ((Context.Rip < 0x10000) ||
980  (Context.Rip > 0x000007FFFFFEFFFFULL))
981  {
982  break;
983  }
984  }
985 
986  /* Check, if we have left our stack */
987  if ((Context.Rsp < StackLow) || (Context.Rsp > StackHigh))
988  {
989  break;
990  }
991 
992  /* Continue with new Rip */
993  ControlPc = Context.Rip;
994 
995  /* Save value, if we are past the frames to skip */
996  if (i >= FramesToSkip)
997  {
998  Callers[i - FramesToSkip] = (PVOID)ControlPc;
999  }
1000  }
1001  }
1003  {
1004  DPRINT1("Exception while getting callers!\n");
1005  i = 0;
1006  }
1007  _SEH2_END;
1008 
1009  DPRINT("RtlWalkFrameChain returns %ld\n", i);
1010  return i;
1011 }
1012 
1016 #undef RtlGetCallersAddress
1017 VOID
1018 NTAPI
1020  OUT PVOID *CallersAddress,
1021  OUT PVOID *CallersCaller )
1022 {
1023  PVOID Callers[4];
1024  ULONG Number;
1025 
1026  /* Get callers:
1027  * RtlWalkFrameChain -> RtlGetCallersAddress -> x -> y */
1028  Number = RtlWalkFrameChain(Callers, 4, 0);
1029 
1030  *CallersAddress = (Number >= 3) ? Callers[2] : NULL;
1031  *CallersCaller = (Number == 4) ? Callers[3] : NULL;
1032 
1033  return;
1034 }
1035 
1036 static
1037 VOID
1039  _Out_ PKNONVOLATILE_CONTEXT_POINTERS NonvolatileContextPointers,
1040  _In_ ULONG64 TargetFrame)
1041 {
1042  CONTEXT Context;
1043  PRUNTIME_FUNCTION FunctionEntry;
1044  ULONG64 ImageBase;
1045  PVOID HandlerData;
1047 
1048  /* Zero out the nonvolatile context pointers */
1049  RtlZeroMemory(NonvolatileContextPointers, sizeof(*NonvolatileContextPointers));
1050 
1051  /* Capture the current context */
1053 
1054  do
1055  {
1056  /* Look up the function entry */
1057  FunctionEntry = RtlLookupFunctionEntry(Context.Rip, &ImageBase, NULL);
1058  ASSERT(FunctionEntry != NULL);
1059 
1060  /* Do a virtual unwind to the caller and capture saved non-volatiles */
1062  ImageBase,
1063  Context.Rip,
1064  FunctionEntry,
1065  &Context,
1066  &HandlerData,
1068  NonvolatileContextPointers);
1069 
1070  /* Make sure nothing fishy is going on. Currently this is for kernel mode only. */
1071  ASSERT(EstablisherFrame != 0);
1072  ASSERT((LONG64)Context.Rip < 0);
1073 
1074  /* Continue until we reached the target frame or user mode */
1075  } while (EstablisherFrame < TargetFrame);
1076 
1077  /* If the caller did the right thing, we should get exactly the target frame */
1078  ASSERT(EstablisherFrame == TargetFrame);
1079 }
1080 
1081 VOID
1084  _In_ DWORD64 TargetFrame)
1085 {
1086  KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
1087 
1088  /* Capture pointers to the non-volatiles up to the target frame */
1089  RtlpCaptureNonVolatileContextPointers(&ContextPointers, TargetFrame);
1090 
1091  /* Copy the nonvolatiles to the captured locations */
1092  *ContextPointers.R12 = Context->R12;
1093  *ContextPointers.R13 = Context->R13;
1094  *ContextPointers.R14 = Context->R14;
1095  *ContextPointers.R15 = Context->R15;
1096  *ContextPointers.Xmm6 = Context->Xmm6;
1097  *ContextPointers.Xmm7 = Context->Xmm7;
1098  *ContextPointers.Xmm8 = Context->Xmm8;
1099  *ContextPointers.Xmm9 = Context->Xmm9;
1100  *ContextPointers.Xmm10 = Context->Xmm10;
1101  *ContextPointers.Xmm11 = Context->Xmm11;
1102  *ContextPointers.Xmm12 = Context->Xmm12;
1103  *ContextPointers.Xmm13 = Context->Xmm13;
1104  *ContextPointers.Xmm14 = Context->Xmm14;
1105  *ContextPointers.Xmm15 = Context->Xmm15;
1106 }
_SEH2_TRY
Definition: create.c:4226
#define STATUS_UNWIND_CONSOLIDATE
Definition: ntstatus.h:220
#define EXCEPTION_NONCONTINUABLE_EXCEPTION
Definition: winbase.h:325
#define IN
Definition: typedefs.h:39
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
ASMGENDATA Table[]
Definition: genincdata.c:61
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_
Definition: ms_sal.h:378
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:82
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:653
UBYTE FrameOffset
Definition: unwind.c:57
#define _Out_
Definition: ms_sal.h:345
BOOLEAN NTAPI RtlpUnwindInternal(_In_opt_ PVOID TargetFrame, _In_opt_ PVOID TargetIp, _In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PVOID ReturnValue, _In_ PCONTEXT ContextRecord, _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable, _In_ ULONG HandlerType)
Definition: unwind.c:659
#define TRUE
Definition: types.h:120
#define STATUS_BAD_STACK
Definition: ntstatus.h:277
M128A
Definition: ketypes.h:925
static __inline BOOLEAN RtlpTryToUnwindEpilog(_Inout_ PCONTEXT Context, _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, _In_ ULONG64 ImageBase, _In_ PRUNTIME_FUNCTION FunctionEntry)
Helper function that tries to unwind epilog instructions.
Definition: unwind.c:304
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_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
Definition: unwind.c:469
#define UWOP_SPARE_CODE
Definition: unwind.c:30
#define _Outptr_
Definition: ms_sal.h:427
NTSYSAPI NTSTATUS NTAPI ZwRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames)
BYTE UnwindOp
Definition: cpu_x86_64.c:54
#define EXCEPTION_NONCONTINUABLE
Definition: rtltypes.h:154
struct _UNWIND_INFO UNWIND_INFO
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static ULONG64 GetEstablisherFrame(_In_ PCONTEXT Context, _In_ PUNWIND_INFO UnwindInfo, _In_ ULONG_PTR CodeOffset)
Definition: unwind.c:430
_SEH2_END
Definition: create.c:4400
#define UWOP_EPILOG
Definition: unwind.c:29
static __inline DWORD64 GetReg(_In_ PCONTEXT Context, _In_ BYTE Reg)
Definition: unwind.c:237
PVOID NTAPI RtlPcToFileHeader(IN PVOID PcValue, PVOID *BaseOfImage)
Definition: libsupp.c:659
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
#define UWOP_PUSH_NONVOL
Definition: unwind.c:19
static __inline M128A GetXmmReg(PCONTEXT Context, BYTE Reg)
Definition: unwind.c:286
#define STATUS_BAD_FUNCTION_TABLE
Definition: ntstatus.h:491
PVOID ExceptionAddress
Definition: compat.h:211
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define UWOP_SET_FPREG
Definition: unwind.c:22
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE ACPI_HANDLE *OutHandle ACPI_HANDLE *OutHandle void *Context void *Context ACPI_EVENT_HANDLER Handler UINT32 UINT32 ACPI_GPE_HANDLER void *Context UINT32 HandlerType
Definition: acpixf.h:813
DWORD ExceptionCode
Definition: compat.h:208
UBYTE UnwindOp
Definition: unwind.c:44
UINT32 void void ** ReturnValue
Definition: acevents.h:214
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define STATUS_INVALID_DISPOSITION
Definition: ntstatus.h:275
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:654
#define EXCEPTION_TARGET_UNWIND
Definition: rtltypes.h:159
BYTE CodeOffset
Definition: cpu_x86_64.c:53
#define UWOP_ALLOC_LARGE
Definition: unwind.c:20
#define UWOP_SAVE_XMM128_FAR
Definition: unwind.c:33
union _UNWIND_CODE UNWIND_CODE
unsigned char BOOLEAN
#define _In_
Definition: ms_sal.h:308
#define UWOP_PUSH_MACHFRAME
Definition: unwind.c:34
void * PVOID
Definition: retypes.h:9
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: unwind.c:863
UBYTE Flags
Definition: unwind.c:53
#define EXCEPTION_STACK_INVALID
Definition: rtltypes.h:157
EXCEPTION_ROUTINE * PEXCEPTION_ROUTINE
Definition: compat.h:568
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
int64_t LONG64
Definition: typedefs.h:68
int Count
Definition: noreturn.cpp:7
union _UNWIND_CODE * PUNWIND_CODE
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
static __inline void SetXmmRegFromStackValue(_Out_ PCONTEXT Context, _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, _In_ BYTE Reg, _In_ M128A *ValuePointer)
Definition: unwind.c:270
#define ASSERT(a)
Definition: mode.c:44
UBYTE Version
Definition: unwind.c:52
UBYTE FrameRegister
Definition: unwind.c:56
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char UBYTE
Definition: unwind.c:37
#define EXCEPTION_COLLIDED_UNWIND
Definition: rtltypes.h:160
static void Exit(void)
Definition: sock.c:1331
#define UWOP_SAVE_XMM128
Definition: unwind.c:32
unsigned long DWORD
Definition: ntddk_ex.h:95
static __inline ULONG UnwindOpSlots(_In_ UNWIND_CODE UnwindCode)
Definition: unwind.c:177
struct _RUNTIME_FUNCTION RUNTIME_FUNCTION
#define UWOP_ALLOC_SMALL
Definition: unwind.c:21
unsigned char UBYTE
Definition: lzx.c:48
struct _RUNTIME_FUNCTION * PRUNTIME_FUNCTION
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:654
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned char UCHAR
Definition: xmlstorage.h:181
UBYTE OpInfo
Definition: unwind.c:45
#define RtlImageDirectoryEntryToData
Definition: compat.h:668
#define ALIGN_UP_POINTER_BY(ptr, align)
Definition: umtypes.h:85
#define _Inout_opt_
Definition: ms_sal.h:379
VOID RtlSetUnwindContext(_In_ PCONTEXT Context, _In_ DWORD64 TargetFrame)
Definition: unwind.c:1082
VOID NTAPI RtlpGetStackLimits(PULONG_PTR StackBase, PULONG_PTR StackLimit)
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
UNWIND_CODE UnwindCode[1]
Definition: cpu_x86_64.c:68
unsigned char BYTE
Definition: xxhash.c:193
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define RVA(m, b)
Definition: freeldr.h:24
UBYTE SizeOfProlog
Definition: unwind.c:54
USHORT FrameOffset
Definition: cpu_x86_64.c:57
struct _UNWIND_INFO * PUNWIND_INFO
uint64_t DWORD64
Definition: typedefs.h:67
static __inline void PopReg(_Inout_ PCONTEXT Context, _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, _In_ BYTE Reg)
Definition: unwind.c:247
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned short USHORT
Definition: pedump.c:61
static __inline void SetReg(_Inout_ PCONTEXT Context, _In_ BYTE Reg, _In_ DWORD64 Value)
Definition: unwind.c:210
unsigned int * PULONG
Definition: retypes.h:1
#define STATUS_UNWIND
Definition: ntstatus.h:276
#define NULL
Definition: types.h:112
UBYTE CodeOffset
Definition: unwind.c:43
#define DPRINT1
Definition: precomp.h:8
#define UWOP_SAVE_NONVOL_FAR
Definition: unwind.c:24
VOID NTAPI RtlUnwind(IN PVOID TargetFrame, IN PVOID TargetIp, IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID ReturnValue)
Definition: unwind.c:899
struct tagContext Context
Definition: acpixf.h:1034
#define OUT
Definition: typedefs.h:40
VOID NTAPI RtlGetCallersAddress(OUT PVOID *CallersAddress, OUT PVOID *CallersCaller)
Definition: unwind.c:1019
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN PVOID ContextData, IN ULONG Size)
Definition: libsupp.c:201
uint64_t * PDWORD64
Definition: typedefs.h:67
enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION
#define UNIMPLEMENTED
Definition: debug.h:115
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static __inline void SetRegFromStackValue(_Inout_ PCONTEXT Context, _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, _In_ BYTE Reg, _In_ PDWORD64 ValuePointer)
Definition: unwind.c:221
static WLX_DISPATCH_VERSION_1_4 FunctionTable
Definition: wlx.c:722
#define UWOP_SAVE_NONVOL
Definition: unwind.c:23
unsigned __int64 * PULONG64
Definition: imports.h:198
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags)
Definition: unwind.c:911
DWORD NumberParameters
Definition: compat.h:212
#define DPRINT
Definition: sndvol32.h:71
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....
Definition: unwind.c:124
static VOID RtlpCaptureNonVolatileContextPointers(_Out_ PKNONVOLATILE_CONTEXT_POINTERS NonvolatileContextPointers, _In_ ULONG64 TargetFrame)
Definition: unwind.c:1038
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION
Definition: pedump.c:262
UBYTE CountOfCodes
Definition: unwind.c:55
PRUNTIME_FUNCTION NTAPI RtlpLookupDynamicFunctionEntry(_In_ DWORD64 ControlPc, _Out_ PDWORD64 ImageBase, _In_ PUNWIND_HISTORY_TABLE HistoryTable)
Definition: dynfntbl.c:271
#define UNW_FLAG_NHANDLER
Definition: gs_support.c:32
static __inline void SetXmmReg(_Inout_ PCONTEXT Context, _In_ BYTE Reg, _In_ M128A Value)
Definition: unwind.c:259