Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/signal_i386.c | 22 ++++++++++++++++------ dlls/ntdll/signal_x86_64.c | 35 +++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 14971032ce6..0245aa602a1 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -481,17 +481,15 @@ __ASM_STDCALL_FUNC( RtlRaiseException, 4,
/************************************************************************* - * RtlCaptureStackBackTrace (NTDLL.@) + * capture_stack_back_trace */ -USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) +static USHORT capture_stack_back_trace( CONTEXT *context, ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) { - CONTEXT context; - ULONG i; ULONG *frame; + ULONG i;
- RtlCaptureContext( &context ); if (hash) *hash = 0; - frame = (ULONG *)context.Ebp; + frame = (ULONG *)context->Ebp;
while (skip--) { @@ -510,6 +508,18 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, }
+/************************************************************************* + * RtlCaptureStackBackTrace (NTDLL.@) + */ +USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) +{ + CONTEXT context; + + RtlCaptureContext( &context ); + return capture_stack_back_trace( &context, skip, count, buffer, hash ); +} + + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index ef32eba68b7..dbf622392b7 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1490,27 +1490,23 @@ static inline ULONG hash_pointers( void **ptrs, ULONG count )
/************************************************************************* - * RtlCaptureStackBackTrace (NTDLL.@) + * capture_stack_back_trace */ -USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) +static USHORT capture_stack_back_trace( CONTEXT *context, ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) { - UNWIND_HISTORY_TABLE table; DISPATCHER_CONTEXT dispatch; - CONTEXT context; + UNWIND_HISTORY_TABLE table; + USHORT num_entries = 0; NTSTATUS status; ULONG i; - USHORT num_entries = 0;
- TRACE( "(%u, %u, %p, %p)\n", skip, count, buffer, hash ); - - RtlCaptureContext( &context ); dispatch.TargetIp = 0; - dispatch.ContextRecord = &context; + dispatch.ContextRecord = context; dispatch.HistoryTable = &table; if (hash) *hash = 0; for (i = 0; i < skip + count; i++) { - status = virtual_unwind( UNW_FLAG_NHANDLER, &dispatch, &context ); + status = virtual_unwind( UNW_FLAG_NHANDLER, &dispatch, context ); if (status != STATUS_SUCCESS) return i;
if (!dispatch.EstablisherFrame) break; @@ -1524,9 +1520,9 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, break; }
- if (context.Rsp == (ULONG64)NtCurrentTeb()->Tib.StackBase) break; + if (context->Rsp == (ULONG64)NtCurrentTeb()->Tib.StackBase) break;
- if (i >= skip) buffer[num_entries++] = (void *)context.Rip; + if (i >= skip) buffer[num_entries++] = (void *)context->Rip; } if (hash && num_entries > 0) *hash = hash_pointers( buffer, num_entries ); TRACE( "captured %hu frames\n", num_entries ); @@ -1534,6 +1530,21 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, }
+/************************************************************************* + * RtlCaptureStackBackTrace (NTDLL.@) + */ +USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) +{ + CONTEXT context; + + TRACE( "(%u, %u, %p, %p)\n", skip, count, buffer, hash ); + + RtlCaptureContext( &context ); + + return capture_stack_back_trace( &context, skip, count, buffer, hash ); +} + + /*********************************************************************** * signal_start_thread */
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/signal_arm.c | 11 +++++++ dlls/ntdll/signal_arm64.c | 11 +++++++ dlls/ntdll/signal_i386.c | 24 ++++++++++++++ dlls/ntdll/signal_x86_64.c | 24 ++++++++++++++ dlls/ntdll/tests/exception.c | 51 +++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- include/ddk/ntddk.h | 3 ++ include/winnt.h | 2 ++ 9 files changed, 128 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 13e65f65139..c54b2e205aa 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1073,7 +1073,7 @@ @ stdcall RtlWakeAddressSingle(ptr) @ stdcall RtlWakeAllConditionVariable(ptr) @ stdcall RtlWakeConditionVariable(ptr) -@ stub RtlWalkFrameChain +@ stdcall RtlWalkFrameChain(ptr long long) @ stdcall RtlWalkHeap(long ptr) @ stdcall RtlWow64EnableFsRedirection(long) @ stdcall RtlWow64EnableFsRedirectionEx(long ptr) diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 0ef210a0331..1ab4aa032c0 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -308,6 +308,17 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, return 0; }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + + FIXME( "callers %p, count %u, flags %#x stub.\n", callers, count, flags ); + + return 0; +} + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 290639b676b..401db35d405 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -1481,6 +1481,17 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, return 0; }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + + FIXME( "callers %p, count %u, flags %#x stub.\n", callers, count, flags ); + + return 0; +} + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 0245aa602a1..9390ffa3df3 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -520,6 +520,30 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + CONTEXT context; + ULONG skip; + ULONG ret; + + TRACE( "callers %p, count %u, flags %#x.\n", callers, count, flags ); + + RtlCaptureContext( &context ); + + skip = (flags >> 8) & 0xff; + flags &= ~0xff00; + + if (flags) + FIXME( "flags %#x are not supported.\n", flags ); + + ret = capture_stack_back_trace( &context, skip, count, callers, NULL ); + return ret ? ret + skip : 0; +} + + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index dbf622392b7..e57b538d17c 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1545,6 +1545,30 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + CONTEXT context; + ULONG skip; + ULONG ret; + + TRACE( "callers %p, count %u, flags %#x.\n", callers, count, flags ); + + RtlCaptureContext( &context ); + + skip = (flags >> 8) & 0xff; + flags &= ~0xff00; + + if (flags) + FIXME( "flags %#x are not supported.\n", flags ); + + ret = capture_stack_back_trace( &context, skip, count, callers, NULL ); + return ret ? ret + skip : 0; +} + + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 6af68317732..63b1edeebc9 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -28,6 +28,7 @@ #include "winnt.h" #include "winreg.h" #include "winternl.h" +#include "ddk/ntddk.h" #include "ddk/wdm.h" #include "excpt.h" #include "wine/test.h" @@ -9113,6 +9114,55 @@ static void test_copy_context(void) } #endif
+static void test_walk_stack(void) +{ + ULONG frame_count, frame_count2; + void *addrs[256], *addrs2[256]; + void *start, *end; + unsigned int i; + + memset(addrs, 0xcc, sizeof(addrs)); + memset(addrs2, 0xcc, sizeof(addrs2)); + + frame_count = RtlCaptureStackBackTrace(0, ARRAY_SIZE(addrs), addrs, NULL); + frame_count2 = RtlWalkFrameChain(addrs2, ARRAY_SIZE(addrs2), 0); + + trace("frame_count %u.\n", frame_count); + + ok(frame_count > 1, "Got zero frame_count.\n"); + ok(frame_count == frame_count2, "Got unexpected frame_count %u, frame_count2 %u.\n", frame_count, frame_count2); + + start = test_walk_stack; + end = (BYTE *)start + 0x1000; + todo_wine_if(sizeof(void *) == 4) + ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", + start, end, addrs[0]); + todo_wine_if(sizeof(void *) == 4) + ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", + start, end, addrs2[0]); + + for (i = 1; i < frame_count; ++i) + { + ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]); + } + todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n"); + + memset(addrs, 0xcc, sizeof(addrs)); + memset(addrs2, 0xcc, sizeof(addrs2)); + + frame_count = RtlCaptureStackBackTrace(1, ARRAY_SIZE(addrs), addrs, NULL); + ok(frame_count == frame_count2 - 1, "Got unexpected frame_count %u.\n", frame_count); + + frame_count2 = RtlWalkFrameChain(addrs2, frame_count2, 1 << RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT) - 1; + ok(frame_count == frame_count2, "Got unexpected frame_count %u, frame_count2 %u.\n", frame_count, frame_count2); + + for (i = 0; i < frame_count; ++i) + { + ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]); + } + todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n"); +} + START_TEST(exception) { HMODULE hntdll = GetModuleHandleA("ntdll.dll"); @@ -9339,5 +9389,6 @@ START_TEST(exception) test_suspend_thread(); test_suspend_process(); test_unload_trace(); + test_walk_stack(); VirtualFree(code_mem, 0, MEM_RELEASE); } diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 0208e2f633f..b94e58ccb26 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1300,7 +1300,7 @@ @ stdcall RtlVerifyVersionInfo(ptr long int64) @ stdcall -arch=arm64,x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr) @ stub RtlVolumeDeviceToDosName -@ stub RtlWalkFrameChain +@ stdcall RtlWalkFrameChain(ptr long long) @ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long) @ stub RtlZeroHeap @ stdcall RtlZeroMemory(ptr long) diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index 41ad3d721bd..ce558139aa6 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -245,6 +245,8 @@ typedef EXPAND_STACK_CALLOUT *PEXPAND_STACK_CALLOUT; typedef GUID UUID; #endif
+#define RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT 8 + NTSTATUS WINAPI ExUuidCreate(UUID*); NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE,PULONG,PCONFIGURATION_TYPE,PULONG, PCONFIGURATION_TYPE,PULONG,PIO_QUERY_DEVICE_ROUTINE,PVOID); @@ -267,5 +269,6 @@ NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine(PCREATE_THREAD_NOTIFY_ROUTINE); NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE); void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE,PRTL_AVL_COMPARE_ROUTINE,PRTL_AVL_ALLOCATE_ROUTINE, PRTL_AVL_FREE_ROUTINE,void *); void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE,void *,ULONG,BOOL*); +ULONG WINAPI RtlWalkFrameChain(void **,ULONG,ULONG);
#endif diff --git a/include/winnt.h b/include/winnt.h index ef731e29c52..eb1bd165720 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -1840,6 +1840,8 @@ NTSYSAPI PVOID WINAPI RtlVirtualUnwind(DWORD,ULONG_PTR,ULONG_PTR,RUNTIME_FUNCT
#endif
+NTSYSAPI USHORT WINAPI RtlCaptureStackBackTrace(ULONG,ULONG,void **,ULONG *); + /* * Product types */
Hi,
Il 21/10/21 18:03, Paul Gofman ha scritto:
- start = test_walk_stack;
- end = (BYTE *)start + 0x1000;
- todo_wine_if(sizeof(void *) == 4)
- ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
start, end, addrs[0]);
- todo_wine_if(sizeof(void *) == 4)
- ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
start, end, addrs2[0]);
Another check you could do is whether addrs[1] == __builtin_extract_return_addr(__builtin_return_address(0)). Probably you don't even need __builtin_extract_return_addr, because I think it is required only for architectures for which we do not compile anyway.
Giovanni.
On 10/22/21 16:48, Giovanni Mascellani wrote:
Hi,
Il 21/10/21 18:03, Paul Gofman ha scritto:
+ start = test_walk_stack; + end = (BYTE *)start + 0x1000; + todo_wine_if(sizeof(void *) == 4) + ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", + start, end, addrs[0]); + todo_wine_if(sizeof(void *) == 4) + ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", + start, end, addrs2[0]);
Another check you could do is whether addrs[1] == __builtin_extract_return_addr(__builtin_return_address(0)). Probably you don't even need __builtin_extract_return_addr, because I think it is required only for architectures for which we do not compile anyway.
Giovanni.
Yes, I could, but do you think another check is really needed? It feels to me that might make the check more fragile than it already is. I'd rather consider maybe just dropping such check if it will be considered concerning. I added that only because I spotted the actual bug on x86 skipping the first frame and wanted to illustrate / verify that.
Hi,
Il 22/10/21 15:53, Paul Gofman ha scritto:
Yes, I could, but do you think another check is really needed? It feels to me that might make the check more fragile than it already is. I'd rather consider maybe just dropping such check if it will be considered concerning. I added that only because I spotted the actual bug on x86 skipping the first frame and wanted to illustrate / verify that.
No, it's not really needed. If you think we're better off without it, that's fine for me.
Giovanni.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/signal_x86_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index e57b538d17c..2f91abdbee0 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1507,7 +1507,7 @@ static USHORT capture_stack_back_trace( CONTEXT *context, ULONG skip, ULONG coun for (i = 0; i < skip + count; i++) { status = virtual_unwind( UNW_FLAG_NHANDLER, &dispatch, context ); - if (status != STATUS_SUCCESS) return i; + if (status != STATUS_SUCCESS) return num_entries;
if (!dispatch.EstablisherFrame) break;
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/signal_i386.c | 24 ++++++++++++++++++++++-- dlls/ntdll/tests/exception.c | 2 -- 2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 9390ffa3df3..108f140aeb8 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -480,6 +480,25 @@ __ASM_STDCALL_FUNC( RtlRaiseException, 4, "ret $4" ) /* actually never returns */
+/*********************************************************************** + * capture_context_wrapper (NTDLL.@) + */ +void WINAPI capture_context_wrapper(CONTEXT *); +__ASM_STDCALL_FUNC( capture_context_wrapper, 4, + "pushl %ebp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") + "movl %esp,%ebp\n\t" + __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") + "mov 8(%ebp),%eax\n\t" /* context */ + "pushl %eax\n\t" + "call " __ASM_STDCALL("RtlCaptureContext",4) "\n\t" + "leave\n\t" + __ASM_CFI(".cfi_def_cfa %esp,4\n\t") + __ASM_CFI(".cfi_same_value %ebp\n\t") + "ret $4" ) + + /************************************************************************* * capture_stack_back_trace */ @@ -515,7 +534,8 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, { CONTEXT context;
- RtlCaptureContext( &context ); + /* Need a wrapper as RtlCaptureContext() skips the last frame. */ + capture_context_wrapper( &context ); return capture_stack_back_trace( &context, skip, count, buffer, hash ); }
@@ -531,7 +551,7 @@ ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags)
TRACE( "callers %p, count %u, flags %#x.\n", callers, count, flags );
- RtlCaptureContext( &context ); + capture_context_wrapper( &context );
skip = (flags >> 8) & 0xff; flags &= ~0xff00; diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 63b1edeebc9..1d7f5ed4408 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -9134,10 +9134,8 @@ static void test_walk_stack(void)
start = test_walk_stack; end = (BYTE *)start + 0x1000; - todo_wine_if(sizeof(void *) == 4) ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", start, end, addrs[0]); - todo_wine_if(sizeof(void *) == 4) ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", start, end, addrs2[0]);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/signal_i386.c | 2 +- dlls/ntdll/signal_x86_64.c | 2 +- dlls/ntdll/tests/exception.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 108f140aeb8..a48edf864d3 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -518,7 +518,7 @@ static USHORT capture_stack_back_trace( CONTEXT *context, ULONG skip, ULONG coun
for (i = 0; i < count; i++) { - if (!is_valid_frame( frame )) break; + if (!is_valid_frame( frame ) || !frame[1]) break; buffer[i] = (void *)frame[1]; if (hash) *hash += frame[1]; frame = (ULONG *)*frame; diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 2f91abdbee0..d3a6d9b78c5 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1509,7 +1509,7 @@ static USHORT capture_stack_back_trace( CONTEXT *context, ULONG skip, ULONG coun status = virtual_unwind( UNW_FLAG_NHANDLER, &dispatch, context ); if (status != STATUS_SUCCESS) return num_entries;
- if (!dispatch.EstablisherFrame) break; + if (!dispatch.EstablisherFrame || !context->Rip) break;
if ((dispatch.EstablisherFrame & 7) || dispatch.EstablisherFrame < (ULONG64)NtCurrentTeb()->Tib.StackLimit || diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 1d7f5ed4408..846baeda4c8 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -9143,7 +9143,7 @@ static void test_walk_stack(void) { ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]); } - todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n"); + ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n");
memset(addrs, 0xcc, sizeof(addrs)); memset(addrs2, 0xcc, sizeof(addrs2)); @@ -9158,7 +9158,7 @@ static void test_walk_stack(void) { ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]); } - todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n"); + ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n"); }
START_TEST(exception)