ReactOS 0.4.17-dev-243-g1369312
RtlVirtualUnwind.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Test for x64 RtlVirtualUnwind
5 * COPYRIGHT: Copyright 2026 Jiahe Wang <wjhwjhn@gmail.com>
6 */
7
8#include <rtltests.h>
9
10#define UWOP_PUSH_NONVOL 0
11#define UWOP_ALLOC_LARGE 1
12#define UWOP_ALLOC_SMALL 2
13#define UWOP_SET_FPREG 3
14#define UWOP_SAVE_NONVOL 4
15#define UWOP_SAVE_NONVOL_FAR 5
16#define UWOP_EPILOG 6
17#define UWOP_SPARE_CODE 7
18#define UWOP_SAVE_XMM128 8
19#define UWOP_SAVE_XMM128_FAR 9
20#define UWOP_PUSH_MACHFRAME 10
21
22/* OpInfo register encoding. Matches the order of integer registers
23 * starting at CONTEXT.Rax, which is what GetReg/SetReg in unwind.c index. */
24enum
25{
30};
31
32/* UNWIND_INFO and UNWIND_CODE are not exposed by any public PSDK header
33 * (they live as private definitions inside sdk/lib/rtl/amd64/unwind.c),
34 * so we mirror them locally for the test. */
35typedef union _TEST_UNWIND_CODE
36{
37 struct
38 {
42 };
45
46typedef struct _TEST_UNWIND_INFO
47{
56
57/* The fake image is split into 0x1000-byte regions so the unwinder sees
58 * a Code range that doesn't overlap with the unwind data we author. */
59typedef struct _IMAGE_STRUCT
60{
61 UCHAR Header[0x1000];
62 UCHAR Code[0x1000];
63 UCHAR Data[0x1000];
64 UCHAR Unwind[0x1000];
66
67#define PARENT_OFFSET 0x100 /* Offset of the parent unwind info inside Unwind[]. */
68
69#define INIT_RAX 0xDEADBEEFDEADBEEFULL
70
71static DECLSPEC_ALIGN(16) IMAGE_STRUCT g_Image;
72
73/* Most tests rely on the unwinder's tail step:
74 * Context->Rip = *(DWORD64*)Context->Rsp; Context->Rsp += 8;
75 * They stage the expected Rip QWORD at g_StackBuffer[Rsp/8], matching
76 * the QWORD pointed to by the pre-tail-step Rsp. */
77static DECLSPEC_ALIGN(16) DWORD64 g_StackBuffer[0x80];
78
79static TEST_UNWIND_INFO *
80ResetUnwindInfo(UCHAR Version, UCHAR SizeOfProlog, UCHAR CountOfCodes)
81{
83 RtlZeroMemory(Info, sizeof(*Info));
84 Info->Version = Version;
85 Info->SizeOfProlog = SizeOfProlog;
86 Info->CountOfCodes = CountOfCodes;
87 return Info;
88}
89
90static VOID
92 UCHAR CodeOffset, UCHAR UnwindOp, UCHAR OpInfo)
93{
94 Info->UnwindCode[Index].CodeOffset = CodeOffset;
95 Info->UnwindCode[Index].UnwindOp = UnwindOp;
96 Info->UnwindCode[Index].OpInfo = OpInfo;
97}
98
99static VOID
101{
102 RtlZeroMemory(Context, sizeof(*Context));
103 Context->Rsp = Rsp;
104 Context->Rax = INIT_RAX;
105}
106
107static ULONG_PTR
109 PKNONVOLATILE_CONTEXT_POINTERS Pointers)
110{
111 RUNTIME_FUNCTION Func =
112 {
116 };
117 PVOID HandlerData = NULL;
119
121 (ULONG_PTR)&g_Image,
122 (ULONG_PTR)g_Image.Code + CodeOffset,
123 &Func,
124 Context,
125 &HandlerData,
127 Pointers);
128 return EstablisherFrame;
129}
130
131static ULONG_PTR
133 PKNONVOLATILE_CONTEXT_POINTERS Pointers)
134{
135 InitContext(Context, Rsp);
136 return DoUnwind(Context, CodeOffset, Pointers);
137}
138
140{
141 CONTEXT Ctx;
143 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
144
145 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
146 g_StackBuffer[0] = 0x1111111122222222ULL;
147 g_StackBuffer[1] = 0xDEADC0DEDEADC0DEULL;
148
149 Info = ResetUnwindInfo(1, 1, 1);
151
152 ok_eq_hex64(RunUnwind(&Ctx, Stack, 1, NULL), Stack);
153 ok_eq_hex64(Ctx.Rbp, 0x1111111122222222ULL);
154 ok_eq_hex64(Ctx.Rip, 0xDEADC0DEDEADC0DEULL);
155 ok_eq_hex64(Ctx.Rsp, Stack + 16);
156}
157
159{
160 CONTEXT Ctx;
162 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
163
164 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
165 g_StackBuffer[8] = 0xFEEDFACEFEEDFACEULL;
166
167 /* sub rsp, 0x40 -> OpInfo = (0x40/8) - 1 = 7 */
168 Info = ResetUnwindInfo(1, 4, 1);
169 SetCode(Info, 0, 4, UWOP_ALLOC_SMALL, 7);
170
171 ok_eq_hex64(RunUnwind(&Ctx, Stack, 4, NULL), Stack);
172 ok_eq_hex64(Ctx.Rip, 0xFEEDFACEFEEDFACEULL);
173 ok_eq_hex64(Ctx.Rsp, Stack + 0x40 + 8);
174}
175
177{
178 CONTEXT Ctx;
180 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
181
182 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
183 g_StackBuffer[0x100 / 8] = 0x12345678ABCDEF00ULL;
184
185 /* sub rsp, 0x100 with ALLOC_LARGE OpInfo=0: next slot * 8 */
186 Info = ResetUnwindInfo(1, 7, 2);
187 SetCode(Info, 0, 7, UWOP_ALLOC_LARGE, 0);
188 Info->UnwindCode[1].FrameOffset = 0x100 / 8;
189
190 ok_eq_hex64(RunUnwind(&Ctx, Stack, 7, NULL), Stack);
191 ok_eq_hex64(Ctx.Rip, 0x12345678ABCDEF00ULL);
192 ok_eq_hex64(Ctx.Rsp, Stack + 0x100 + 8);
193}
194
196{
197 CONTEXT Ctx;
199 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
200 ULONG Size = 0x300;
201
202 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
203 g_StackBuffer[Size / 8] = 0xAA55AA55AA55AA55ULL;
204
205 /* sub rsp, Size with ALLOC_LARGE OpInfo=1: next 2 slots = full ULONG */
206 Info = ResetUnwindInfo(1, 7, 3);
207 SetCode(Info, 0, 7, UWOP_ALLOC_LARGE, 1);
208 *(ULONG *)&Info->UnwindCode[1] = Size;
209
210 ok_eq_hex64(RunUnwind(&Ctx, Stack, 7, NULL), Stack);
211 ok_eq_hex64(Ctx.Rip, 0xAA55AA55AA55AA55ULL);
212 ok_eq_hex64(Ctx.Rsp, Stack + Size + 8);
213}
214
216{
217 CONTEXT Ctx;
219 ULONG_PTR EstFrame;
220 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
221 ULONG_PTR FrameTop = Stack + 0x100;
222
223 /* lea rbp, [rsp + 0x20]; FrameOffset (in 16-byte units) = 2 */
224 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
225 g_StackBuffer[0x100 / 8] = 0x9999AAAA9999AAAAULL;
226
227 Info = ResetUnwindInfo(1, 4, 1);
228 Info->FrameRegister = REG_RBP;
229 Info->FrameOffset = 2;
230 SetCode(Info, 0, 4, UWOP_SET_FPREG, 0);
231
232 InitContext(&Ctx, Stack);
233 Ctx.Rbp = FrameTop + 0x20;
234 EstFrame = DoUnwind(&Ctx, 4, NULL);
235
236 ok_eq_hex64(EstFrame, FrameTop);
237 ok_eq_hex64(Ctx.Rip, 0x9999AAAA9999AAAAULL);
238 ok_eq_hex64(Ctx.Rsp, FrameTop + 8);
239}
240
242{
243 CONTEXT Ctx;
245 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
246
247 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
248 g_StackBuffer[0x80 / 8] = 0x4242424242424242ULL;
249 g_StackBuffer[0] = 0xDEADC0DEDEADC0DEULL;
250
251 /* mov [rsp + 0x80], rsi; FrameOffset (in 8-byte units) = 0x10 */
252 Info = ResetUnwindInfo(1, 8, 2);
254 Info->UnwindCode[1].FrameOffset = 0x10;
255
256 ok_eq_hex64(RunUnwind(&Ctx, Stack, 8, NULL), Stack);
257 ok_eq_hex64(Ctx.Rsi, 0x4242424242424242ULL);
258 ok_eq_hex64(Ctx.Rip, 0xDEADC0DEDEADC0DEULL);
259 ok_eq_hex64(Ctx.Rsp, Stack + 8);
260}
261
263{
264 CONTEXT Ctx;
266 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
268
269 Expected.Low = 0x0011223344556677ULL;
270 Expected.High = 0x8899AABBCCDDEEFFULL;
271
272 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
273 *(M128A *)&g_StackBuffer[0x40 / 8] = Expected;
274
275 /* movaps [rsp + 0x40], xmm7; FrameOffset (in 16-byte units) = 4 */
276 Info = ResetUnwindInfo(1, 9, 2);
277 SetCode(Info, 0, 9, UWOP_SAVE_XMM128, 7 /* XMM7 */);
278 Info->UnwindCode[1].FrameOffset = 4;
279
280 ok_eq_hex64(RunUnwind(&Ctx, Stack, 9, NULL), Stack);
281 ok_eq_xmm(Ctx.Xmm7, Expected);
282}
283
285{
286 CONTEXT Ctx;
288 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
289
290 /* MACHINE_FRAME layout: [Rip][Cs][EFlags][Rsp][Ss], OpInfo=1 means an
291 * error code was pushed (one extra QWORD before the frame). */
292 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
293 g_StackBuffer[1] = 0xCAFEBABE00000000ULL; /* Rip */
294 g_StackBuffer[4] = Stack + 0x100; /* Rsp */
295
296 Info = ResetUnwindInfo(1, 1, 1);
298
299 RunUnwind(&Ctx, Stack, 1, NULL);
300 ok_eq_hex64(Ctx.Rip, 0xCAFEBABE00000000ULL);
301 ok_eq_hex64(Ctx.Rsp, Stack + 0x100);
302}
303
305{
306 CONTEXT Ctx;
308 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
309
310 /* Equivalent to:
311 * push rbp ; CodeOffset 1
312 * push rbx ; CodeOffset 2
313 * push rsi ; CodeOffset 3
314 * sub rsp, 0x40 ; CodeOffset 7 (4-byte instruction)
315 */
316 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
317 g_StackBuffer[0x40 / 8] = 0x1111111111111111ULL; /* saved RSI */
318 g_StackBuffer[0x48 / 8] = 0x2222222222222222ULL; /* saved RBX */
319 g_StackBuffer[0x50 / 8] = 0x3333333333333333ULL; /* saved RBP */
320 g_StackBuffer[0x58 / 8] = 0x4444444444444444ULL; /* return Rip */
321
322 Info = ResetUnwindInfo(1, 7, 4);
323 SetCode(Info, 0, 7, UWOP_ALLOC_SMALL, 7);
327
328 ok_eq_hex64(RunUnwind(&Ctx, Stack, 7, NULL), Stack);
329 ok_eq_hex64(Ctx.Rsi, 0x1111111111111111ULL);
330 ok_eq_hex64(Ctx.Rbx, 0x2222222222222222ULL);
331 ok_eq_hex64(Ctx.Rbp, 0x3333333333333333ULL);
332 ok_eq_hex64(Ctx.Rip, 0x4444444444444444ULL);
333 ok_eq_hex64(Ctx.Rsp, Stack + 0x60);
334 ok_eq_hex64(Ctx.Rax, INIT_RAX);
335}
336
338{
339 CONTEXT Ctx;
341 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
342
343 /* Same prolog but ControlPc is between push rbx and sub rsp.
344 * Only push rbp / push rbx have executed, so sub rsp must NOT undo. */
345 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
346 g_StackBuffer[0] = 0x2222222222222222ULL;
347 g_StackBuffer[1] = 0x3333333333333333ULL;
348 g_StackBuffer[2] = 0x4444444444444444ULL;
349
350 Info = ResetUnwindInfo(1, 7, 4);
351 SetCode(Info, 0, 7, UWOP_ALLOC_SMALL, 7);
355
356 ok_eq_hex64(RunUnwind(&Ctx, Stack, 2, NULL), Stack);
357 ok_eq_hex64(Ctx.Rbx, 0x2222222222222222ULL);
358 ok_eq_hex64(Ctx.Rbp, 0x3333333333333333ULL);
359 ok_eq_hex64(Ctx.Rip, 0x4444444444444444ULL);
360 ok_eq_hex64(Ctx.Rsi, 0); /* push rsi not yet executed */
361 ok_eq_hex64(Ctx.Rsp, Stack + 0x18);
362}
363
365{
366 CONTEXT Ctx;
367 KNONVOLATILE_CONTEXT_POINTERS Ptrs;
369 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
370
371 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
372 RtlZeroMemory(&Ptrs, sizeof(Ptrs));
373 g_StackBuffer[0] = 0xAABBCCDDAABBCCDDULL;
374
375 Info = ResetUnwindInfo(1, 1, 1);
377
378 RunUnwind(&Ctx, Stack, 1, &Ptrs);
379 ok_eq_pointer(Ptrs.Rbx, &g_StackBuffer[0]);
380 ok_eq_hex64(Ctx.Rbx, 0xAABBCCDDAABBCCDDULL);
381}
382
384{
385 CONTEXT Ctx;
387 PRUNTIME_FUNCTION ParentFunc;
388 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
389
390 /* Child runs PUSH_NONVOL(RBX), then chains to a parent that runs
391 * PUSH_NONVOL(RBP). Final tail step pops Rip. */
392 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
393 g_StackBuffer[0] = 0xAA00AA00AA00AA00ULL; /* saved RBX */
394 g_StackBuffer[1] = 0xBB00BB00BB00BB00ULL; /* saved RBP */
395 g_StackBuffer[2] = 0xCC00CC00CC00CC00ULL; /* return Rip */
396
397 Child = ResetUnwindInfo(1, 1, 1);
398 Child->Flags = UNW_FLAG_CHAININFO;
400
401 /* Parent's RUNTIME_FUNCTION sits right after the rounded-up child
402 * UnwindCode array, at &UnwindCode[(CountOfCodes + 1) & ~1]. */
403 ParentFunc = (PRUNTIME_FUNCTION)&Child->UnwindCode[2];
404 ParentFunc->BeginAddress = FIELD_OFFSET(IMAGE_STRUCT, Code);
405 ParentFunc->EndAddress = FIELD_OFFSET(IMAGE_STRUCT, Data);
406 ParentFunc->UnwindData = FIELD_OFFSET(IMAGE_STRUCT, Unwind) + PARENT_OFFSET;
407
408 Parent = (TEST_UNWIND_INFO *)(g_Image.Unwind + PARENT_OFFSET);
409 RtlZeroMemory(Parent, sizeof(*Parent));
410 Parent->Version = 1;
411 Parent->SizeOfProlog = 1;
412 Parent->CountOfCodes = 1;
414
415 RunUnwind(&Ctx, Stack, 1, NULL);
416 ok_eq_hex64(Ctx.Rbx, 0xAA00AA00AA00AA00ULL);
417 ok_eq_hex64(Ctx.Rbp, 0xBB00BB00BB00BB00ULL);
418 ok_eq_hex64(Ctx.Rip, 0xCC00CC00CC00CC00ULL);
419 ok_eq_hex64(Ctx.Rsp, Stack + 0x18);
420}
421
423{
424 CONTEXT Ctx;
426 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
427
428 /* Expected at unscaled byte offset 8, decoy at the buggy
429 * (DWORD64*)Rsp + 8 == Rsp + 64 location. */
430 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
431 g_StackBuffer[1] = 0xAAAAAAAABBBBBBBBULL; /* byte offset 8 */
432 g_StackBuffer[8] = 0xCCCCCCCCDDDDDDDDULL; /* byte offset 64 */
433
434 Info = ResetUnwindInfo(2, 0, 3);
436 *(ULONG *)&Info->UnwindCode[1] = 8;
437
438 RunUnwind(&Ctx, Stack, 0, NULL);
439 ok_eq_hex64(Ctx.Rbx, 0xAAAAAAAABBBBBBBBULL);
440 ok(Ctx.Rbx != 0xCCCCCCCCDDDDDDDDULL,
441 "Rbx looks scaled-by-8: %I64x\n", Ctx.Rbx);
442 /* If the unwinder mis-advances i, trailing zero slots decode as
443 * UWOP_PUSH_NONVOL(RAX) and shift Rsp / clobber Rax. */
444 ok_eq_hex64(Ctx.Rax, INIT_RAX);
445 ok_eq_hex64(Ctx.Rsp, Stack + 8);
446}
447
449{
450 CONTEXT Ctx;
452 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
453 M128A Expected, Decoy;
454
455 Expected.Low = 0x1111111122222222ULL;
456 Expected.High = 0x3333333344444444ULL;
457 Decoy.Low = 0x5555555566666666ULL;
458 Decoy.High = 0x7777777788888888ULL;
459
460 /* Expected at unscaled byte offset 16, decoy at the buggy
461 * (M128A*)Rsp + 16 == Rsp + 256 location. */
462 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
463 *(M128A *)&g_StackBuffer[16 / 8] = Expected;
464 *(M128A *)&g_StackBuffer[256 / 8] = Decoy;
465
466 Info = ResetUnwindInfo(2, 0, 3);
467 SetCode(Info, 0, 0, UWOP_SAVE_XMM128_FAR, 6 /* XMM6 */);
468 *(ULONG *)&Info->UnwindCode[1] = 16;
469
470 RunUnwind(&Ctx, Stack, 0, NULL);
471 ok_eq_xmm(Ctx.Xmm6, Expected);
472 ok(Ctx.Xmm6.Low != Decoy.Low,
473 "Xmm6 looks scaled-by-16: %I64x\n", Ctx.Xmm6.Low);
474 ok_eq_hex64(Ctx.Rax, INIT_RAX);
475 ok_eq_hex64(Ctx.Rsp, Stack + 8);
476}
477
479{
480 CONTEXT Ctx;
482 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
483
484 /* UWOP_EPILOG consumes 2 slots. If the unwinder advances by only 1,
485 * the trailing zero slot is misread as UWOP_PUSH_NONVOL(RAX) and the
486 * subsequent PUSH_NONVOL(RDI) sees a shifted Rsp. */
487 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
488 g_StackBuffer[0] = 0xAAAAAAAAAAAAAAAAULL;
489 g_StackBuffer[1] = 0xBBBBBBBBBBBBBBBBULL;
490
491 Info = ResetUnwindInfo(2, 0, 3);
492 SetCode(Info, 0, 0, UWOP_EPILOG, 0);
493 Info->UnwindCode[1].FrameOffset = 0;
495
496 RunUnwind(&Ctx, Stack, 0, NULL);
497 ok_eq_hex64(Ctx.Rdi, 0xAAAAAAAAAAAAAAAAULL);
498 ok_eq_hex64(Ctx.Rax, INIT_RAX);
499}
500
502{
503 CONTEXT Ctx;
505 ULONG_PTR Stack = (ULONG_PTR)g_StackBuffer;
506
507 /* Same idea as Test_Epilog, but UWOP_SPARE_CODE consumes 3 slots.
508 * The unwinder hits ASSERT(FALSE) before advancing i, so on debug
509 * (DBG=1) builds the fix path is unreachable; catch and skip. */
510 RtlZeroMemory(g_StackBuffer, sizeof(g_StackBuffer));
511 g_StackBuffer[0] = 0xAAAAAAAAAAAAAAAAULL;
512 g_StackBuffer[1] = 0xBBBBBBBBBBBBBBBBULL;
513
514 Info = ResetUnwindInfo(2, 0, 4);
515 SetCode(Info, 0, 0, UWOP_SPARE_CODE, 0);
516 Info->UnwindCode[1].FrameOffset = 0;
517 Info->UnwindCode[2].FrameOffset = 0;
519
521 {
522 RunUnwind(&Ctx, Stack, 0, NULL);
523 ok_eq_hex64(Ctx.Rdi, 0xAAAAAAAAAAAAAAAAULL);
524 ok_eq_hex64(Ctx.Rax, INIT_RAX);
525 }
527 {
528 skip("UWOP_SPARE_CODE triggered exception 0x%08lx (debug build ASSERT)\n",
530 }
531 _SEH2_END;
532}
533
535{
550 Test_Epilog();
552}
BOOLEAN Expected
static VOID Test_TypicalProlog(VOID)
static VOID Test_SaveXmm128(VOID)
static VOID Test_PushNonvol(VOID)
#define UWOP_EPILOG
static VOID Test_PartialProlog(VOID)
static VOID Test_PushMachframe(VOID)
static VOID Test_ContextPointers(VOID)
struct _TEST_UNWIND_INFO TEST_UNWIND_INFO
static VOID Test_Epilog(VOID)
#define INIT_RAX
static VOID SetCode(TEST_UNWIND_INFO *Info, ULONG Index, UCHAR CodeOffset, UCHAR UnwindOp, UCHAR OpInfo)
union _TEST_UNWIND_CODE TEST_UNWIND_CODE
#define UWOP_SAVE_NONVOL
static VOID Test_AllocLargeScaled(VOID)
#define UWOP_SPARE_CODE
#define UWOP_SAVE_NONVOL_FAR
static VOID Test_AllocSmall(VOID)
@ REG_RBP
@ REG_R8
@ REG_R14
@ REG_RSP
@ REG_R11
@ REG_RCX
@ REG_RDX
@ REG_R13
@ REG_RDI
@ REG_R12
@ REG_RAX
@ REG_R15
@ REG_R10
@ REG_RBX
@ REG_RSI
@ REG_R9
#define UWOP_PUSH_MACHFRAME
#define UWOP_ALLOC_LARGE
static VOID Test_SaveXmm128Far(VOID)
#define PARENT_OFFSET
#define UWOP_ALLOC_SMALL
static ULONG_PTR RunUnwind(PCONTEXT Context, ULONG_PTR Rsp, ULONG CodeOffset, PKNONVOLATILE_CONTEXT_POINTERS Pointers)
static ULONG_PTR DoUnwind(PCONTEXT Context, ULONG CodeOffset, PKNONVOLATILE_CONTEXT_POINTERS Pointers)
#define UWOP_SAVE_XMM128
static VOID Test_SpareCode(VOID)
struct _IMAGE_STRUCT IMAGE_STRUCT
#define UWOP_SAVE_XMM128_FAR
static VOID Test_SaveNonvolFar(VOID)
static VOID Test_ChainedInfo(VOID)
#define UWOP_PUSH_NONVOL
static VOID Test_SetFpReg(VOID)
static VOID Test_AllocLargeUnscaled(VOID)
static VOID InitContext(PCONTEXT Context, ULONG_PTR Rsp)
#define UWOP_SET_FPREG
static VOID Test_SaveNonvol(VOID)
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx 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 Parent
Definition: acpixf.h:732
#define ok_eq_pointer(value, expected)
Definition: apitest.h:116
#define ok_eq_hex64(value, expected)
Definition: apitest.h:146
#define ok_eq_xmm(value, expected)
Definition: apitest.h:147
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
Definition: Header.h:9
#define NULL
Definition: types.h:112
#define DECLSPEC_ALIGN(x)
Definition: corecrt.h:141
#define ULONG_PTR
Definition: config.h:101
#define UNW_FLAG_NHANDLER
Definition: gs_support.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
static PRUNTIME_FUNCTION(WINAPI *pRtlLookupFunctionEntry)(ULONG_PTR
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:665
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
void(* Func)(int)
NTSYSAPI PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind(ULONG, ULONG_PTR, ULONG_PTR, RUNTIME_FUNCTION *, CONTEXT *, void **, ULONG_PTR *, KNONVOLATILE_CONTEXT_POINTERS *)
_In_ PVOID Context
Definition: storport.h:2269
UCHAR Unwind[0x1000]
TEST_UNWIND_CODE UnwindCode[32]
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint64_t DWORD64
Definition: typedefs.h:67
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1707
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE _In_ USHORT _In_ USHORT Version
Definition: wdffdo.h:469
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
M128A
Definition: ketypes.h:992