使用 FramesToSkip 的 CaptureStackBackTrace 不一致
CaptureStackBackTrace inconsistencies using FramesToSkip
在 windows 上,您可以使用 CaptureStackBackTrace 作为
捕获堆栈跟踪
void* frames[USHRT_MAX];
USHORT framesCount = CaptureStackBackTrace(0, USHRT_MAX, frames, NULL);
但是,在循环中通过较小的块捕获它以避免分配 USHRT_MAX
缓冲区不会提供相同的结果。
这个代码
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
__declspec(noinline) void CheckStack(void)
{
printf("Checking stack...\n");
void* entireStack[USHRT_MAX];
USHORT frameCount = CaptureStackBackTrace(0, USHRT_MAX, entireStack, NULL);
printf("Stack size is: %u\n", frameCount);
ULONG frameOffset = 1;
for (;;)
{
void* chunk[64];
USHORT framesFound = CaptureStackBackTrace(frameOffset, 64, chunk, NULL);
if (framesFound)
{
if (memcmp(entireStack + frameOffset, chunk, sizeof(chunk)) != 0)
{
printf("Incorrect content\n");
}
frameOffset += (ULONG)framesFound;
}
else
{
break;
}
}
if (frameCount != frameOffset)
{
printf("Incorrect count (%u != %u)\n", frameCount, frameOffset);
}
printf("Done\n");
}
__declspec(noinline) void Test(int i)
{
if (i != 500)
Test(++i);
else
CheckStack();
}
int main()
{
Test(0);
}
产生以下输出
Checking stack...
Stack size is: 507
Incorrect count (507 != 257)
Done
构建时 cl /Od main.c /link /OUT:main.exe
。
我是否错误地使用了 FramesToSkip
参数或者为什么计数不相等?
如果您使用的是 Windows Server 2003 和 Windows XP,
The sum of the FramesToSkip and FramesToCapture parameters must be
less than 63.
在文档中。
否则,正如@RbMm所说,在API源代码中,有以下逻辑:
if(FramesToSkip>0xfe)
{
return 0; //There are too many stack structures skipped, returning directly to 0.
}
然而,CaptureStackBackTrace and RtlCaptureStackBackTrace 中的 msdn 均未提及此内容。
我这里就不去post源码了,而是在调试中证明一下:
1.Create一个样本:
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
__declspec(noinline) void CheckStack(void)
{
void* entireStack[USHRT_MAX];
USHORT frameCount = CaptureStackBackTrace(255, USHRT_MAX, entireStack, NULL);
}
__declspec(noinline) void Test(int i)
{
if (i != 500)
Test(++i);
else
CheckStack();
}
int main()
{
Test(0);
}
2。在反汇编中进入CaptureStackBackTrace
:
可以看到dword ptr[ebp+8]
(CaptureStackBackTrace
入栈的第一个参数)会和0feh
(254)进行比较。如果为真,return 0.
在 windows 上,您可以使用 CaptureStackBackTrace 作为
捕获堆栈跟踪void* frames[USHRT_MAX];
USHORT framesCount = CaptureStackBackTrace(0, USHRT_MAX, frames, NULL);
但是,在循环中通过较小的块捕获它以避免分配 USHRT_MAX
缓冲区不会提供相同的结果。
这个代码
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
__declspec(noinline) void CheckStack(void)
{
printf("Checking stack...\n");
void* entireStack[USHRT_MAX];
USHORT frameCount = CaptureStackBackTrace(0, USHRT_MAX, entireStack, NULL);
printf("Stack size is: %u\n", frameCount);
ULONG frameOffset = 1;
for (;;)
{
void* chunk[64];
USHORT framesFound = CaptureStackBackTrace(frameOffset, 64, chunk, NULL);
if (framesFound)
{
if (memcmp(entireStack + frameOffset, chunk, sizeof(chunk)) != 0)
{
printf("Incorrect content\n");
}
frameOffset += (ULONG)framesFound;
}
else
{
break;
}
}
if (frameCount != frameOffset)
{
printf("Incorrect count (%u != %u)\n", frameCount, frameOffset);
}
printf("Done\n");
}
__declspec(noinline) void Test(int i)
{
if (i != 500)
Test(++i);
else
CheckStack();
}
int main()
{
Test(0);
}
产生以下输出
Checking stack...
Stack size is: 507
Incorrect count (507 != 257)
Done
构建时 cl /Od main.c /link /OUT:main.exe
。
我是否错误地使用了 FramesToSkip
参数或者为什么计数不相等?
如果您使用的是 Windows Server 2003 和 Windows XP,
The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
在文档中。
否则,正如@RbMm所说,在API源代码中,有以下逻辑:
if(FramesToSkip>0xfe)
{
return 0; //There are too many stack structures skipped, returning directly to 0.
}
然而,CaptureStackBackTrace and RtlCaptureStackBackTrace 中的 msdn 均未提及此内容。 我这里就不去post源码了,而是在调试中证明一下:
1.Create一个样本:
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
__declspec(noinline) void CheckStack(void)
{
void* entireStack[USHRT_MAX];
USHORT frameCount = CaptureStackBackTrace(255, USHRT_MAX, entireStack, NULL);
}
__declspec(noinline) void Test(int i)
{
if (i != 500)
Test(++i);
else
CheckStack();
}
int main()
{
Test(0);
}
2。在反汇编中进入CaptureStackBackTrace
:
dword ptr[ebp+8]
(CaptureStackBackTrace
入栈的第一个参数)会和0feh
(254)进行比较。如果为真,return 0.