diff options
Diffstat (limited to 'src/scripts/genEtwProvider.py')
-rw-r--r-- | src/scripts/genEtwProvider.py | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/src/scripts/genEtwProvider.py b/src/scripts/genEtwProvider.py deleted file mode 100644 index fc9d43800f..0000000000 --- a/src/scripts/genEtwProvider.py +++ /dev/null @@ -1,312 +0,0 @@ -## -## 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. -## -## This script generates the interface to ETW using MC.exe - -import os -from os import path -import shutil -import re -import sys -import argparse -import subprocess -import xml.dom.minidom as DOM -from genEventing import parseTemplateNodes -from utilities import open_for_update - -macroheader_filename = "etwmacros.h" -mcheader_filename = "ClrEtwAll.h" -clrxplat_filename = "clrxplatevents.h" -etw_dirname = "etw" -replacements = [ - (r"EventEnabled", "EventXplatEnabled"), - (r"\bPVOID\b", "void*") -] - -stdprolog_cpp=""" -// 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. - -/****************************************************************** - -DO NOT MODIFY. AUTOGENERATED FILE. -This file is generated using the logic from <root>/src/scripts/genEtwProvider.py - -******************************************************************/ -""" -stdprolog_cmake=""" -# -# -#****************************************************************** - -#DO NOT MODIFY. AUTOGENERATED FILE. -#This file is generated using the logic from <root>/src/scripts/genEtwProvider.py - -#****************************************************************** -""" - -def genProviderInterface(manifest, intermediate): - provider_dirname = os.path.join(intermediate, etw_dirname) - - if not os.path.exists(provider_dirname): - os.makedirs(provider_dirname) - - cmd = ['mc.exe', '-h', provider_dirname, '-r', provider_dirname, '-b', '-co', '-um', '-p', 'FireEtXplat', manifest] - subprocess.check_call(cmd) - - header_text = None - with open(path.join(provider_dirname, mcheader_filename), 'r') as mcheader_file: - header_text = mcheader_file.read() - - for pattern, replacement in replacements: - header_text = re.sub(pattern, replacement, header_text) - - with open_for_update(path.join(provider_dirname, mcheader_filename)) as mcheader_file: - mcheader_file.write(header_text) - -def genCmake(intermediate): - # Top level Cmake - - with open_for_update(os.path.join(intermediate, "CMakeLists.txt")) as cmake_file: - cmake_file.write(stdprolog_cmake) - cmake_file.write(""" -project(eventprovider) - -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -include_directories({0}) - -add_library_clr(eventprovider - STATIC - "{0}/{1}" - "{0}/{2}" -) - -#set_target_properties(eventprovider PROPERTIES LINKER_LANGUAGE Hxx) -""".format(etw_dirname, macroheader_filename, "ClrEtwAll.cpp")) - -def genXplatHeader(intermediate): - with open_for_update(path.join(intermediate, clrxplat_filename)) as header_file: - header_file.write(""" -#ifndef _CLR_XPLAT_EVENTS_H_ -#define _CLR_XPLAT_EVENTS_H_ - -#include "{0}/{1}" -#include "{0}/{2}" - -#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) - - eventCond = tokens[0] == eventProvider or tokens[0] == "*" - taskCond = tokens[1] == taskName or tokens[1] == "*" - symbolCond = tokens[2] == eventSymbol or tokens[2] == "*" - - if eventCond and taskCond and symbolCond: - return False - return True - -#Add the miscelaneous checks here -def checkConsistency(manifest, exclusion_filename): - tree = DOM.parse(manifest) - exclusionInfo = parseExclusionList(exclusion_filename) - for providerNode in tree.getElementsByTagName('provider'): - - stackSupportSpecified = {} - eventNodes = providerNode.getElementsByTagName('event') - templateNodes = providerNode.getElementsByTagName('template') - eventProvider = providerNode.getAttribute('name') - allTemplates = parseTemplateNodes(templateNodes) - - for eventNode in eventNodes: - taskName = eventNode.getAttribute('task') - eventSymbol = eventNode.getAttribute('symbol') - eventTemplate = eventNode.getAttribute('template') - eventValue = int(eventNode.getAttribute('value')) - clrInstanceBit = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.noclrinstance) - sLookupFieldName = "ClrInstanceID" - sLookupFieldType = "win:UInt16" - - if clrInstanceBit and allTemplates.get(eventTemplate): - # check for the event template and look for a field named ClrInstanceId of type win:UInt16 - fnParam = allTemplates[eventTemplate].getFnParam(sLookupFieldName) - - if not(fnParam and fnParam.winType == sLookupFieldType): - raise Exception(exclusion_filename + ":No " + sLookupFieldName + " field of type " + sLookupFieldType + " for event symbol " + eventSymbol) - - # If some versions of an event are on the nostack/stack lists, - # and some versions are not on either the nostack or stack list, - # then developer likely forgot to specify one of the versions - - eventStackBitFromNoStackList = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.nostack) - eventStackBitFromExplicitStackList = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.explicitstack) - sStackSpecificityError = exclusion_filename + ": Error processing event :" + eventSymbol + "(ID" + str(eventValue) + "): This file must contain either ALL versions of this event or NO versions of this event. Currently some, but not all, versions of this event are present\n" - - if not stackSupportSpecified.get(eventValue): - # Haven't checked this event before. Remember whether a preference is stated - if ( not eventStackBitFromNoStackList) or ( not eventStackBitFromExplicitStackList): - stackSupportSpecified[eventValue] = True - else: - stackSupportSpecified[eventValue] = False - else: - # We've checked this event before. - if stackSupportSpecified[eventValue]: - # When we last checked, a preference was previously specified, so it better be specified here - if eventStackBitFromNoStackList and eventStackBitFromExplicitStackList: - raise Exception(sStackSpecificityError) - else: - # When we last checked, a preference was not previously specified, so it better not be specified here - if ( not eventStackBitFromNoStackList) or ( not eventStackBitFromExplicitStackList): - raise Exception(sStackSpecificityError) - -def genEtwMacroHeader(manifest, exclusion_filename, intermediate): - provider_dirname = os.path.join(intermediate, etw_dirname) - - if not os.path.exists(provider_dirname): - os.makedirs(provider_dirname) - - tree = DOM.parse(manifest) - numOfProviders = len(tree.getElementsByTagName('provider')) - nMaxEventBytesPerProvider = 64 - - exclusionInfo = parseExclusionList(exclusion_filename) - - with open_for_update(os.path.join(provider_dirname, macroheader_filename)) as header_file: - header_file.write(stdprolog_cpp + "\n") - - header_file.write("#define NO_OF_ETW_PROVIDERS " + str(numOfProviders) + "\n") - header_file.write("#define MAX_BYTES_PER_ETW_PROVIDER " + str(nMaxEventBytesPerProvider) + "\n") - header_file.write("EXTERN_C __declspec(selectany) const BYTE etwStackSupportedEvents[NO_OF_ETW_PROVIDERS][MAX_BYTES_PER_ETW_PROVIDER] = \n{\n") - - for providerNode in tree.getElementsByTagName('provider'): - stackSupportedEvents = [0]*nMaxEventBytesPerProvider - eventNodes = providerNode.getElementsByTagName('event') - eventProvider = providerNode.getAttribute('name') - - for eventNode in eventNodes: - taskName = eventNode.getAttribute('task') - eventSymbol = eventNode.getAttribute('symbol') - eventTemplate = eventNode.getAttribute('template') - eventTemplate = eventNode.getAttribute('template') - eventValue = int(eventNode.getAttribute('value')) - eventIndex = eventValue // 8 - eventBitPositionInIndex = eventValue % 8 - - eventStackBitFromNoStackList = int(getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.nostack)) - eventStackBitFromExplicitStackList = int(getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.explicitstack)) - - # Shift those bits into position. For the explicit stack list, swap 0 and 1, so the eventValue* variables - # have 1 in the position iff we should issue a stack for the event. - eventValueUsingNoStackListByPosition = (eventStackBitFromNoStackList << eventBitPositionInIndex) - eventValueUsingExplicitStackListByPosition = ((1 - eventStackBitFromExplicitStackList) << eventBitPositionInIndex) - - # Commit the values to the in-memory array that we'll dump into the header file - stackSupportedEvents[eventIndex] = stackSupportedEvents[eventIndex] | eventValueUsingNoStackListByPosition; - if eventStackBitFromExplicitStackList == 0: - stackSupportedEvents[eventIndex] = stackSupportedEvents[eventIndex] | eventValueUsingExplicitStackListByPosition - - # print the bit array - line = [] - line.append("\t{") - for elem in stackSupportedEvents: - line.append(str(elem)) - line.append(", ") - - del line[-1] - line.append("},") - header_file.write(''.join(line) + "\n") - header_file.write("};\n") - -def genFiles(manifest, intermediate, exclusion_filename): - if not os.path.exists(intermediate): - os.makedirs(intermediate) - - genProviderInterface(manifest, intermediate) - genEtwMacroHeader(manifest, exclusion_filename, intermediate) - genXplatHeader(intermediate) - - -def main(argv): - #parse the command line - parser = argparse.ArgumentParser(description="Generates the Code required to instrument ETW logging mechanism") - - 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') - args, unknown = parser.parse_known_args(argv) - if unknown: - print('Unknown argument(s): ', ', '.join(unknown)) - return 1 - - manifest = args.man - exclusion_filename = args.exc - intermediate = args.intermediate - - checkConsistency(manifest, exclusion_filename) - genFiles(manifest, intermediate, exclusion_filename) - -if __name__ == '__main__': - return_code = main(sys.argv[1:]) - sys.exit(return_code)
\ No newline at end of file |