ReactOS  0.4.15-dev-3207-ga415bd4
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 
116 NTAPI
118  IN DWORD64 ControlPc,
119  OUT PDWORD64 ImageBase,
120  OUT PUNWIND_HISTORY_TABLE HistoryTable)
121 {
122  PRUNTIME_FUNCTION FunctionTable, FunctionEntry;
123  ULONG TableLength;
124  ULONG IndexLo, IndexHi, IndexMid;
125 
126  /* Find the corresponding table */
127  FunctionTable = RtlLookupFunctionTable(ControlPc, ImageBase, &TableLength);
128 
129  /* Fail, if no table is found */
130  if (!FunctionTable)
131  {
132  return NULL;
133  }
134 
135  /* Use relative virtual address */
136  ControlPc -= *ImageBase;
137 
138  /* Do a binary search */
139  IndexLo = 0;
140  IndexHi = TableLength;
141  while (IndexHi > IndexLo)
142  {
143  IndexMid = (IndexLo + IndexHi) / 2;
144  FunctionEntry = &FunctionTable[IndexMid];
145 
146  if (ControlPc < FunctionEntry->BeginAddress)
147  {
148  /* Continue search in lower half */
149  IndexHi = IndexMid;
150  }
151  else if (ControlPc >= FunctionEntry->EndAddress)
152  {
153  /* Continue search in upper half */
154  IndexLo = IndexMid + 1;
155  }
156  else
157  {
158  /* ControlPc is within limits, return entry */
159  return FunctionEntry;
160  }
161  }
162 
163  /* Nothing found, return NULL */
164  return NULL;
165 }
166 
167 BOOLEAN
168 NTAPI
171  IN DWORD EntryCount,
173 {
175  return FALSE;
176 }
177 
178 BOOLEAN
179 NTAPI
182 {
184  return FALSE;
185 }
186 
187 BOOLEAN
188 NTAPI
190  IN DWORD64 TableIdentifier,
192  IN DWORD Length,
193  IN PGET_RUNTIME_FUNCTION_CALLBACK Callback,
194  IN PVOID Context,
195  IN PCWSTR OutOfProcessCallbackDll)
196 {
198  return FALSE;
199 }
200 
201 static
202 __inline
203 ULONG
205  _In_ UNWIND_CODE UnwindCode)
206 {
207  static const UCHAR UnwindOpExtraSlotTable[] =
208  {
209  0, // UWOP_PUSH_NONVOL
210  1, // UWOP_ALLOC_LARGE (or 3, special cased in lookup code)
211  0, // UWOP_ALLOC_SMALL
212  0, // UWOP_SET_FPREG
213  1, // UWOP_SAVE_NONVOL
214  2, // UWOP_SAVE_NONVOL_FAR
215  1, // UWOP_EPILOG // previously UWOP_SAVE_XMM
216  2, // UWOP_SPARE_CODE // previously UWOP_SAVE_XMM_FAR
217  1, // UWOP_SAVE_XMM128
218  2, // UWOP_SAVE_XMM128_FAR
219  0, // UWOP_PUSH_MACHFRAME
220  2, // UWOP_SET_FPREG_LARGE
221  };
222 
223  if ((UnwindCode.UnwindOp == UWOP_ALLOC_LARGE) &&
224  (UnwindCode.OpInfo != 0))
225  {
226  return 3;
227  }
228  else
229  {
230  return UnwindOpExtraSlotTable[UnwindCode.UnwindOp] + 1;
231  }
232 }
233 
234 static
235 __inline
236 void
239  _In_ BYTE Reg,
241 {
242  ((DWORD64*)(&Context->Rax))[Reg] = Value;
243 }
244 
245 static
246 __inline
247 void
250  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
251  _In_ BYTE Reg,
252  _In_ PDWORD64 ValuePointer)
253 {
254  SetReg(Context, Reg, *ValuePointer);
255  if (ContextPointers != NULL)
256  {
257  ContextPointers->IntegerContext[Reg] = ValuePointer;
258  }
259 }
260 
261 static
262 __inline
263 DWORD64
266  _In_ BYTE Reg)
267 {
268  return ((DWORD64*)(&Context->Rax))[Reg];
269 }
270 
271 static
272 __inline
273 void
276  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
277  _In_ BYTE Reg)
278 {
279  SetRegFromStackValue(Context, ContextPointers, Reg, (PDWORD64)Context->Rsp);
280  Context->Rsp += sizeof(DWORD64);
281 }
282 
283 static
284 __inline
285 void
288  _In_ BYTE Reg,
289  _In_ M128A Value)
290 {
291  ((M128A*)(&Context->Xmm0))[Reg] = Value;
292 }
293 
294 static
295 __inline
296 void
299  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
300  _In_ BYTE Reg,
301  _In_ M128A *ValuePointer)
302 {
303  SetXmmReg(Context, Reg, *ValuePointer);
304  if (ContextPointers != NULL)
305  {
306  ContextPointers->FloatingContext[Reg] = ValuePointer;
307  }
308 }
309 
310 static
311 __inline
312 M128A
314 {
315  return ((M128A*)(&Context->Xmm0))[Reg];
316 }
317 
328 static
329 __inline
330 BOOLEAN
333  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
334  _In_ ULONG64 ImageBase,
335  _In_ PRUNTIME_FUNCTION FunctionEntry)
336 {
337  CONTEXT LocalContext;
338  BYTE *InstrPtr;
339  DWORD Instr;
340  BYTE Reg, Mod;
341  ULONG64 EndAddress;
342 
343  /* Make a local copy of the context */
344  LocalContext = *Context;
345 
346  InstrPtr = (BYTE*)LocalContext.Rip;
347 
348  /* Check if first instruction of epilog is "add rsp, x" */
349  Instr = *(DWORD*)InstrPtr;
350  if ( (Instr & 0x00fffdff) == 0x00c48148 )
351  {
352  if ( (Instr & 0x0000ff00) == 0x8300 )
353  {
354  /* This is "add rsp, 0x??" */
355  LocalContext.Rsp += Instr >> 24;
356  InstrPtr += 4;
357  }
358  else
359  {
360  /* This is "add rsp, 0x???????? */
361  LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
362  InstrPtr += 7;
363  }
364  }
365  /* Check if first instruction of epilog is "lea rsp, ..." */
366  else if ( (Instr & 0x38fffe) == 0x208d48 )
367  {
368  /* Get the register */
369  Reg = ((Instr << 8) | (Instr >> 16)) & 0x7;
370 
371  LocalContext.Rsp = GetReg(&LocalContext, Reg);
372 
373  /* Get adressing mode */
374  Mod = (Instr >> 22) & 0x3;
375  if (Mod == 0)
376  {
377  /* No displacement */
378  InstrPtr += 3;
379  }
380  else if (Mod == 1)
381  {
382  /* 1 byte displacement */
383  LocalContext.Rsp += Instr >> 24;
384  InstrPtr += 4;
385  }
386  else if (Mod == 2)
387  {
388  /* 4 bytes displacement */
389  LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
390  InstrPtr += 7;
391  }
392  }
393 
394  /* Loop the following instructions before the ret */
395  EndAddress = FunctionEntry->EndAddress + ImageBase - 1;
396  while ((DWORD64)InstrPtr < EndAddress)
397  {
398  Instr = *(DWORD*)InstrPtr;
399 
400  /* Check for a simple pop */
401  if ( (Instr & 0xf8) == 0x58 )
402  {
403  /* Opcode pops a basic register from stack */
404  Reg = Instr & 0x7;
405  PopReg(&LocalContext, ContextPointers, Reg);
406  InstrPtr++;
407  continue;
408  }
409 
410  /* Check for REX + pop */
411  if ( (Instr & 0xf8fb) == 0x5841 )
412  {
413  /* Opcode is pop r8 .. r15 */
414  Reg = ((Instr >> 8) & 0x7) + 8;
415  PopReg(&LocalContext, ContextPointers, Reg);
416  InstrPtr += 2;
417  continue;
418  }
419 
420  /* Opcode not allowed for Epilog */
421  return FALSE;
422  }
423 
424  // check for popfq
425 
426  // also allow end with jmp imm, jmp [target], iretq
427 
428  /* Check if we are at the ret instruction */
429  if ((DWORD64)InstrPtr != EndAddress)
430  {
431  /* If we went past the end of the function, something is broken! */
432  ASSERT((DWORD64)InstrPtr <= EndAddress);
433  return FALSE;
434  }
435 
436  /* Make sure this is really a ret instruction */
437  if (*InstrPtr != 0xc3)
438  {
439  ASSERT(FALSE);
440  return FALSE;
441  }
442 
443  /* Unwind is finished, pop new Rip from Stack */
444  LocalContext.Rip = *(DWORD64*)LocalContext.Rsp;
445  LocalContext.Rsp += sizeof(DWORD64);
446 
447  *Context = LocalContext;
448  return TRUE;
449 }
450 
455 static
456 ULONG64
459  _In_ PUNWIND_INFO UnwindInfo,
460  _In_ ULONG_PTR CodeOffset)
461 {
462  ULONG i;
463 
464  /* Check if we have a frame register */
465  if (UnwindInfo->FrameRegister == 0)
466  {
467  /* No frame register means we use Rsp */
468  return Context->Rsp;
469  }
470 
471  if ((CodeOffset >= UnwindInfo->SizeOfProlog) ||
472  ((UnwindInfo->Flags & UNW_FLAG_CHAININFO) != 0))
473  {
474  return GetReg(Context, UnwindInfo->FrameRegister) -
475  UnwindInfo->FrameOffset * 16;
476  }
477 
478  /* Loop all unwind ops */
479  for (i = 0;
480  i < UnwindInfo->CountOfCodes;
481  i += UnwindOpSlots(UnwindInfo->UnwindCode[i]))
482  {
483  /* Check for SET_FPREG */
484  if (UnwindInfo->UnwindCode[i].UnwindOp == UWOP_SET_FPREG)
485  {
486  return GetReg(Context, UnwindInfo->FrameRegister) -
487  UnwindInfo->FrameOffset * 16;
488  }
489  }
490 
491  return Context->Rsp;
492 }
493 
495 NTAPI
498  _In_ ULONG64 ImageBase,
499  _In_ ULONG64 ControlPc,
500  _In_ PRUNTIME_FUNCTION FunctionEntry,
502  _Outptr_ PVOID *HandlerData,
504  _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
505 {
506  PUNWIND_INFO UnwindInfo;
507  ULONG_PTR CodeOffset;
508  ULONG i, Offset;
509  UNWIND_CODE UnwindCode;
510  BYTE Reg;
511  PULONG LanguageHandler;
512 
513  /* Use relative virtual address */
514  ControlPc -= ImageBase;
515 
516  /* Sanity checks */
517  if ( (ControlPc < FunctionEntry->BeginAddress) ||
518  (ControlPc >= FunctionEntry->EndAddress) )
519  {
520  return NULL;
521  }
522 
523  /* Get a pointer to the unwind info */
524  UnwindInfo = RVA(ImageBase, FunctionEntry->UnwindData);
525 
526  /* The language specific handler data follows the unwind info */
527  LanguageHandler = ALIGN_UP_POINTER_BY(&UnwindInfo->UnwindCode[UnwindInfo->CountOfCodes], sizeof(ULONG));
528  *HandlerData = (LanguageHandler + 1);
529 
530  /* Calculate relative offset to function start */
531  CodeOffset = ControlPc - FunctionEntry->BeginAddress;
532 
533  *EstablisherFrame = GetEstablisherFrame(Context, UnwindInfo, CodeOffset);
534 
535  /* Check if we are in the function epilog and try to finish it */
536  if (CodeOffset > UnwindInfo->SizeOfProlog)
537  {
538  if (RtlpTryToUnwindEpilog(Context, ContextPointers, ImageBase, FunctionEntry))
539  {
540  /* There's no exception routine */
541  return NULL;
542  }
543  }
544 
545  /* Skip all Ops with an offset greater than the current Offset */
546  i = 0;
547  while ((i < UnwindInfo->CountOfCodes) &&
548  (UnwindInfo->UnwindCode[i].CodeOffset > CodeOffset))
549  {
550  i += UnwindOpSlots(UnwindInfo->UnwindCode[i]);
551  }
552 
553 RepeatChainedInfo:
554 
555  /* Process the remaining unwind ops */
556  while (i < UnwindInfo->CountOfCodes)
557  {
558  UnwindCode = UnwindInfo->UnwindCode[i];
559  switch (UnwindCode.UnwindOp)
560  {
561  case UWOP_PUSH_NONVOL:
562  Reg = UnwindCode.OpInfo;
563  PopReg(Context, ContextPointers, Reg);
564  i++;
565  break;
566 
567  case UWOP_ALLOC_LARGE:
568  if (UnwindCode.OpInfo)
569  {
570  Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i+1]);
571  Context->Rsp += Offset;
572  i += 3;
573  }
574  else
575  {
576  Offset = UnwindInfo->UnwindCode[i+1].FrameOffset;
577  Context->Rsp += Offset * 8;
578  i += 2;
579  }
580  break;
581 
582  case UWOP_ALLOC_SMALL:
583  Context->Rsp += (UnwindCode.OpInfo + 1) * 8;
584  i++;
585  break;
586 
587  case UWOP_SET_FPREG:
588  Reg = UnwindInfo->FrameRegister;
589  Context->Rsp = GetReg(Context, Reg) - UnwindInfo->FrameOffset * 16;
590  i++;
591  break;
592 
593  case UWOP_SAVE_NONVOL:
594  Reg = UnwindCode.OpInfo;
595  Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
596  SetRegFromStackValue(Context, ContextPointers, Reg, (DWORD64*)Context->Rsp + Offset);
597  i += 2;
598  break;
599 
601  Reg = UnwindCode.OpInfo;
602  Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i + 1]);
603  SetRegFromStackValue(Context, ContextPointers, Reg, (DWORD64*)Context->Rsp + Offset);
604  i += 3;
605  break;
606 
607  case UWOP_EPILOG:
608  i += 1;
609  break;
610 
611  case UWOP_SPARE_CODE:
612  ASSERT(FALSE);
613  i += 2;
614  break;
615 
616  case UWOP_SAVE_XMM128:
617  Reg = UnwindCode.OpInfo;
618  Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
619  SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
620  i += 2;
621  break;
622 
624  Reg = UnwindCode.OpInfo;
625  Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i + 1]);
626  SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
627  i += 3;
628  break;
629 
630  case UWOP_PUSH_MACHFRAME:
631  /* OpInfo is 1, when an error code was pushed, otherwise 0. */
632  Context->Rsp += UnwindCode.OpInfo * sizeof(DWORD64);
633 
634  /* Now pop the MACHINE_FRAME (Yes, "magic numbers", deal with it) */
635  Context->Rip = *(PDWORD64)(Context->Rsp + 0x00);
636  Context->SegCs = *(PDWORD64)(Context->Rsp + 0x08);
637  Context->EFlags = *(PDWORD64)(Context->Rsp + 0x10);
638  Context->SegSs = *(PDWORD64)(Context->Rsp + 0x20);
639  Context->Rsp = *(PDWORD64)(Context->Rsp + 0x18);
640  ASSERT((i + 1) == UnwindInfo->CountOfCodes);
641  goto Exit;
642  }
643  }
644 
645  /* Check for chained info */
646  if (UnwindInfo->Flags & UNW_FLAG_CHAININFO)
647  {
648  /* See https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-160#chained-unwind-info-structures */
649  FunctionEntry = (PRUNTIME_FUNCTION)&(UnwindInfo->UnwindCode[(UnwindInfo->CountOfCodes + 1) & ~1]);
650  UnwindInfo = RVA(ImageBase, FunctionEntry->UnwindData);
651  i = 0;
652  goto RepeatChainedInfo;
653  }
654 
655  /* Unwind is finished, pop new Rip from Stack */
656  if (Context->Rsp != 0)
657  {
658  Context->Rip = *(DWORD64*)Context->Rsp;
659  Context->Rsp += sizeof(DWORD64);
660  }
661 
662 Exit:
663 
664  /* Check if we have a handler and return it */
665  if (UnwindInfo->Flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
666  {
667  return RVA(ImageBase, *LanguageHandler);
668  }
669 
670  return NULL;
671 }
672 
684 BOOLEAN
685 NTAPI
687  _In_opt_ PVOID TargetFrame,
688  _In_opt_ PVOID TargetIp,
689  _In_ PEXCEPTION_RECORD ExceptionRecord,
692  _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable,
694 {
696  PEXCEPTION_ROUTINE ExceptionRoutine;
698  PRUNTIME_FUNCTION FunctionEntry;
699  ULONG_PTR StackLow, StackHigh;
700  ULONG64 ImageBase, EstablisherFrame;
701  CONTEXT UnwindContext;
702 
703  /* Get the current stack limits and registration frame */
704  RtlpGetStackLimits(&StackLow, &StackHigh);
705 
706  /* If we have a target frame, then this is our high limit */
707  if (TargetFrame != NULL)
708  {
709  StackHigh = (ULONG64)TargetFrame + 1;
710  }
711 
712  /* Copy the context */
713  UnwindContext = *ContextRecord;
714 
715  /* Set up the constant fields of the dispatcher context */
716  DispatcherContext.ContextRecord = ContextRecord;
717  DispatcherContext.HistoryTable = HistoryTable;
718  DispatcherContext.TargetIp = (ULONG64)TargetIp;
719 
720  /* Start looping */
721  while (TRUE)
722  {
723  /* Lookup the FunctionEntry for the current RIP */
724  FunctionEntry = RtlLookupFunctionEntry(UnwindContext.Rip, &ImageBase, NULL);
725  if (FunctionEntry == NULL)
726  {
727  /* No function entry, so this must be a leaf function. Pop the return address from the stack.
728  Note: this can happen after the first frame as the result of an exception */
729  UnwindContext.Rip = *(DWORD64*)UnwindContext.Rsp;
730  UnwindContext.Rsp += sizeof(DWORD64);
731  continue;
732  }
733 
734  /* Do a virtual unwind to get the next frame */
735  ExceptionRoutine = RtlVirtualUnwind(HandlerType,
736  ImageBase,
737  UnwindContext.Rip,
738  FunctionEntry,
739  &UnwindContext,
740  &DispatcherContext.HandlerData,
742  NULL);
743 
744  /* Check, if we are still within the stack boundaries */
745  if ((EstablisherFrame < StackLow) ||
746  (EstablisherFrame >= StackHigh) ||
747  (EstablisherFrame & 7))
748  {
750 
751  /* If we are handling an exception, we are done here. */
753  {
754  ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
755  return FALSE;
756  }
757 
758  __debugbreak();
760  }
761 
762  /* Check if we have an exception routine */
763  if (ExceptionRoutine != NULL)
764  {
765  /* Check if this is the target frame */
766  if (EstablisherFrame == (ULONG64)TargetFrame)
767  {
768  /* Set flag to inform the language handler */
769  ExceptionRecord->ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
770  }
771 
772  /* Log the exception if it's enabled */
773  RtlpCheckLogException(ExceptionRecord,
776  sizeof(DispatcherContext));
777 
778  /* Set up the variable fields of the dispatcher context */
779  DispatcherContext.ControlPc = ContextRecord->Rip;
780  DispatcherContext.ImageBase = ImageBase;
781  DispatcherContext.FunctionEntry = FunctionEntry;
782  DispatcherContext.LanguageHandler = ExceptionRoutine;
783  DispatcherContext.EstablisherFrame = EstablisherFrame;
784  DispatcherContext.ScopeIndex = 0;
785 
786  /* Store the return value in the unwind context */
787  UnwindContext.Rax = (ULONG64)ReturnValue;
788 
789  /* Loop all nested handlers */
790  do
791  {
793  /* Call the language specific handler */
794  Disposition = ExceptionRoutine(ExceptionRecord,
796  &UnwindContext,
798 
799  /* Clear exception flags for the next iteration */
800  ExceptionRecord->ExceptionFlags &= ~(EXCEPTION_TARGET_UNWIND |
802 
803  /* Check if we do exception handling */
805  {
807  {
808  /* Check if it was non-continuable */
809  if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
810  {
811  __debugbreak();
813  }
814 
815  /* Execution continues */
816  return TRUE;
817  }
819  {
821  __debugbreak();
822  }
823  }
824 
826  {
828  __debugbreak();
829  }
830 
831  /* This must be ExceptionContinueSearch now */
833  {
834  __debugbreak();
836  }
837  } while (ExceptionRecord->ExceptionFlags & EXCEPTION_COLLIDED_UNWIND);
838  }
839 
840  /* Check, if we have left our stack (8.) */
841  if ((EstablisherFrame < StackLow) ||
842  (EstablisherFrame > StackHigh) ||
843  (EstablisherFrame & 7))
844  {
846  __debugbreak();
847 
848  if (UnwindContext.Rip == ContextRecord->Rip)
849  {
851  }
852  else
853  {
854  ZwRaiseException(ExceptionRecord, ContextRecord, FALSE);
855  }
856  }
857 
858  if (EstablisherFrame == (ULONG64)TargetFrame)
859  {
860  break;
861  }
862 
863  /* We have successfully unwound a frame. Copy the unwind context back. */
864  *ContextRecord = UnwindContext;
865  }
866 
867  if (ExceptionRecord->ExceptionCode != STATUS_UNWIND_CONSOLIDATE)
868  {
869  ContextRecord->Rip = (ULONG64)TargetIp;
870  }
871 
872  /* Set the return value */
874 
875  /* Restore the context */
876  RtlRestoreContext(ContextRecord, ExceptionRecord);
877 
878  /* Should never get here! */
879  ASSERT(FALSE);
880  return FALSE;
881 }
882 
883 VOID
884 NTAPI
886  _In_opt_ PVOID TargetFrame,
887  _In_opt_ PVOID TargetIp,
888  _In_opt_ PEXCEPTION_RECORD ExceptionRecord,
891  _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable)
892 {
893  EXCEPTION_RECORD LocalExceptionRecord;
894 
895  /* Capture the current context */
897 
898  /* Check if we have an exception record */
899  if (ExceptionRecord == NULL)
900  {
901  /* No exception record was passed, so set up a local one */
902  LocalExceptionRecord.ExceptionCode = STATUS_UNWIND;
903  LocalExceptionRecord.ExceptionAddress = (PVOID)ContextRecord->Rip;
904  LocalExceptionRecord.ExceptionRecord = NULL;
905  LocalExceptionRecord.NumberParameters = 0;
906  ExceptionRecord = &LocalExceptionRecord;
907  }
908 
909  /* Call the internal function */
910  RtlpUnwindInternal(TargetFrame,
911  TargetIp,
912  ExceptionRecord,
913  ReturnValue,
915  HistoryTable,
917 }
918 
919 VOID
920 NTAPI
922  IN PVOID TargetFrame,
923  IN PVOID TargetIp,
924  IN PEXCEPTION_RECORD ExceptionRecord,
926 {
928  return;
929 }
930 
931 ULONG
932 NTAPI
934  IN ULONG Count,
935  IN ULONG Flags)
936 {
938  ULONG64 ControlPc, ImageBase, EstablisherFrame;
939  ULONG64 StackLow, StackHigh;
940  PVOID HandlerData;
941  ULONG i, FramesToSkip;
942  PRUNTIME_FUNCTION FunctionEntry;
943 
944  DPRINT("Enter RtlWalkFrameChain\n");
945 
946  /* The upper bits in Flags define how many frames to skip */
947  FramesToSkip = Flags >> 8;
948 
949  /* Capture the current Context */
951  ControlPc = Context.Rip;
952 
953  /* Get the stack limits */
954  RtlpGetStackLimits(&StackLow, &StackHigh);
955 
956  /* Check if we want the user-mode stack frame */
957  if (Flags & 1)
958  {
959  }
960 
961  _SEH2_TRY
962  {
963  /* Loop the frames */
964  for (i = 0; i < FramesToSkip + Count; i++)
965  {
966  /* Lookup the FunctionEntry for the current ControlPc */
967  FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
968 
969  /* Is this a leaf function? */
970  if (!FunctionEntry)
971  {
972  Context.Rip = *(DWORD64*)Context.Rsp;
973  Context.Rsp += sizeof(DWORD64);
974  DPRINT("leaf funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
975  }
976  else
977  {
979  ImageBase,
980  ControlPc,
981  FunctionEntry,
982  &Context,
983  &HandlerData,
985  NULL);
986  DPRINT("normal funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp);
987  }
988 
989  /* Check if we are in kernel mode */
990  if (RtlpGetMode() == KernelMode)
991  {
992  /* Check if we left the kernel range */
993  if (!(Flags & 1) && (Context.Rip < 0xFFFF800000000000ULL))
994  {
995  break;
996  }
997  }
998  else
999  {
1000  /* Check if we left the user range */
1001  if ((Context.Rip < 0x10000) ||
1002  (Context.Rip > 0x000007FFFFFEFFFFULL))
1003  {
1004  break;
1005  }
1006  }
1007 
1008  /* Check, if we have left our stack */
1009  if ((Context.Rsp < StackLow) || (Context.Rsp > StackHigh))
1010  {
1011  break;
1012  }
1013 
1014  /* Continue with new Rip */
1015  ControlPc = Context.Rip;
1016 
1017  /* Save value, if we are past the frames to skip */
1018  if (i >= FramesToSkip)
1019  {
1020  Callers[i - FramesToSkip] = (PVOID)ControlPc;
1021  }
1022  }
1023  }
1025  {
1026  DPRINT1("Exception while getting callers!\n");
1027  i = 0;
1028  }
1029  _SEH2_END;
1030 
1031  DPRINT("RtlWalkFrameChain returns %ld\n", i);
1032  return i;
1033 }
1034 
1038 #undef RtlGetCallersAddress
1039 VOID
1040 NTAPI
1042  OUT PVOID *CallersAddress,
1043  OUT PVOID *CallersCaller )
1044 {
1045  PVOID Callers[4];
1046  ULONG Number;
1047 
1048  /* Get callers:
1049  * RtlWalkFrameChain -> RtlGetCallersAddress -> x -> y */
1050  Number = RtlWalkFrameChain(Callers, 4, 0);
1051 
1052  *CallersAddress = (Number >= 3) ? Callers[2] : NULL;
1053  *CallersCaller = (Number == 4) ? Callers[3] : NULL;
1054 
1055  return;
1056 }
1057 
1058 static
1059 VOID
1061  _Out_ PKNONVOLATILE_CONTEXT_POINTERS NonvolatileContextPointers,
1062  _In_ ULONG64 TargetFrame)
1063 {
1064  CONTEXT Context;
1065  PRUNTIME_FUNCTION FunctionEntry;
1066  ULONG64 ImageBase;
1067  PVOID HandlerData;
1069 
1070  /* Zero out the nonvolatile context pointers */
1071  RtlZeroMemory(NonvolatileContextPointers, sizeof(*NonvolatileContextPointers));
1072 
1073  /* Capture the current context */
1075 
1076  do
1077  {
1078  /* Look up the function entry */
1079  FunctionEntry = RtlLookupFunctionEntry(Context.Rip, &ImageBase, NULL);
1080  ASSERT(FunctionEntry != NULL);
1081 
1082  /* Do a virtual unwind to the caller and capture saved non-volatiles */
1084  ImageBase,
1085  Context.Rip,
1086  FunctionEntry,
1087  &Context,
1088  &HandlerData,
1090  NonvolatileContextPointers);
1091 
1092  /* Make sure nothing fishy is going on. Currently this is for kernel mode only. */
1093  ASSERT(EstablisherFrame != 0);
1094  ASSERT((LONG64)Context.Rip < 0);
1095 
1096  /* Continue until we reached the target frame or user mode */
1097  } while (EstablisherFrame < TargetFrame);
1098 
1099  /* If the caller did the right thing, we should get exactly the target frame */
1100  ASSERT(EstablisherFrame == TargetFrame);
1101 }
1102 
1103 VOID
1106  _In_ DWORD64 TargetFrame)
1107 {
1108  KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
1109 
1110  /* Capture pointers to the non-volatiles up to the target frame */
1111  RtlpCaptureNonVolatileContextPointers(&ContextPointers, TargetFrame);
1112 
1113  /* Copy the nonvolatiles to the captured locations */
1114  *ContextPointers.R12 = Context->R12;
1115  *ContextPointers.R13 = Context->R13;
1116  *ContextPointers.R14 = Context->R14;
1117  *ContextPointers.R15 = Context->R15;
1118  *ContextPointers.Xmm6 = Context->Xmm6;
1119  *ContextPointers.Xmm7 = Context->Xmm7;
1120  *ContextPointers.Xmm8 = Context->Xmm8;
1121  *ContextPointers.Xmm9 = Context->Xmm9;
1122  *ContextPointers.Xmm10 = Context->Xmm10;
1123  *ContextPointers.Xmm11 = Context->Xmm11;
1124  *ContextPointers.Xmm12 = Context->Xmm12;
1125  *ContextPointers.Xmm13 = Context->Xmm13;
1126  *ContextPointers.Xmm14 = Context->Xmm14;
1127  *ContextPointers.Xmm15 = Context->Xmm15;
1128 }
#define STATUS_UNWIND_CONSOLIDATE
Definition: ntstatus.h:220
#define EXCEPTION_NONCONTINUABLE_EXCEPTION
Definition: winbase.h:325
const uint16_t * PCWSTR
Definition: typedefs.h:57
#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:686
#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:331
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:496
#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:457
#define UWOP_EPILOG
Definition: unwind.c:29
static __inline DWORD64 GetReg(_In_ PCONTEXT Context, _In_ BYTE Reg)
Definition: unwind.c:264
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:313
#define STATUS_BAD_FUNCTION_TABLE
Definition: ntstatus.h:491
PVOID ExceptionAddress
Definition: compat.h:211
_SEH2_TRY
Definition: create.c:4226
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
BOOLEAN NTAPI RtlAddFunctionTable(IN PRUNTIME_FUNCTION FunctionTable, IN DWORD EntryCount, IN DWORD64 BaseAddress)
Definition: unwind.c:169
#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:885
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
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
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:297
#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:204
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:1104
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
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:456
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
_SEH2_END
Definition: create.c:4400
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:274
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:237
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
BOOLEAN NTAPI RtlDeleteFunctionTable(IN PRUNTIME_FUNCTION FunctionTable)
Definition: unwind.c:180
#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:921
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:1041
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:248
static WLX_DISPATCH_VERSION_1_4 FunctionTable
Definition: wlx.c:736
#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:933
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:117
static VOID RtlpCaptureNonVolatileContextPointers(_Out_ PKNONVOLATILE_CONTEXT_POINTERS NonvolatileContextPointers, _In_ ULONG64 TargetFrame)
Definition: unwind.c:1060
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION
Definition: pedump.c:262
UBYTE CountOfCodes
Definition: unwind.c:55
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: unwind.c:189
#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:286