This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Basic infrastructure for binder tracing #27383
Merged
elinor-fung
merged 9 commits into
dotnet:master
from
elinor-fung:binderTrace-infrastructure
Oct 28, 2019
Merged
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
abf0381
Basic infrastructure for binder tracing
elinor-fung 453ee01
Add test project for binder tracing tests
elinor-fung bdf6401
PR feedback
elinor-fung c73a3b8
Remove manually managed parts for calling into ActivityTracker and move
elinor-fung 59f58c4
Switch to CALL_MANAGED_METHOD macros
elinor-fung e2ac7d7
PR feedback
elinor-fung 6dd2f82
Rename events from bind/binder to load/loader
elinor-fung 3d22fb3
Move check for tracing enabled to ALC instead of Assembly
elinor-fung dcc10d7
Better naming
elinor-fung File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,5 +123,8 @@ public static Assembly GetCallingAssembly() | |
|
||
[MethodImpl(MethodImplOptions.InternalCall)] | ||
internal static extern uint GetAssemblyCount(); | ||
|
||
[MethodImpl(MethodImplOptions.InternalCall)] | ||
internal static extern bool IsBinderTracingEnabled(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am wondering whether AssemblyLoadContext would be a more appropriate place for this. Assembly is a grab bag of everything. AssemblyLoadContext is very specific to assembly loading and presumably quite a bit of the tracing will live on ALC. Also, this method can be called just |
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
// ============================================================ | ||
// | ||
// activitytracker.cpp | ||
// | ||
|
||
|
||
// | ||
// Helpers for interaction with the managed ActivityTracker | ||
// | ||
// ============================================================ | ||
|
||
#include "common.h" | ||
#include "activitytracker.h" | ||
|
||
void ActivityTracker::Start(/*out*/ GUID *activityId, /*out*/ GUID *relatedActivityId) | ||
{ | ||
GCX_COOP(); | ||
|
||
PREPARE_NONVIRTUAL_CALLSITE(METHOD__ACTIVITY_TRACKER__START_ASSEMBLY_BIND); | ||
DECLARE_ARGHOLDER_ARRAY(args, 1); | ||
elinor-fung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
args[ARGNUM_0] = PTR_TO_ARGHOLDER(activityId); | ||
args[ARGNUM_1] = PTR_TO_ARGHOLDER(relatedActivityId); | ||
|
||
CALL_MANAGED_METHOD_NORET(args) | ||
elinor-fung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
void ActivityTracker::Stop(/*out*/ GUID *activityId) | ||
{ | ||
GCX_COOP(); | ||
|
||
PREPARE_NONVIRTUAL_CALLSITE(METHOD__ACTIVITY_TRACKER__STOP_ASSEMBLY_BIND); | ||
DECLARE_ARGHOLDER_ARRAY(args, 1); | ||
args[ARGNUM_0] = PTR_TO_ARGHOLDER(activityId); | ||
|
||
CALL_MANAGED_METHOD_NORET(args) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
// ============================================================ | ||
// | ||
// bindertracing.cpp | ||
// | ||
|
||
|
||
// | ||
// Implements helpers for binder tracing | ||
// | ||
// ============================================================ | ||
|
||
#include "common.h" | ||
#include "bindertracing.h" | ||
|
||
#include "activitytracker.h" | ||
|
||
#ifdef FEATURE_EVENT_TRACE | ||
#include "eventtracebase.h" | ||
#endif // FEATURE_EVENT_TRACE | ||
|
||
using namespace BINDER_SPACE; | ||
|
||
namespace | ||
{ | ||
thread_local bool s_trackingBind = false; | ||
elinor-fung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
void FireAssemblyBindStart(const BinderTracing::AssemblyBindEvent::BindRequest &request) | ||
{ | ||
#ifdef FEATURE_EVENT_TRACE | ||
if (!EventEnabledAssemblyBindStart()) | ||
return; | ||
|
||
GUID activityId = GUID_NULL; | ||
GUID relatedActivityId = GUID_NULL; | ||
ActivityTracker::Start(&activityId, &relatedActivityId); | ||
|
||
FireEtwAssemblyBindStart( | ||
GetClrInstanceId(), | ||
request.AssemblyName, | ||
request.AssemblyPath, | ||
request.ParentAssembly, | ||
request.AssemblyLoadContext, | ||
&activityId, | ||
&relatedActivityId); | ||
#endif // FEATURE_EVENT_TRACE | ||
} | ||
|
||
void FireAssemblyBindStop(const BinderTracing::AssemblyBindEvent::BindRequest &request, bool success, const WCHAR *resultName, const WCHAR *resultPath, bool cached) | ||
{ | ||
#ifdef FEATURE_EVENT_TRACE | ||
if (!EventEnabledAssemblyBindStop()) | ||
return; | ||
|
||
GUID activityId = GUID_NULL; | ||
ActivityTracker::Stop(&activityId); | ||
|
||
FireEtwAssemblyBindStop( | ||
GetClrInstanceId(), | ||
request.AssemblyName, | ||
request.AssemblyPath, | ||
request.ParentAssembly, | ||
request.AssemblyLoadContext, | ||
success, | ||
resultName, | ||
resultPath, | ||
cached, | ||
&activityId); | ||
#endif // FEATURE_EVENT_TRACE | ||
} | ||
} | ||
|
||
bool BinderTracing::IsEnabled() | ||
{ | ||
#ifdef FEATURE_EVENT_TRACE | ||
// Just check for the AssemblyBindStart event being enabled. | ||
return EventEnabledAssemblyBindStart(); | ||
#endif // FEATURE_EVENT_TRACE | ||
return false; | ||
} | ||
|
||
namespace BinderTracing | ||
{ | ||
AssemblyBindEvent::AssemblyBindEvent(AssemblySpec *assemblySpec) | ||
: m_bindRequest { assemblySpec } | ||
, m_prevTrackingBind { s_trackingBind } | ||
, m_success { false } | ||
, m_cached { false } | ||
{ | ||
_ASSERTE(assemblySpec != nullptr); | ||
|
||
// ActivityTracker or EventSource may have triggered the system satellite load. | ||
// Don't track system satellite binding to avoid potential infinite recursion. | ||
s_trackingBind = BinderTracing::IsEnabled() && !m_bindRequest.AssemblySpec->IsMscorlibSatellite(); | ||
if (s_trackingBind) | ||
{ | ||
m_bindRequest.AssemblySpec->GetFileOrDisplayName(ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE | ASM_DISPLAYF_PUBLIC_KEY_TOKEN, m_bindRequest.AssemblyName); | ||
FireAssemblyBindStart(m_bindRequest); | ||
} | ||
} | ||
|
||
AssemblyBindEvent::~AssemblyBindEvent() | ||
{ | ||
if (s_trackingBind) | ||
FireAssemblyBindStop(m_bindRequest, m_success, m_resultName.GetUnicode(), m_resultPath.GetUnicode(), m_cached); | ||
|
||
s_trackingBind = m_prevTrackingBind; | ||
} | ||
|
||
void AssemblyBindEvent::SetResult(PEAssembly *assembly) | ||
{ | ||
m_success = assembly != nullptr; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
// | ||
// activitytracker.h | ||
// | ||
|
||
#ifndef __ACTIVITY_TRACKER_H__ | ||
#define __ACTIVITY_TRACKER_H__ | ||
|
||
namespace ActivityTracker | ||
{ | ||
void Start(/*out*/ GUID *activityId, /*out*/ GUID *relatedActivityId); | ||
void Stop(/*out*/ GUID *activityId); | ||
}; | ||
|
||
#endif // __ACTIVITY_TRACKER_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
// | ||
// bindertracing.h | ||
// | ||
|
||
#ifndef __BINDER_TRACING_H__ | ||
#define __BINDER_TRACING_H__ | ||
|
||
class AssemblySpec; | ||
class PEAssembly; | ||
|
||
namespace BinderTracing | ||
{ | ||
bool IsEnabled(); | ||
|
||
// If tracing is enabled, this class fires an assembly bind start event on construction | ||
// and the corresponding stop event on destruction | ||
class AssemblyBindEvent | ||
elinor-fung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
public: | ||
// This class assumes the assembly spec will have a longer lifetime than itself | ||
AssemblyBindEvent(AssemblySpec *assemblySpec); | ||
~AssemblyBindEvent(); | ||
|
||
void SetResult(PEAssembly *assembly); | ||
|
||
struct BindRequest | ||
{ | ||
AssemblySpec *AssemblySpec; | ||
SString AssemblyName; | ||
SString AssemblyPath; | ||
SString ParentAssembly; | ||
SString AssemblyLoadContext; | ||
}; | ||
|
||
private: | ||
BindRequest m_bindRequest; | ||
|
||
bool m_prevTrackingBind; | ||
|
||
bool m_success; | ||
SString m_resultName; | ||
SString m_resultPath; | ||
bool m_cached; | ||
}; | ||
}; | ||
|
||
#endif // __BINDER_TRACING_H__ |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know we like to call this assembly binding for historic reasons, but our documentation and customers call this assembly loading. E.g.: https://docs.microsoft.com/en-us/dotnet/core/dependency-loading/loading-managed
I would stick with assembly loading for anything that is public facing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that mean we don't want to call it assembly binding in the events either? I put them under the
Binder
keyword (that used to beFusion
); I didn't want to have them underLoader
, since I think we'd want to enable them separately. The new events are also under theAssemblyBinder
task and namedAssemblyBind*
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to call this
AssemblyLoader
/AssemblyLoad
?I would be interested to know what other people (e.g. PMs) think about the right public facing names for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe also
AssemblyResolver
/AssemblyResolve
? Since we have theAssemblyLoadContext.Resolving
andAppDomain.AssemblyResolve
events.Will check with PMs.