Skip to content

Commit 91706b3

Browse files
committed
Fix native and managed callstacks merge
1 parent d0fe312 commit 91706b3

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

profiler/src/ProfilerEngine/Datadog.Profiler.Native/CrashReporting.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,17 +355,19 @@ int32_t CrashReporting::ExportImpl(ddog_Endpoint* endpoint)
355355
std::vector<StackFrame> CrashReporting::MergeFrames(const std::vector<StackFrame>& nativeFrames, const std::vector<StackFrame>& managedFrames)
356356
{
357357
std::vector<StackFrame> result;
358+
// it's safe here to not use nativeFrames.size() + managedFrames.size()
359+
// because the managed frames should be a subset of the native frames
358360
result.reserve(std::max(nativeFrames.size(), managedFrames.size()));
359361

360362
size_t i = 0, j = 0;
361363
while (i < nativeFrames.size() && j < managedFrames.size())
362364
{
363-
if (nativeFrames[i].sp < managedFrames[j].sp)
365+
if (nativeFrames[i].sp > managedFrames[j].sp)
364366
{
365367
result.push_back(nativeFrames[i]);
366368
++i;
367369
}
368-
else if (managedFrames[j].sp < nativeFrames[i].sp)
370+
else if (managedFrames[j].sp > nativeFrames[i].sp)
369371
{
370372
result.push_back(managedFrames[j]);
371373
++j;

profiler/src/ProfilerEngine/Datadog.Profiler.Native/CrashReporting.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ class CrashReporting : public ICrashReporting
143143
virtual std::vector<StackFrame> GetThreadFrames(int32_t tid, ResolveManagedCallstack resolveManagedCallstack, void* context) = 0;
144144
virtual std::string GetSignalInfo(int32_t signal) = 0;
145145

146+
#ifdef DD_TEST
147+
friend class CrashReportingTest_CheckMergedCallstack_Test;
148+
#endif
146149
static std::vector<StackFrame> MergeFrames(const std::vector<StackFrame>& nativeFrames, const std::vector<StackFrame>& managedFrames);
147150
private:
148151
int32_t ExportImpl(ddog_Endpoint* endpoint);

profiler/test/Datadog.Profiler.Native.Tests/CrashReportingTest.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
22
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc.
33

4+
#include "gtest/gtest.h"
5+
6+
#include "unknwn.h"
7+
8+
const IID IID_IUnknown = {0x00000000,
9+
0x0000,
10+
0x0000,
11+
{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
12+
13+
#include "CrashReporting.h"
14+
415
#ifdef _WIN32
516

617
#include "resource.h"
7-
#include "gtest/gtest.h"
818
#include <string_view>
919
#include <windows.h>
1020
#include <vector>
@@ -130,5 +140,38 @@ TEST(CrashReportingTest, ExtractPdbSignaturePE64)
130140
// | Pdb signature |Age|
131141
ASSERT_STRCASEEQ(buildIdStr.data(), "C465AFCDBDBC58A0100995839A0E4C271");
132142
}
143+
#endif
144+
133145

134-
#endif
146+
TEST(CrashReportingTest, CheckMergedCallstack)
147+
{
148+
std::vector<StackFrame> nativeFrames = {
149+
{0x7F4DECDF2BC0, 0x7F478000ACE0, "__GI___wait4", 0x7F4DECDF2BC0, 0x7F4DECD1F000, false, ""},
150+
{0x7F4DECB882F0, 0x7F478000AD10, "PROCCreateCrashDump(std::vector<char const*, std::allocator<char const*> >&, char*, int, bool)", 0x7F4DECB882F0, 0x7F4DEC514000, false, ""},
151+
{0x7F4D778E1A7D, 0x7F476CC3E9D0, "/memfd:doublemapper (deleted)!<unknown>+b84da7d", 0x7F4D778E1A7D, 0x7F4D6C094000, false, ""},
152+
{0x7F4D76593D2A, 0x7F476CC3EA10, "/memfd:doublemapper (deleted)!<unknown>+a4ffd2a", 0x7F4D76593D2A, 0x7F4D6C094000, false, ""},
153+
{0x7F4D6D7D3924, 0x7F476CC3EA90, "/usr/share/dotnet/shared/Microsoft.NETCore.App/9.0.10/System.Private.CoreLib.dll!<unknown>+5e370b924", 0x7F4D6D7D3924, 0x7F478A0C8000, false, ""},
154+
};
155+
156+
std::vector<StackFrame> managedFrames = {
157+
{0x7F4D778E1A7D, 0x7F476CC3E9D0, "System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>+AsyncStateMachineBox<Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol+<ProcessRequests>d__238<System.__Canon>>.MoveNext", 0x7F4D778E1A7D, 0x7F4D6C094000, false, ""},
158+
{0x7F4D76593D2A, 0x7F476CC3EA10, "System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch", 0x7F4D76593D2A, 0x7F4D6C094000, false, ""},
159+
{0x7F4D6D7D3924, 0x7F476CC3EA90, "System.Private.CoreLib.dll!System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart", 0x7F4D6D7D3924, 0x7F478A0C8000, false, ""},
160+
};
161+
162+
auto mergedFrames = CrashReporting::MergeFrames(nativeFrames, managedFrames);
163+
164+
std::vector<std::string> expectedFunctions = {
165+
"__GI___wait4",
166+
"PROCCreateCrashDump(std::vector<char const*, std::allocator<char const*> >&, char*, int, bool)",
167+
"System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>+AsyncStateMachineBox<Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol+<ProcessRequests>d__238<System.__Canon>>.MoveNext",
168+
"System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch",
169+
"System.Private.CoreLib.dll!System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart",
170+
};
171+
172+
ASSERT_EQ(mergedFrames.size(), expectedFunctions.size());
173+
for (size_t i = 0; i < mergedFrames.size(); i++)
174+
{
175+
ASSERT_EQ(mergedFrames[i].method, expectedFunctions[i]);
176+
}
177+
}

0 commit comments

Comments
 (0)