From a7c9ca110096c27de23f045cd176c2109d0676d9 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Mon, 18 Mar 2019 15:19:45 -0700 Subject: Avoid stack walk as specified in the exclusion list --- build.cmd | 4 ++-- build.sh | 2 +- src/scripts/genEtwProvider.py | 53 +++-------------------------------------- src/scripts/genEventPipe.py | 29 +++++++++++++++------- src/scripts/utilities.py | 46 +++++++++++++++++++++++++++++++++++ src/vm/eventpipeeventsource.cpp | 1 + src/vm/eventpipeinternal.cpp | 2 +- src/vm/eventpipeprovider.cpp | 13 ---------- src/vm/eventpipeprovider.h | 9 +------ 9 files changed, 75 insertions(+), 84 deletions(-) diff --git a/build.cmd b/build.cmd index 3617b1b48a..1502783ab9 100644 --- a/build.cmd +++ b/build.cmd @@ -426,7 +426,7 @@ if %__BuildNative% EQU 1 ( "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventing.py --inc %__IntermediatesIncDir% --dummy %__IntermediatesIncDir%\etmdummy.h --man %__SourceDir%\vm\ClrEtwAll.man --nonextern --noxplatheader|| exit /b 1 echo %__MsgPrefix%Laying out dynamically generated EventPipe Implementation - "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate %__IntermediatesEventingDir%\eventpipe --nonextern || exit /b 1 + "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --exc %__SourceDir%\vm\ClrEtwAllMeta.lst --intermediate %__IntermediatesEventingDir%\eventpipe --nonextern || exit /b 1 echo %__MsgPrefix%Laying out ETW event logging interface "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEtwProvider.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate %__IntermediatesIncDir% --exc %__SourceDir%\vm\ClrEtwAllMeta.lst || exit /b 1 @@ -448,7 +448,7 @@ if %__BuildCrossArchNative% EQU 1 ( "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventing.py --inc !__CrossCompIntermediatesIncDir! --dummy !__CrossCompIntermediatesIncDir!\etmdummy.h --man %__SourceDir%\vm\ClrEtwAll.man --nonextern || exit /b 1 echo %__MsgPrefix%Laying out dynamically generated EventPipe Implementation - "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate !__CrossCompIntermediatesEventingDir!\eventpipe --nonextern || exit /b 1 + "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --exc %__SourceDir%\vm\ClrEtwAllMeta.lst --intermediate !__CrossCompIntermediatesEventingDir!\eventpipe --nonextern || exit /b 1 echo %__MsgPrefix%Laying out dynamically generated EventSource classes "!PYTHON!" -B -Wall %__SourceDir%\scripts\genRuntimeEventSources.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate !__CrossCompIntermediatesEventingDir! || exit /b 1 diff --git a/build.sh b/build.sh index 7e9ce99124..a24bd89070 100755 --- a/build.sh +++ b/build.sh @@ -188,7 +188,7 @@ generate_event_logging_sources() fi echo "Laying out dynamically generated EventPipe Implementation" - $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genEventPipe.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__OutputEventingDir/eventpipe" + $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genEventPipe.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --exc "$__ProjectRoot/src/vm/ClrEtwAllMeta.lst" --intermediate "$__OutputEventingDir/eventpipe" echo "Laying out dynamically generated EventSource classes" $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genRuntimeEventSources.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__OutputEventingDir" diff --git a/src/scripts/genEtwProvider.py b/src/scripts/genEtwProvider.py index 79a286a501..89d3119cf4 100644 --- a/src/scripts/genEtwProvider.py +++ b/src/scripts/genEtwProvider.py @@ -14,7 +14,7 @@ import argparse import subprocess import xml.dom.minidom as DOM from genEventing import parseTemplateNodes -from utilities import open_for_update, update_directory +from utilities import open_for_update, update_directory, parseExclusionList macroheader_filename = "etwmacros.h" mcheader_filename = "ClrEtwAll.h" @@ -102,59 +102,12 @@ def genXplatHeader(intermediate): #endif //_CLR_XPLAT_EVENTS_H_ """.format(etw_dirname, macroheader_filename, mcheader_filename)) - -class EventExclusions: - def __init__(self): - self.nostack = set() - self.explicitstack = set() - self.noclrinstance = set() - -def parseExclusionList(exclusion_filename): - with open(exclusion_filename,'r') as ExclusionFile: - exclusionInfo = EventExclusions() - - for line in ExclusionFile: - line = line.strip() - - #remove comments - if not line or line.startswith('#'): - continue - - tokens = line.split(':') - #entries starting with nomac are ignored - if "nomac" in tokens: - continue - - if len(tokens) > 5: - raise Exception("Invalid Entry " + line + "in "+ exclusion_filename) - - eventProvider = tokens[2] - eventTask = tokens[1] - eventSymbol = tokens[4] - - if eventProvider == '': - eventProvider = "*" - if eventTask == '': - eventTask = "*" - if eventSymbol == '': - eventSymbol = "*" - entry = eventProvider + ":" + eventTask + ":" + eventSymbol - - if tokens[0].lower() == "nostack": - exclusionInfo.nostack.add(entry) - if tokens[0].lower() == "stack": - exclusionInfo.explicitstack.add(entry) - if tokens[0].lower() == "noclrinstanceid": - exclusionInfo.noclrinstance.add(entry) - - return exclusionInfo - def getStackWalkBit(eventProvider, taskName, eventSymbol, stackSet): for entry in stackSet: tokens = entry.split(':') if len(tokens) != 3: - raise Exception("Error, possible error in the script which introduced the enrty "+ entry) + raise Exception("Error, possible error in the script which introduced the entry "+ entry) eventCond = tokens[0] == eventProvider or tokens[0] == "*" taskCond = tokens[1] == taskName or tokens[1] == "*" @@ -164,7 +117,7 @@ def getStackWalkBit(eventProvider, taskName, eventSymbol, stackSet): return False return True -#Add the miscelaneous checks here +#Add the miscellaneous checks here def checkConsistency(manifest, exclusion_filename): tree = DOM.parse(manifest) exclusionInfo = parseExclusionList(exclusion_filename) diff --git a/src/scripts/genEventPipe.py b/src/scripts/genEventPipe.py index 59f5d711fe..f66b54ea28 100644 --- a/src/scripts/genEventPipe.py +++ b/src/scripts/genEventPipe.py @@ -3,7 +3,7 @@ from genEventing import * from genLttngProvider import * import os import xml.dom.minidom as DOM -from utilities import open_for_update +from utilities import open_for_update, parseExclusionList stdprolog_cpp = """// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. @@ -73,7 +73,7 @@ def generateMethodSignatureWrite(eventName, template, extern): return ''.join(sig_pieces) def generateClrEventPipeWriteEventsImpl( - providerName, eventNodes, allTemplates, extern): + providerName, eventNodes, allTemplates, extern, exclusionList): providerPrettyName = providerName.replace("Windows-", '') providerPrettyName = providerPrettyName.replace("Microsoft-", '') providerPrettyName = providerPrettyName.replace('-', '_') @@ -153,8 +153,14 @@ def generateClrEventPipeWriteEventsImpl( eventLevel = eventLevel.replace("win:", "EventPipeEventLevel::") taskName = eventNode.getAttribute('task') - initEvent = """ EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s); -""" % (eventName, providerPrettyName, eventValue, eventKeywordsMask, eventVersion, eventLevel) + needStack = "true" + for nostackentry in exclusionList.nostack: + tokens = nostackentry.split(':') + if tokens[2] == eventName: + needStack = "false" + + initEvent = """ EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s,%s); +""" % (eventName, providerPrettyName, eventValue, eventKeywordsMask, eventVersion, eventLevel, needStack) WriteEventImpl.append(initEvent) WriteEventImpl.append("}") @@ -384,7 +390,7 @@ bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, helper.close() def generateEventPipeImplFiles( - etwmanifest, eventpipe_directory, extern): + etwmanifest, eventpipe_directory, extern, exclusionList): tree = DOM.parse(etwmanifest) # Find the src directory starting with the assumption that @@ -460,11 +466,12 @@ bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& size, providerName, eventNodes, allTemplates, - extern) + "\n") + extern, + exclusionList) + "\n") def generateEventPipeFiles( - etwmanifest, intermediate, extern): + etwmanifest, intermediate, extern, exclusionList): eventpipe_directory = os.path.join(intermediate, eventpipe_dirname) tree = DOM.parse(etwmanifest) @@ -487,7 +494,8 @@ def generateEventPipeFiles( generateEventPipeImplFiles( etwmanifest, eventpipe_directory, - extern + extern, + exclusionList ) import argparse @@ -502,6 +510,8 @@ def main(argv): required = parser.add_argument_group('required arguments') required.add_argument('--man', type=str, required=True, help='full path to manifest containig the description of events') + required.add_argument('--exc', type=str, required=True, + help='full path to exclusion list') required.add_argument('--intermediate', type=str, required=True, help='full path to eventprovider intermediate directory') required.add_argument('--nonextern', action='store_true', @@ -512,10 +522,11 @@ def main(argv): return 1 sClrEtwAllMan = args.man + exclusion_filename = args.exc intermediate = args.intermediate extern = not args.nonextern - generateEventPipeFiles(sClrEtwAllMan, intermediate, extern) + generateEventPipeFiles(sClrEtwAllMan, intermediate, extern, parseExclusionList(exclusion_filename)) if __name__ == '__main__': return_code = main(sys.argv[1:]) diff --git a/src/scripts/utilities.py b/src/scripts/utilities.py index 7e69f462a9..c4767a43b7 100644 --- a/src/scripts/utilities.py +++ b/src/scripts/utilities.py @@ -120,3 +120,49 @@ def update_directory(srcpath, dstpath, recursive=True, destructive=True, shallow if not os.path.exists(dstdir): os.makedirs(dstdir) update_directory(srcdir, dstdir, recursive, destructive, shallow) + +class EventExclusions: + def __init__(self): + self.nostack = set() + self.explicitstack = set() + self.noclrinstance = set() + +def parseExclusionList(exclusion_filename): + with open(exclusion_filename,'r') as ExclusionFile: + exclusionInfo = EventExclusions() + + for line in ExclusionFile: + line = line.strip() + + #remove comments + if not line or line.startswith('#'): + continue + + tokens = line.split(':') + #entries starting with nomac are ignored + if "nomac" in tokens: + continue + + if len(tokens) > 5: + raise Exception("Invalid Entry " + line + "in "+ exclusion_filename) + + eventProvider = tokens[2] + eventTask = tokens[1] + eventSymbol = tokens[4] + + if eventProvider == '': + eventProvider = "*" + if eventTask == '': + eventTask = "*" + if eventSymbol == '': + eventSymbol = "*" + entry = eventProvider + ":" + eventTask + ":" + eventSymbol + + if tokens[0].lower() == "nostack": + exclusionInfo.nostack.add(entry) + if tokens[0].lower() == "stack": + exclusionInfo.explicitstack.add(entry) + if tokens[0].lower() == "noclrinstanceid": + exclusionInfo.noclrinstance.add(entry) + + return exclusionInfo \ No newline at end of file diff --git a/src/vm/eventpipeeventsource.cpp b/src/vm/eventpipeeventsource.cpp index 20613b8d53..ca62677cde 100644 --- a/src/vm/eventpipeeventsource.cpp +++ b/src/vm/eventpipeeventsource.cpp @@ -51,6 +51,7 @@ EventPipeEventSource::EventPipeEventSource() 0, /* keywords */ 0, /* eventVersion */ EventPipeEventLevel::LogAlways, + false, /* needStack */ pMetadata, (unsigned int)metadataLength); diff --git a/src/vm/eventpipeinternal.cpp b/src/vm/eventpipeinternal.cpp index c02317f491..30a14642c0 100644 --- a/src/vm/eventpipeinternal.cpp +++ b/src/vm/eventpipeinternal.cpp @@ -110,7 +110,7 @@ INT_PTR QCALLTYPE EventPipeInternal::DefineEvent( _ASSERTE(provHandle != NULL); EventPipeProvider *pProvider = reinterpret_cast(provHandle); - pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, (BYTE *)pMetadata, metadataLength); + pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, /* needStack = */ true, (BYTE *)pMetadata, metadataLength); _ASSERTE(pEvent != NULL); END_QCALL; diff --git a/src/vm/eventpipeprovider.cpp b/src/vm/eventpipeprovider.cpp index 4630c93acd..4c6eabcf50 100644 --- a/src/vm/eventpipeprovider.cpp +++ b/src/vm/eventpipeprovider.cpp @@ -130,19 +130,6 @@ void EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, E InvokeCallback(pFilterData); } -EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata, unsigned int metadataLength) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - return AddEvent(eventID, keywords, eventVersion, level, true /* needStack */, pMetadata, metadataLength); -} - EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength) { CONTRACTL diff --git a/src/vm/eventpipeprovider.h b/src/vm/eventpipeprovider.h index cf89cf3229..8ae57d9d62 100644 --- a/src/vm/eventpipeprovider.h +++ b/src/vm/eventpipeprovider.h @@ -70,17 +70,10 @@ public: bool EventEnabled(INT64 keywords, EventPipeEventLevel eventLevel) const; // Create a new event. - EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata = NULL, unsigned int metadataLength = 0); + EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0); private: - // Create a new event, but allow needStack to be specified. - // In general, we want stack walking to be controlled by the consumer and not the producer of events. - // However, there are a couple of cases that we know we don't want to do a stackwalk that would affect performance significantly: - // 1. Sample profiler events: The sample profiler already does a stack walk of the target thread. Doing one of the sampler thread is a waste. - // 2. Metadata events: These aren't as painful but because we have to keep this functionality around, might as well use it. - EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0); - // Add an event to the provider. void AddEvent(EventPipeEvent &event); -- cgit v1.2.3