diff options
author | Victor "Nate" Graf <nategraf1@gmail.com> | 2017-12-21 11:48:14 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-21 11:48:14 -0800 |
commit | 302005ca8ae14eade37ddf4ac6e900617c1c166a (patch) | |
tree | df32e188ca3c3c2bec14d61b477e54dd4b2fe0c8 /src/scripts | |
parent | 0e4662c8911e3cf80eaaa446f280d7694ac09733 (diff) | |
download | coreclr-302005ca8ae14eade37ddf4ac6e900617c1c166a.tar.gz coreclr-302005ca8ae14eade37ddf4ac6e900617c1c166a.tar.bz2 coreclr-302005ca8ae14eade37ddf4ac6e900617c1c166a.zip |
Revert "Enable EventPipe across Unix and Windows (#14772)" (#15609)
This reverts commit 7524d72d4f0f634fe5407280b83c25181dc8c556.
Diffstat (limited to 'src/scripts')
-rw-r--r-- | src/scripts/Utilities.py | 49 | ||||
-rw-r--r-- | src/scripts/check-definitions.py | 24 | ||||
-rw-r--r-- | src/scripts/genDummyProvider.py | 211 | ||||
-rw-r--r-- | src/scripts/genEtwProvider.py | 312 | ||||
-rw-r--r-- | src/scripts/genEventPipe.py | 313 | ||||
-rw-r--r-- | src/scripts/genWinEtw.py | 125 | ||||
-rw-r--r-- | src/scripts/genXplatEventing.py (renamed from src/scripts/genEventing.py) | 387 | ||||
-rw-r--r-- | src/scripts/genXplatLttng.py (renamed from src/scripts/genLttngProvider.py) | 228 | ||||
-rw-r--r-- | src/scripts/utilities.py | 106 |
9 files changed, 673 insertions, 1082 deletions
diff --git a/src/scripts/Utilities.py b/src/scripts/Utilities.py new file mode 100644 index 0000000000..c1ceec8e9f --- /dev/null +++ b/src/scripts/Utilities.py @@ -0,0 +1,49 @@ +from filecmp import dircmp +import shutil +import os + +def walk_recursively_and_update(dcmp): + #for different Files Copy from right to left + for name in dcmp.diff_files: + srcpath = dcmp.right + "/" + name + destpath = dcmp.left + "/" + name + print("Updating %s" % (destpath)) + if os.path.isfile(srcpath): + shutil.copyfile(srcpath, destpath) + else : + raise Exception("path: " + srcpath + "is neither a file or folder") + + #copy right only files + for name in dcmp.right_only: + srcpath = dcmp.right + "/" + name + destpath = dcmp.left + "/" + name + print("Updating %s" % (destpath)) + if os.path.isfile(srcpath): + shutil.copyfile(srcpath, destpath) + elif os.path.isdir(srcpath): + shutil.copytree(srcpath, destpath) + else : + raise Exception("path: " + srcpath + "is neither a file or folder") + + #delete left only files + for name in dcmp.left_only: + path = dcmp.left + "/" + name + print("Deleting %s" % (path)) + if os.path.isfile(path): + os.remove(path) + elif os.path.isdir(path): + shutil.rmtree(path) + else : + raise Exception("path: " + path + "is neither a file or folder") + + #call recursively + for sub_dcmp in dcmp.subdirs.values(): + walk_recursively_and_update(sub_dcmp) + +def UpdateDirectory(destpath,srcpath): + + print("Updating %s with %s" % (destpath,srcpath)) + if not os.path.exists(destpath): + os.makedirs(destpath) + dcmp = dircmp(destpath,srcpath) + walk_recursively_and_update(dcmp) diff --git a/src/scripts/check-definitions.py b/src/scripts/check-definitions.py index 4f1026d4ef..59b309a3e6 100644 --- a/src/scripts/check-definitions.py +++ b/src/scripts/check-definitions.py @@ -33,17 +33,18 @@ debug = 0 # For the native part, return the sorted definition array. def loadDefinitionFile(filename): result = [] - try: - with open(filename, 'r') as f: - for line in f: - line = line.strip() - if line: - result.append(line) - except IOError: - # If cmake was not used, this script won't work, and that's ok + f = open(filename, 'r') + except: sys.exit(0) + # if cmake was not used (because of skipnative or systems that do not use cmake), this script won't work. + + for line in f: + theLine = line.rstrip("\r\n").strip() + if (len(theLine) > 0): + result.append(theLine) + f.close() result = sorted(result) return result @@ -107,10 +108,9 @@ def getDiff(arrNative, arrManaged): def printPotentiallyCritical(arrDefinitions, referencedFilename, arrIgnore): - content = None - with open(referencedFilename, 'r') as f: - content = f.read() - + f = open(referencedFilename, 'r') + content = f.read() + f.close() for keyword in arrDefinitions: skip = 0 diff --git a/src/scripts/genDummyProvider.py b/src/scripts/genDummyProvider.py deleted file mode 100644 index 0704554263..0000000000 --- a/src/scripts/genDummyProvider.py +++ /dev/null @@ -1,211 +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 exists to create a dummy implementaion of the eventprovider -## interface from a manifest file -## -## The intended use if for platforms which support event pipe -## but do not have a an eventing platform to recieve report events - -import os -from genEventing import * -from utilities import open_for_update - -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/genDummyProvider.py - -******************************************************************/ -""" -stdprolog_cmake=""" -# -# -#****************************************************************** - -#DO NOT MODIFY. AUTOGENERATED FILE. -#This file is generated using the logic from <root>/src/scripts/genDummyProvider.py - -#****************************************************************** -""" - -def trimProvName(name): - name = name.replace("Windows-",'') - name = name.replace("Microsoft-",'') - name = name.replace('-','_') - return name - -def escapeProvFilename(name): - name = name.replace('_','') - name = name.lower() - return name - -def generateDummyProvider(providerName, eventNodes, allTemplates, extern): - impl = [] - for eventNode in eventNodes: - eventName = eventNode.getAttribute('symbol') - templateName = eventNode.getAttribute('template') - - #generate EventXplatEnabled - if extern: impl.append('extern "C" ') - impl.append("BOOL EventXplatEnabled%s(){ return FALSE; }\n\n" % (eventName,)) - - #generate FireEtw functions - fnptype = [] - linefnptype = [] - if extern: fnptype.append('extern "C" ') - fnptype.append("ULONG FireEtXplat") - fnptype.append(eventName) - fnptype.append("(\n") - - - if templateName: - template = allTemplates[templateName] - else: - template = None - - if template: - fnSig = template.signature - for paramName in fnSig.paramlist: - fnparam = fnSig.getParam(paramName) - wintypeName = fnparam.winType - typewName = palDataTypeMapping[wintypeName] - winCount = fnparam.count - countw = palDataTypeMapping[winCount] - - if paramName in template.structs: - linefnptype.append("%sint %s_ElementSize,\n" % (lindent, paramName)) - - linefnptype.append(lindent) - linefnptype.append(typewName) - if countw != " ": - linefnptype.append(countw) - - linefnptype.append(" ") - linefnptype.append(fnparam.name) - linefnptype.append(",\n") - - if len(linefnptype) > 0 : - del linefnptype[-1] - - fnptype.extend(linefnptype) - fnptype.append(")\n{\n") - impl.extend(fnptype) - - #start of fn body - impl.append(" return ERROR_SUCCESS;\n") - impl.append("}\n\n") - - return ''.join(impl) - -def generateDummyFiles(etwmanifest, out_dirname, extern): - tree = DOM.parse(etwmanifest) - - #keep these relative - dummy_directory = "dummy" - dummyevntprovPre = os.path.join(dummy_directory, "eventprov") - - if not os.path.exists(out_dirname): - os.makedirs(out_dirname) - - if not os.path.exists(os.path.join(out_dirname, dummy_directory)): - os.makedirs(os.path.join(out_dirname, dummy_directory)) - - # Cmake - with open_for_update(os.path.join(out_dirname, "CMakeLists.txt")) as cmake: - cmake.write(stdprolog_cmake + "\n") - cmake.write("\ncmake_minimum_required(VERSION 2.8.12.2)\n") - if extern: cmake.write("\nproject(eventprovider)\n") - cmake.write(""" - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -if(FEATURE_PAL) - add_definitions(-DPAL_STDCPP_COMPAT=1) - include_directories(${COREPAL_SOURCE_DIR}/inc/rt) -endif(FEATURE_PAL) -include_directories(dummy) - -""") - if extern: cmake.write("add_library") - else: cmake.write("add_library_clr") - cmake.write("""(eventprovider - STATIC\n""") - - for providerNode in tree.getElementsByTagName('provider'): - providerName = trimProvName(providerNode.getAttribute('name')) - providerName_File = escapeProvFilename(providerName) - - cmake.write(' "%s%s.cpp"\n' % (dummyevntprovPre, providerName_File)) - - cmake.write(")") - if extern: cmake.write(""" - -# Install the static eventprovider library -install(TARGETS eventprovider DESTINATION lib) -""") - - # Dummy Instrumentation - for providerNode in tree.getElementsByTagName('provider'): - providerName = trimProvName(providerNode.getAttribute('name')) - providerName_File = escapeProvFilename(providerName) - - dummyevntprov = os.path.join(out_dirname, dummyevntprovPre + providerName_File + ".cpp") - - with open_for_update(dummyevntprov) as impl: - impl.write(stdprolog_cpp + "\n") - - impl.write(""" -#ifdef PLATFORM_UNIX -#include "pal_mstypes.h" -#include "pal_error.h" -#include "pal.h" -#define PAL_free free -#define PAL_realloc realloc -#include "pal/stackstring.hpp" -#endif - - -""") - - templateNodes = providerNode.getElementsByTagName('template') - eventNodes = providerNode.getElementsByTagName('event') - - allTemplates = parseTemplateNodes(templateNodes) - - #create the implementation of eventing functions : dummyeventprov*.cp - impl.write(generateDummyProvider(providerName, eventNodes, allTemplates, extern) + "\n") - -def main(argv): - - #parse the command line - parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng 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('--intermediate', type=str, required=True, - help='full path to eventprovider intermediate directory') - required.add_argument('--nonextern', action='store_true', - help='if specified, will generate files to be compiled into the CLR rather than externaly' ) - args, unknown = parser.parse_known_args(argv) - if unknown: - print('Unknown argument(s): ', ', '.join(unknown)) - return 1 - - sClrEtwAllMan = args.man - intermediate = args.intermediate - extern = not args.nonextern - - generateDummyFiles(sClrEtwAllMan, intermediate, extern) - -if __name__ == '__main__': - return_code = main(sys.argv[1:]) - sys.exit(return_code)
\ No newline at end of file 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 diff --git a/src/scripts/genEventPipe.py b/src/scripts/genEventPipe.py index 96755ea459..8a970794c0 100644 --- a/src/scripts/genEventPipe.py +++ b/src/scripts/genEventPipe.py @@ -1,11 +1,10 @@ from __future__ import print_function -from genEventing import * -from genLttngProvider import * +from genXplatEventing import * +from genXplatLttng import * import os import xml.dom.minidom as DOM -from utilities import open_for_update -stdprolog_cpp = """// Licensed to the .NET Foundation under one or more agreements. +stdprolog = """// 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. @@ -15,7 +14,6 @@ DO NOT MODIFY. AUTOGENERATED FILE. This file is generated using the logic from <root>/src/scripts/genEventPipe.py ******************************************************************/ - """ stdprolog_cmake = """# @@ -26,54 +24,11 @@ stdprolog_cmake = """# #This file is generated using the logic from <root>/src/scripts/genEventPipe.py #****************************************************************** - """ -eventpipe_dirname = "eventpipe" - -def generateMethodSignatureEnabled(eventName): - return "BOOL EventPipeEventEnabled%s()" % (eventName,) - -def generateMethodSignatureWrite(eventName, template, extern): - sig_pieces = [] - - if extern: sig_pieces.append('extern "C" ') - sig_pieces.append("ULONG EventPipeWriteEvent") - sig_pieces.append(eventName) - sig_pieces.append("(") - - if template: - sig_pieces.append("\n") - fnSig = template.signature - for paramName in fnSig.paramlist: - fnparam = fnSig.getParam(paramName) - wintypeName = fnparam.winType - typewName = palDataTypeMapping[wintypeName] - winCount = fnparam.count - countw = palDataTypeMapping[winCount] - - if paramName in template.structs: - sig_pieces.append( - "%sint %s_ElementSize,\n" % - (lindent, paramName)) - - sig_pieces.append(lindent) - sig_pieces.append(typewName) - if countw != " ": - sig_pieces.append(countw) - - sig_pieces.append(" ") - sig_pieces.append(fnparam.name) - sig_pieces.append(",\n") - - if len(sig_pieces) > 0: - del sig_pieces[-1] - - sig_pieces.append(")") - return ''.join(sig_pieces) def generateClrEventPipeWriteEventsImpl( - providerName, eventNodes, allTemplates, extern): + providerName, eventNodes, allTemplates, exclusionListFile): providerPrettyName = providerName.replace("Windows-", '') providerPrettyName = providerPrettyName.replace("Microsoft-", '') providerPrettyName = providerPrettyName.replace('-', '_') @@ -92,24 +47,54 @@ def generateClrEventPipeWriteEventsImpl( templateName = eventNode.getAttribute('template') # generate EventPipeEventEnabled function - eventEnabledImpl = generateMethodSignatureEnabled(eventName) + """ + eventEnabledImpl = """bool EventPipeEventEnabled%s() { return EventPipeEvent%s->IsEnabled(); } -""" % eventName +""" % (eventName, eventName) WriteEventImpl.append(eventEnabledImpl) # generate EventPipeWriteEvent function fnptype = [] + linefnptype = [] + fnptype.append("extern \"C\" ULONG EventPipeWriteEvent") + fnptype.append(eventName) + fnptype.append("(\n") if templateName: template = allTemplates[templateName] else: template = None - fnptype.append(generateMethodSignatureWrite(eventName, template, extern)) - fnptype.append("\n{\n") + if template: + fnSig = template.signature + for paramName in fnSig.paramlist: + fnparam = fnSig.getParam(paramName) + wintypeName = fnparam.winType + typewName = palDataTypeMapping[wintypeName] + winCount = fnparam.count + countw = palDataTypeMapping[winCount] + + if paramName in template.structs: + linefnptype.append( + "%sint %s_ElementSize,\n" % + (lindent, paramName)) + + linefnptype.append(lindent) + linefnptype.append(typewName) + if countw != " ": + linefnptype.append(countw) + + linefnptype.append(" ") + linefnptype.append(fnparam.name) + linefnptype.append(",\n") + + if len(linefnptype) > 0: + del linefnptype[-1] + + fnptype.extend(linefnptype) + fnptype.append(")\n{\n") checking = """ if (!EventPipeEventEnabled%s()) return ERROR_SUCCESS; """ % (eventName) @@ -130,9 +115,8 @@ def generateClrEventPipeWriteEventsImpl( WriteEventImpl.append("\n return ERROR_SUCCESS;\n}\n\n") # EventPipeProvider and EventPipeEvent initialization - if extern: WriteEventImpl.append('extern "C" ') WriteEventImpl.append( - "void Init" + + "extern \"C\" void Init" + providerPrettyName + "()\n{\n") WriteEventImpl.append( @@ -150,6 +134,7 @@ def generateClrEventPipeWriteEventsImpl( eventVersion = eventNode.getAttribute('version') eventLevel = eventNode.getAttribute('level') eventLevel = eventLevel.replace("win:", "EventPipeEventLevel::") + exclusionInfo = parseExclusionList(exclusionListFile) taskName = eventNode.getAttribute('task') initEvent = """ EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s); @@ -165,8 +150,8 @@ def generateWriteEventBody(template, providerName, eventName): header = """ char stackBuffer[%s]; char *buffer = stackBuffer; - size_t offset = 0; - size_t size = %s; + unsigned int offset = 0; + unsigned int size = %s; bool fixedBuffer = true; bool success = true; @@ -213,7 +198,7 @@ def generateWriteEventBody(template, providerName, eventName): }\n\n""" body = " EventPipe::WriteEvent(*EventPipeEvent" + \ - eventName + ", (BYTE *)buffer, (unsigned int)offset);\n" + eventName + ", (BYTE *)buffer, offset);\n" footer = """ if (!fixedBuffer) @@ -236,23 +221,20 @@ def generateEventKeywords(eventKeywords): return mask -def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory, extern): +def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory): tree = DOM.parse(etwmanifest) - with open_for_update(os.path.join(eventpipe_directory, "CMakeLists.txt")) as cmake_file: - cmake_file.write(stdprolog_cmake) - cmake_file.write("cmake_minimum_required(VERSION 2.8.12.2)\n") - if extern: cmake_file.write("\nproject(eventpipe)\n") - cmake_file.write(""" + with open(eventpipe_directory + "CMakeLists.txt", 'w') as topCmake: + topCmake.write(stdprolog_cmake + "\n") + topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2) -set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories(${CLR_DIR}/src/vm) + project(eventpipe) -""") - if extern: cmake_file.write("add_library") - else: cmake_file.write("add_library_clr") - cmake_file.write("""(eventpipe - STATIC\n""") + set(CMAKE_INCLUDE_CURRENT_DIR ON) + include_directories(${CLR_DIR}/src/vm) + + add_library(eventpipe + STATIC\n""") for providerNode in tree.getElementsByTagName('provider'): providerName = providerNode.getAttribute('name') @@ -262,41 +244,34 @@ include_directories(${CLR_DIR}/src/vm) providerName_File = providerName.replace('-', '') providerName_File = providerName_File.lower() - cmake_file.write(' "%s/%s.cpp"\n' % (eventpipe_dirname, providerName_File)) - cmake_file.write(' "%s/eventpipehelpers.cpp"\n)' % (eventpipe_dirname,)) - if extern: cmake_file.write(""" + topCmake.write(' "%s.cpp"\n' % (providerName_File)) + topCmake.write(' "eventpipehelpers.cpp"\n') + topCmake.write(""" ) + + add_dependencies(eventpipe GeneratedEventingFiles) + + # Install the static eventpipe library + install(TARGETS eventpipe DESTINATION lib) + """) + + topCmake.close() -# Install the static eventpipe library -install(TARGETS eventpipe DESTINATION lib) -""") -def generateEventPipeHelperFile(etwmanifest, eventpipe_directory, extern): - with open_for_update(os.path.join(eventpipe_directory, "eventpipehelpers.cpp")) as helper: - helper.write(stdprolog_cpp) +def generateEventPipeHelperFile(etwmanifest, eventpipe_directory): + with open(eventpipe_directory + "eventpipehelpers.cpp", 'w') as helper: + helper.write(stdprolog) helper.write(""" -#include "common.h" -#include <stdlib.h> -#include <string.h> - -#ifndef FEATURE_PAL -#include <windef.h> -#include <crtdbg.h> -#else -#include "pal.h" -#endif //FEATURE_PAL - -bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer) +#include "stdlib.h" + +bool ResizeBuffer(char *&buffer, unsigned int& size, unsigned int currLen, unsigned int newSize, bool &fixedBuffer) { - newSize = (size_t)(newSize * 1.5); + newSize *= 1.5; _ASSERTE(newSize > size); // check for overflow if (newSize < 32) newSize = 32; - char *newBuffer = new (nothrow) char[newSize]; - - if (newBuffer == NULL) - return false; + char *newBuffer = new char[newSize]; memcpy(newBuffer, buffer, currLen); @@ -310,7 +285,7 @@ bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, b return true; } -bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +bool WriteToBuffer(const BYTE *src, unsigned int len, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer) { if(!src) return true; if (offset + len > size) @@ -324,10 +299,10 @@ bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, s return true; } -bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +bool WriteToBuffer(PCWSTR str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer) { if(!str) return true; - size_t byteCount = (wcslen(str) + 1) * sizeof(*str); + unsigned int byteCount = (PAL_wcslen(str) + 1) * sizeof(*str); if (offset + byteCount > size) { @@ -340,10 +315,10 @@ bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool return true; } -bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer) { if(!str) return true; - size_t len = strlen(str) + 1; + unsigned int len = strlen(str) + 1; if (offset + len > size) { if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) @@ -364,18 +339,12 @@ bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, providerPrettyName = providerName.replace("Windows-", '') providerPrettyName = providerPrettyName.replace("Microsoft-", '') providerPrettyName = providerPrettyName.replace('-', '_') - if extern: helper.write( - 'extern "C" ' - ) helper.write( - "void Init" + + "extern \"C\" void Init" + providerPrettyName + "();\n\n") - if extern: helper.write( - 'extern "C" ' - ) - helper.write("void InitProvidersAndEvents()\n{\n") + helper.write("extern \"C\" void InitProvidersAndEvents()\n{\n") for providerNode in tree.getElementsByTagName('provider'): providerName = providerNode.getAttribute('name') providerPrettyName = providerName.replace("Windows-", '') @@ -386,20 +355,11 @@ bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, helper.close() + def generateEventPipeImplFiles( - etwmanifest, eventpipe_directory, extern): + etwmanifest, eventpipe_directory, exclusionListFile): tree = DOM.parse(etwmanifest) - - # Find the src directory starting with the assumption that - # A) It is named 'src' - # B) This script lives in it - src_dirname = os.path.dirname(__file__) - while os.path.basename(src_dirname) != "src": - src_dirname = os.path.dirname(src_dirname) - - if os.path.basename(src_dirname) == "": - raise IOError("Could not find the Core CLR 'src' directory") - + coreclrRoot = os.getcwd() for providerNode in tree.getElementsByTagName('provider'): providerName = providerNode.getAttribute('name') @@ -408,77 +368,74 @@ def generateEventPipeImplFiles( providerName_File = providerPrettyName.replace('-', '') providerName_File = providerName_File.lower() providerPrettyName = providerPrettyName.replace('-', '_') - eventpipefile = os.path.join(eventpipe_directory, providerName_File + ".cpp") - with open_for_update(eventpipefile) as eventpipeImpl: - eventpipeImpl.write(stdprolog_cpp) - - header = """ -#include "{root:s}/vm/common.h" -#include "{root:s}/vm/eventpipeprovider.h" -#include "{root:s}/vm/eventpipeevent.h" -#include "{root:s}/vm/eventpipe.h" + eventpipefile = eventpipe_directory + providerName_File + ".cpp" + eventpipeImpl = open(eventpipefile, 'w') + eventpipeImpl.write(stdprolog) -#if defined(FEATURE_PAL) -#define wcslen PAL_wcslen -#endif + header = """ +#include \"%s/src/vm/common.h\" +#include \"%s/src/vm/eventpipeprovider.h\" +#include \"%s/src/vm/eventpipeevent.h\" +#include \"%s/src/vm/eventpipe.h\" -bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer); -bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer); -bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer); -bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer); +bool ResizeBuffer(char *&buffer, unsigned int& size, unsigned int currLen, unsigned int newSize, bool &fixedBuffer); +bool WriteToBuffer(PCWSTR str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer); +bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer); +bool WriteToBuffer(const BYTE *src, unsigned int len, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer); template <typename T> -bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) -{{ +bool WriteToBuffer(const T &value, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer) +{ if (sizeof(T) + offset > size) - {{ - if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer)) - return false; - }} + { + if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer)) + return false; + } *(T *)(buffer + offset) = value; offset += sizeof(T); return true; -}} +} -""".format(root=src_dirname.replace('\\', '/')) +""" % (coreclrRoot, coreclrRoot, coreclrRoot, coreclrRoot) - eventpipeImpl.write(header) - eventpipeImpl.write( - "const WCHAR* %sName = W(\"%s\");\n" % ( - providerPrettyName, - providerName - ) + eventpipeImpl.write(header) + eventpipeImpl.write( + "const WCHAR* %sName = W(\"%s\");\n" % ( + providerPrettyName, + providerName ) - eventpipeImpl.write( - "EventPipeProvider *EventPipeProvider%s = nullptr;\n" % ( - providerPrettyName, - ) + ) + eventpipeImpl.write( + "EventPipeProvider *EventPipeProvider%s = nullptr;\n" % ( + providerPrettyName, ) - templateNodes = providerNode.getElementsByTagName('template') - allTemplates = parseTemplateNodes(templateNodes) - eventNodes = providerNode.getElementsByTagName('event') - eventpipeImpl.write( - generateClrEventPipeWriteEventsImpl( - providerName, - eventNodes, - allTemplates, - extern) + "\n") + ) + templateNodes = providerNode.getElementsByTagName('template') + allTemplates = parseTemplateNodes(templateNodes) + eventNodes = providerNode.getElementsByTagName('event') + eventpipeImpl.write( + generateClrEventPipeWriteEventsImpl( + providerName, + eventNodes, + allTemplates, + exclusionListFile) + "\n") + eventpipeImpl.close() def generateEventPipeFiles( - etwmanifest, intermediate, extern): - eventpipe_directory = os.path.join(intermediate, eventpipe_dirname) + etwmanifest, eventpipe_directory, exclusionListFile): + eventpipe_directory = eventpipe_directory + "/" tree = DOM.parse(etwmanifest) if not os.path.exists(eventpipe_directory): os.makedirs(eventpipe_directory) - # generate CMake file - generateEventPipeCmakeFile(etwmanifest, intermediate, extern) + # generate Cmake file + generateEventPipeCmakeFile(etwmanifest, eventpipe_directory) # generate helper file - generateEventPipeHelperFile(etwmanifest, eventpipe_directory, extern) + generateEventPipeHelperFile(etwmanifest, eventpipe_directory) # generate all keywords for keywordNode in tree.getElementsByTagName('keyword'): @@ -490,12 +447,12 @@ def generateEventPipeFiles( generateEventPipeImplFiles( etwmanifest, eventpipe_directory, - extern - ) + exclusionListFile) import argparse import sys + def main(argv): # parse the command line @@ -507,19 +464,19 @@ def main(argv): help='full path to manifest containig the description of events') required.add_argument('--intermediate', type=str, required=True, help='full path to eventprovider intermediate directory') - required.add_argument('--nonextern', action='store_true', - help='if specified, will generate files to be compiled into the CLR rather than extern' ) + required.add_argument('--exc', type=str, required=True, + help='full path to exclusion list') args, unknown = parser.parse_known_args(argv) if unknown: print('Unknown argument(s): ', ', '.join(unknown)) - return 1 + return const.UnknownArguments sClrEtwAllMan = args.man intermediate = args.intermediate - extern = not args.nonextern + exclusionListFile = args.exc - generateEventPipeFiles(sClrEtwAllMan, intermediate, extern) + generateEventPipeFiles(sClrEtwAllMan, intermediate, exclusionListFile) if __name__ == '__main__': return_code = main(sys.argv[1:]) - sys.exit(return_code)
\ No newline at end of file + sys.exit(return_code) diff --git a/src/scripts/genWinEtw.py b/src/scripts/genWinEtw.py new file mode 100644 index 0000000000..aa75f680cd --- /dev/null +++ b/src/scripts/genWinEtw.py @@ -0,0 +1,125 @@ + +## 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. +# + +import os +from genXplatEventing import * + +stdprolog=""" +// 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/genWinEtw.py + +******************************************************************/ + +""" +import argparse +import sys +import xml.dom.minidom as DOM + +def generateEtwMacroHeader(sClrEtwAllMan, sExcludeFile,macroHeader,inHeader): + tree = DOM.parse(sClrEtwAllMan) + numOfProviders = len(tree.getElementsByTagName('provider')) + nMaxEventBytesPerProvider = 64 + + exclusionInfo = parseExclusionList(sExcludeFile) + incDir = os.path.dirname(os.path.realpath(macroHeader)) + if not os.path.exists(incDir): + os.makedirs(incDir) + + outHeader = open(macroHeader,'w') + outHeader.write(stdprolog + "\n") + + outHeader.write("#include \"" + os.path.basename(inHeader) + '"\n') + outHeader.write("#define NO_OF_ETW_PROVIDERS " + str(numOfProviders) + "\n") + outHeader.write("#define MAX_BYTES_PER_ETW_PROVIDER " + str(nMaxEventBytesPerProvider) + "\n") + outHeader.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("},") + outHeader.write(''.join(line) + "\n") + outHeader.write("};\n") + + outHeader.close() + + +def generateEtwFiles(sClrEtwAllMan, exclusionListFile, etmdummyHeader, macroHeader, inHeader): + + checkConsistency(sClrEtwAllMan, exclusionListFile) + generateEtmDummyHeader(sClrEtwAllMan, etmdummyHeader) + generateEtwMacroHeader(sClrEtwAllMan, exclusionListFile, macroHeader, inHeader) + +def main(argv): + + #parse the command line + parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng 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('--eventheader', type=str, required=True, + help='full path to the header file') + required.add_argument('--macroheader', type=str, required=True, + help='full path to the macro header file') + required.add_argument('--dummy', type=str, required=True, + help='full path to file that will have dummy definitions of FireEtw functions') + + args, unknown = parser.parse_known_args(argv) + if unknown: + print('Unknown argument(s): ', ', '.join(unknown)) + return const.UnknownArguments + + sClrEtwAllMan = args.man + exclusionListFile = args.exc + inHeader = args.eventheader + macroHeader = args.macroheader + etmdummyHeader = args.dummy + + generateEtwFiles(sClrEtwAllMan, exclusionListFile, etmdummyHeader, macroHeader, inHeader) + +if __name__ == '__main__': + return_code = main(sys.argv[1:]) + sys.exit(return_code) diff --git a/src/scripts/genEventing.py b/src/scripts/genXplatEventing.py index d6d6afbb90..4c9ce873b7 100644 --- a/src/scripts/genEventing.py +++ b/src/scripts/genXplatEventing.py @@ -6,7 +6,7 @@ # #USAGE: #Add Events: modify <root>src/vm/ClrEtwAll.man -#Look at the Code in <root>/src/scripts/genLttngProvider.py for using subroutines in this file +#Look at the Code in <root>/src/scripts/genXplatLttng.py for using subroutines in this file # # Python 2 compatibility @@ -14,7 +14,6 @@ from __future__ import print_function import os import xml.dom.minidom as DOM -from utilities import open_for_update stdprolog=""" // Licensed to the .NET Foundation under one or more agreements. @@ -24,7 +23,7 @@ stdprolog=""" /****************************************************************** DO NOT MODIFY. AUTOGENERATED FILE. -This file is generated using the logic from <root>/src/scripts/genEventing.py +This file is generated using the logic from <root>/src/scripts/genXplatEventing.py ******************************************************************/ """ @@ -35,7 +34,7 @@ stdprolog_cmake=""" #****************************************************************** #DO NOT MODIFY. AUTOGENERATED FILE. -#This file is generated using the logic from <root>/src/scripts/genEventing.py +#This file is generated using the logic from <root>/src/scripts/genXplatEventing.py #****************************************************************** """ @@ -261,7 +260,7 @@ def parseTemplateNodes(templateNodes): assert(countVarName in fnPrototypes.paramlist) if not countVarName: raise ValueError("Struct '%s' in template '%s' does not have an attribute count." % (structName, templateName)) - + names = [x.attributes['name'].value for x in structToBeMarshalled.getElementsByTagName("data")] types = [x.attributes['inType'].value for x in structToBeMarshalled.getElementsByTagName("data")] @@ -306,8 +305,8 @@ def generateClrallEvents(eventNodes,allTemplates): typewName = palDataTypeMapping[wintypeName] winCount = fnparam.count countw = palDataTypeMapping[winCount] - - + + if params in template.structs: fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params)) @@ -322,7 +321,7 @@ def generateClrallEvents(eventNodes,allTemplates): for params in fnSig.paramlist: fnparam = fnSig.getParam(params) - if params in template.structs: + if params in template.structs: line.append(fnparam.name + "_ElementSize") line.append(", ") @@ -350,23 +349,20 @@ def generateClrallEvents(eventNodes,allTemplates): return ''.join(clrallEvents) -def generateClrXplatEvents(eventNodes, allTemplates, extern): +def generateClrXplatEvents(eventNodes, allTemplates): clrallEvents = [] for eventNode in eventNodes: eventName = eventNode.getAttribute('symbol') templateName = eventNode.getAttribute('template') #generate EventEnabled - if extern: clrallEvents.append('extern "C" ') - clrallEvents.append("BOOL EventXplatEnabled") + clrallEvents.append("extern \"C\" BOOL EventXplatEnabled") clrallEvents.append(eventName) clrallEvents.append("();\n") - #generate FireEtw functions fnptype = [] fnptypeline = [] - if extern: fnptype.append('extern "C" ') - fnptype.append("ULONG FireEtXplat") + fnptype.append("extern \"C\" ULONG FireEtXplat") fnptype.append(eventName) fnptype.append("(\n") @@ -381,7 +377,7 @@ def generateClrXplatEvents(eventNodes, allTemplates, extern): winCount = fnparam.count countw = palDataTypeMapping[winCount] - + if params in template.structs: fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params)) @@ -402,7 +398,7 @@ def generateClrXplatEvents(eventNodes, allTemplates, extern): return ''.join(clrallEvents) -def generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern): +def generateClrEventPipeWriteEvents(eventNodes, allTemplates): clrallEvents = [] for eventNode in eventNodes: eventName = eventNode.getAttribute('symbol') @@ -413,13 +409,11 @@ def generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern): writeevent = [] fnptypeline = [] - if extern:eventenabled.append('extern "C" ') - eventenabled.append("BOOL EventPipeEventEnabled") + eventenabled.append("extern \"C\" bool EventPipeEventEnabled") eventenabled.append(eventName) eventenabled.append("();\n") - if extern: writeevent.append('extern "C" ') - writeevent.append("ULONG EventPipeWriteEvent") + writeevent.append("extern \"C\" ULONG EventPipeWriteEvent") writeevent.append(eventName) writeevent.append("(\n") @@ -560,70 +554,63 @@ def generateSanityTest(sClrEtwAllMan,testDir): cmake_file = testDir + "/CMakeLists.txt" test_cpp = "clralltestevents.cpp" testinfo = testDir + "/testinfo.dat" + Cmake_file = open(cmake_file,'w') + Test_cpp = open(testDir + "/" + test_cpp,'w') + Testinfo = open(testinfo,'w') #CMake File: - with open_for_update(cmake_file) as Cmake_file: - Cmake_file.write(stdprolog_cmake) - Cmake_file.write(""" -cmake_minimum_required(VERSION 2.8.12.2) -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(SOURCES -""") - Cmake_file.write(test_cpp) - Cmake_file.write(""" - ) -include_directories(${GENERATED_INCLUDE_DIR}) - -if(FEATURE_PAL) - include_directories(${COREPAL_SOURCE_DIR}/inc/rt) -endif(FEATURE_PAL) - -add_executable(eventprovidertest - ${SOURCES} - ) -set(EVENT_PROVIDER_DEPENDENCIES "") -set(EVENT_PROVIDER_LINKER_OTPTIONS "") -if(FEATURE_EVENT_TRACE) - add_definitions(-DFEATURE_EVENT_TRACE=1) - list(APPEND EVENT_PROVIDER_DEPENDENCIES - eventprovider - ) - if(CLR_CMAKE_PLATFORM_LINUX) - list(APPEND EVENT_PROVIDER_DEPENDENCIES - coreclrtraceptprovider - ) - endif(CLR_CMAKE_PLATFORM_LINUX) - list(APPEND EVENT_PROVIDER_LINKER_OTPTIONS - ${EVENT_PROVIDER_DEPENDENCIES} + Cmake_file.write(stdprolog_cmake) + Cmake_file.write(""" + cmake_minimum_required(VERSION 2.8.12.2) + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(SOURCES + """) + Cmake_file.write(test_cpp) + Cmake_file.write(""" ) -endif(FEATURE_EVENT_TRACE) - -add_dependencies(eventprovidertest ${EVENT_PROVIDER_DEPENDENCIES} coreclrpal) -target_link_libraries(eventprovidertest - coreclrpal - ${EVENT_PROVIDER_LINKER_OTPTIONS} - ) -""") - - - with open_for_update(testinfo) as Testinfo: - Testinfo.write(""" -Copyright (c) Microsoft Corporation. All rights reserved. -# + include_directories(${GENERATED_INCLUDE_DIR}) + include_directories(${COREPAL_SOURCE_DIR}/inc/rt) -Version = 1.0 -Section = EventProvider -Function = EventProvider -Name = PAL test for FireEtW* and EventEnabled* functions -TYPE = DEFAULT -EXE1 = eventprovidertest -Description = This is a sanity test to check that there are no crashes in Xplat eventing -""") + add_executable(eventprovidertest + ${SOURCES} + ) + set(EVENT_PROVIDER_DEPENDENCIES "") + set(EVENT_PROVIDER_LINKER_OTPTIONS "") + if(FEATURE_EVENT_TRACE) + add_definitions(-DFEATURE_EVENT_TRACE=1) + list(APPEND EVENT_PROVIDER_DEPENDENCIES + coreclrtraceptprovider + eventprovider + ) + list(APPEND EVENT_PROVIDER_LINKER_OTPTIONS + ${EVENT_PROVIDER_DEPENDENCIES} + ) + + endif(FEATURE_EVENT_TRACE) + + add_dependencies(eventprovidertest ${EVENT_PROVIDER_DEPENDENCIES} coreclrpal) + target_link_libraries(eventprovidertest + coreclrpal + ${EVENT_PROVIDER_LINKER_OTPTIONS} + ) + """) + Testinfo.write(""" + Copyright (c) Microsoft Corporation. All rights reserved. + # + + Version = 1.0 + Section = EventProvider + Function = EventProvider + Name = PAL test for FireEtW* and EventEnabled* functions + TYPE = DEFAULT + EXE1 = eventprovidertest + Description + =This is a sanity test to check that there are no crashes in Xplat eventing + """) #Test.cpp - with open_for_update(testDir + "/" + test_cpp) as Test_cpp: - Test_cpp.write(stdprolog) - Test_cpp.write(""" + Test_cpp.write(stdprolog) + Test_cpp.write(""" /*===================================================================== ** ** Source: clralltestevents.cpp @@ -632,9 +619,7 @@ Description = This is a sanity test to check that there are no crashes in Xplat ** ** **===================================================================*/ -#if FEATURE_PAL #include <palsuite.h> -#endif //FEATURE_PAL #include <clrxplatevents.h> typedef struct _Struct1 { @@ -661,42 +646,39 @@ int win_Int32 = 12; BYTE* win_Binary =(BYTE*)var21 ; int __cdecl main(int argc, char **argv) { -#if defined(FEATURE_PAL) + /* Initialize the PAL. */ if(0 != PAL_Initialize(argc, argv)) { - return FAIL; + return FAIL; } -#endif ULONG Error = ERROR_SUCCESS; #if defined(FEATURE_EVENT_TRACE) Trace("\\n Starting functional eventing APIs tests \\n"); """) - Test_cpp.write(generateClralltestEvents(sClrEtwAllMan)) - Test_cpp.write(""" - - if (Error != ERROR_SUCCESS) - { - Fail("One or more eventing Apis failed\\n "); - return FAIL; - } - Trace("\\n All eventing APIs were fired succesfully \\n"); -#endif //defined(FEATURE_EVENT_TRACE) -#if defined(FEATURE_PAL) - + Test_cpp.write(generateClralltestEvents(sClrEtwAllMan)) + Test_cpp.write(""" /* Shutdown the PAL. -*/ - - PAL_Terminate(); -#endif - return PASS; - } + */ + + if (Error != ERROR_SUCCESS) + { + Fail("One or more eventing Apis failed\\n "); + return FAIL; + } + Trace("\\n All eventing APIs were fired succesfully \\n"); +#endif //defined(FEATURE_EVENT_TRACE) + PAL_Terminate(); + return PASS; + } """) + Cmake_file.close() + Test_cpp.close() Testinfo.close() def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy): @@ -711,17 +693,19 @@ def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy): if not os.path.exists(incDir): os.makedirs(incDir) - with open_for_update(clretwdummy) as Clretwdummy: - Clretwdummy.write(stdprolog + "\n") + Clretwdummy = open(clretwdummy,'w') + Clretwdummy.write(stdprolog + "\n") + + for providerNode in tree.getElementsByTagName('provider'): + templateNodes = providerNode.getElementsByTagName('template') + allTemplates = parseTemplateNodes(templateNodes) + eventNodes = providerNode.getElementsByTagName('event') + #pal: create etmdummy.h + Clretwdummy.write(generateclrEtwDummy(eventNodes, allTemplates) + "\n") - for providerNode in tree.getElementsByTagName('provider'): - templateNodes = providerNode.getElementsByTagName('template') - allTemplates = parseTemplateNodes(templateNodes) - eventNodes = providerNode.getElementsByTagName('event') - #pal: create etmdummy.h - Clretwdummy.write(generateclrEtwDummy(eventNodes, allTemplates) + "\n") + Clretwdummy.close() -def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern): +def generatePlformIndependentFiles(sClrEtwAllMan,incDir,etmDummyFile): generateEtmDummyHeader(sClrEtwAllMan,etmDummyFile) tree = DOM.parse(sClrEtwAllMan) @@ -733,43 +717,152 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern if not os.path.exists(incDir): os.makedirs(incDir) - # Write the main header for FireETW* functions - clrallevents = os.path.join(incDir, "clretwallmain.h") - with open_for_update(clrallevents) as Clrallevents: - Clrallevents.write(stdprolog) - Clrallevents.write(""" -#include "clrxplatevents.h" -#include "clreventpipewriteevents.h" + clrallevents = incDir + "/clretwallmain.h" + clrxplatevents = incDir + "/clrxplatevents.h" + clreventpipewriteevents = incDir + "/clreventpipewriteevents.h" -""") - for providerNode in tree.getElementsByTagName('provider'): - templateNodes = providerNode.getElementsByTagName('template') - allTemplates = parseTemplateNodes(templateNodes) - eventNodes = providerNode.getElementsByTagName('event') + Clrallevents = open(clrallevents,'w') + Clrxplatevents = open(clrxplatevents,'w') + Clreventpipewriteevents = open(clreventpipewriteevents,'w') - #vm header: - Clrallevents.write(generateClrallEvents(eventNodes, allTemplates) + "\n") + Clrallevents.write(stdprolog + "\n") + Clrxplatevents.write(stdprolog + "\n") + Clreventpipewriteevents.write(stdprolog + "\n") + Clrallevents.write("\n#include \"clrxplatevents.h\"\n") + Clrallevents.write("#include \"clreventpipewriteevents.h\"\n\n") + + for providerNode in tree.getElementsByTagName('provider'): + templateNodes = providerNode.getElementsByTagName('template') + allTemplates = parseTemplateNodes(templateNodes) + eventNodes = providerNode.getElementsByTagName('event') + #vm header: + Clrallevents.write(generateClrallEvents(eventNodes, allTemplates) + "\n") + + #pal: create clrallevents.h + Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates) + "\n") - # Write secondary headers for FireEtXplat* and EventPipe* functions - clrxplatevents = os.path.join(incDir, "clrxplatevents.h") - clreventpipewriteevents = os.path.join(incDir, "clreventpipewriteevents.h") - with open_for_update(clrxplatevents) as Clrxplatevents: - with open_for_update(clreventpipewriteevents) as Clreventpipewriteevents: - Clrxplatevents.write(stdprolog + "\n") - Clreventpipewriteevents.write(stdprolog + "\n") + #eventpipe: create clreventpipewriteevents.h + Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(eventNodes, allTemplates) + "\n") - for providerNode in tree.getElementsByTagName('provider'): - templateNodes = providerNode.getElementsByTagName('template') - allTemplates = parseTemplateNodes(templateNodes) - eventNodes = providerNode.getElementsByTagName('event') + Clrxplatevents.close() + Clrallevents.close() + Clreventpipewriteevents.close() - #pal: create clrallevents.h - Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates, extern) + "\n") +class EventExclusions: + def __init__(self): + self.nostack = set() + self.explicitstack = set() + self.noclrinstance = set() + +def parseExclusionList(exclusionListFile): + ExclusionFile = open(exclusionListFile,'r') + 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 "+ exclusionListFile) + + 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) + ExclusionFile.close() + + 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(sClrEtwAllMan,exclusionListFile): + tree = DOM.parse(sClrEtwAllMan) + exclusionInfo = parseExclusionList(exclusionListFile) + for providerNode in tree.getElementsByTagName('provider'): - #eventpipe: create clreventpipewriteevents.h - Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern) + "\n") + 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(exclusionListFile + ":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 = exclusionListFile + ": 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) import argparse import sys @@ -781,28 +874,28 @@ 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('--inc', type=str, default=None, help='full path to directory where the header files will be generated') required.add_argument('--dummy', type=str,default=None, help='full path to file that will have dummy definitions of FireEtw functions') required.add_argument('--testdir', type=str, default=None, help='full path to directory where the test assets will be deployed' ) - required.add_argument('--nonextern', action='store_true', - help='if specified, will not generated extern function stub headers' ) args, unknown = parser.parse_known_args(argv) if unknown: print('Unknown argument(s): ', ', '.join(unknown)) - return 1 + return const.UnknownArguments sClrEtwAllMan = args.man + exclusionListFile = args.exc incdir = args.inc etmDummyFile = args.dummy testDir = args.testdir - extern = not args.nonextern - - generatePlatformIndependentFiles(sClrEtwAllMan, incdir, etmDummyFile, extern) - generateSanityTest(sClrEtwAllMan, testDir) + checkConsistency(sClrEtwAllMan, exclusionListFile) + generatePlformIndependentFiles(sClrEtwAllMan,incdir,etmDummyFile) + generateSanityTest(sClrEtwAllMan,testDir) if __name__ == '__main__': return_code = main(sys.argv[1:]) - sys.exit(return_code)
\ No newline at end of file + sys.exit(return_code) diff --git a/src/scripts/genLttngProvider.py b/src/scripts/genXplatLttng.py index 382cb74675..9959895f5a 100644 --- a/src/scripts/genLttngProvider.py +++ b/src/scripts/genXplatLttng.py @@ -50,8 +50,7 @@ # import os -from genEventing import * -from utilities import open_for_update +from genXplatEventing import * stdprolog=""" // Licensed to the .NET Foundation under one or more agreements. @@ -61,7 +60,7 @@ stdprolog=""" /****************************************************************** DO NOT MODIFY. AUTOGENERATED FILE. -This file is generated using the logic from <root>/src/scripts/genLttngProvider.py +This file is generated using the logic from <root>/src/scripts/genXplatLttng.py ******************************************************************/ """ @@ -71,7 +70,7 @@ stdprolog_cmake=""" #****************************************************************** #DO NOT MODIFY. AUTOGENERATED FILE. -#This file is generated using the logic from <root>/src/scripts/genLttngProvider.py +#This file is generated using the logic from <root>/src/scripts/genXplatLttng.py #****************************************************************** """ @@ -160,7 +159,7 @@ def generateArgList(template): def generateFieldList(template): header = " " + " TP_FIELDS(\n" footer = "\n )\n)\n" - + if shouldPackTemplate(template): field_list = " ctf_integer(ULONG, length, length)\n" field_list += " ctf_sequence(char, __data__, __data__, ULONG, length)" @@ -210,7 +209,7 @@ def generateLttngHeader(providerName, allTemplates, eventNodes): for templateName in allTemplates: template = allTemplates[templateName] fnSig = allTemplates[templateName].signature - + lTTngHdr.append("\n#define " + templateName + "_TRACEPOINT_ARGS \\\n") #TP_ARGS @@ -290,7 +289,7 @@ def generateMethodBody(template, providerName, eventName): return "\n do_tracepoint(%s, %s);\n" % (providerName, eventName) fnSig = template.signature - + for paramName in fnSig.paramlist: fnparam = fnSig.getParam(paramName) paramname = fnparam.name @@ -299,7 +298,7 @@ def generateMethodBody(template, providerName, eventName): result.append(" INT " + paramname + "_path_size = -1;\n") result.append(" PathCharString " + paramname + "_PS;\n") result.append(" INT " + paramname + "_full_name_path_size") - result.append(" = (wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n") + result.append(" = (PAL_wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n") result.append(" CHAR* " + paramname + "_full_name = ") result.append(paramname + "_PS.OpenStringBuffer(" + paramname + "_full_name_path_size );\n") result.append(" if (" + paramname + "_full_name == NULL )") @@ -309,7 +308,7 @@ def generateMethodBody(template, providerName, eventName): #emit tracepoints fnSig = template.signature - + if not shouldPackTemplate(template): linefnbody = [" do_tracepoint(%s,\n %s" % (providerName, eventName)] @@ -361,8 +360,8 @@ def generateMethodBody(template, providerName, eventName): header = """ char stackBuffer[%s]; char *buffer = stackBuffer; - size_t offset = 0; - size_t size = %s; + int offset = 0; + int size = %s; bool fixedBuffer = true; bool success = true; @@ -402,7 +401,7 @@ def generateMethodBody(template, providerName, eventName): do_tracepoint(%s, %s, offset, buffer);\n""" % (providerName, eventName) return header + code + tracepoint + footer - + @@ -421,7 +420,7 @@ def generateLttngTpProvider(providerName, eventNodes, allTemplates): fnptype.append(eventName) fnptype.append("(\n") - + if templateName: template = allTemplates[templateName] else: @@ -490,7 +489,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory): os.makedirs(eventprovider_directory + tracepointprovider_directory) #Top level Cmake - with open_for_update(eventprovider_directory + "CMakeLists.txt") as topCmake: + with open(eventprovider_directory + "CMakeLists.txt", 'w') as topCmake: topCmake.write(stdprolog_cmake + "\n") topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2) @@ -515,7 +514,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory): providerName_File = providerName_File.lower() topCmake.write(' "%s%s.cpp"\n' % (lttngevntprovPre, providerName_File)) - + topCmake.write(' "%shelpers.cpp"\n' % (lttngevntprovPre,)) topCmake.write(""") add_subdirectory(tracepointprovider) @@ -526,7 +525,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory): #TracepointProvider Cmake - with open_for_update(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt") as tracepointprovider_Cmake: + with open(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt", 'w') as tracepointprovider_Cmake: tracepointprovider_Cmake.write(stdprolog_cmake + "\n") tracepointprovider_Cmake.write("""cmake_minimum_required(VERSION 2.8.12.2) @@ -563,7 +562,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory): install_clr(coreclrtraceptprovider) """) - with open_for_update(eventprovider_directory + lttng_directory + "/eventprovhelpers.cpp") as helper: + with open(eventprovider_directory + lttng_directory + "/eventprovhelpers.cpp", 'w') as helper: helper.write(""" #include "palrt.h" #include "pal.h" @@ -573,81 +572,72 @@ def generateLttngFiles(etwmanifest,eventprovider_directory): #include <new> #include <memory.h> -#define wcslen PAL_wcslen - -bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer) +bool ResizeBuffer(char *&buffer, int& size, int currLen, int newSize, bool &fixedBuffer) { - newSize = (size_t)(newSize * 1.5); - _ASSERTE(newSize > size); // check for overflow + newSize *= 1.5; + _ASSERTE(newSize > size); // check for overflow if (newSize < 32) newSize = 32; - // We can't use coreclr includes here so we use std::nothrow - // rather than the coreclr version - char *newBuffer = new (std::nothrow) char[newSize]; + char *newBuffer = new char[newSize]; - if (newBuffer == NULL) - return false; + memcpy(newBuffer, buffer, currLen); - memcpy(newBuffer, buffer, currLen); + if (!fixedBuffer) + delete[] buffer; - if (!fixedBuffer) - delete[] buffer; + buffer = newBuffer; + size = newSize; + fixedBuffer = false; - buffer = newBuffer; - size = newSize; - fixedBuffer = false; - - return true; + return true; } -bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +bool WriteToBuffer(const BYTE *src, int len, char *&buffer, int& offset, int& size, bool &fixedBuffer) { - if(!src) return true; - if (offset + len > size) - { - if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) - return false; - } - - memcpy(buffer + offset, src, len); - offset += len; - return true; + if (!src) return true; + if (offset + len > size) + { + if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, src, len); + offset += len; + return true; } -bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +bool WriteToBuffer(PCWSTR str, char *&buffer, int& offset, int& size, bool &fixedBuffer) { - if(!str) return true; - size_t byteCount = (wcslen(str) + 1) * sizeof(*str); - - if (offset + byteCount > size) - { - if (!ResizeBuffer(buffer, size, offset, size + byteCount, fixedBuffer)) - return false; - } - - memcpy(buffer + offset, str, byteCount); - offset += byteCount; - return true; + if (!str) return true; + int byteCount = (PAL_wcslen(str) + 1) * sizeof(*str); + + if (offset + byteCount > size) + { + if (!ResizeBuffer(buffer, size, offset, size + byteCount, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, str, byteCount); + offset += byteCount; + return true; } -bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool &fixedBuffer) { - if(!str) return true; - size_t len = strlen(str) + 1; - if (offset + len > size) - { - if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) - return false; - } - - memcpy(buffer + offset, str, len); - offset += len; - return true; -} - -""") + if (!str) return true; + int len = strlen(str) + 1; + if (offset + len > size) + { + if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, str, len); + offset += len; + return true; +}""") # Generate Lttng specific instrumentation for providerNode in tree.getElementsByTagName('provider'): @@ -660,19 +650,24 @@ bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, providerName_File = providerName_File.lower() providerName = providerName.replace('-','_') - lttngevntheadershortname = "tp" + providerName_File +".h" + lttngevntheadershortname = "tp" + providerName_File +".h"; lttngevntheader = eventprovider_directory + "lttng/" + lttngevntheadershortname lttngevntprov = eventprovider_directory + lttngevntprovPre + providerName_File + ".cpp" lttngevntprovTp = eventprovider_directory + lttngevntprovTpPre + providerName_File +".cpp" - templateNodes = providerNode.getElementsByTagName('template') - eventNodes = providerNode.getElementsByTagName('event') - allTemplates = parseTemplateNodes(templateNodes) + lTTngHdr = open(lttngevntheader, 'w') + lTTngImpl = open(lttngevntprov, 'w') + lTTngTpImpl = open(lttngevntprovTp, 'w') + + lTTngHdr.write(stdprolog + "\n") + lTTngImpl.write(stdprolog + "\n") + lTTngTpImpl.write(stdprolog + "\n") + lTTngTpImpl.write("\n#define TRACEPOINT_CREATE_PROBES\n") - with open_for_update(lttngevntheader) as lttnghdr_file: - lttnghdr_file.write(stdprolog + "\n") - lttnghdr_file.write(""" + lTTngTpImpl.write("#include \"./"+lttngevntheadershortname + "\"\n") + + lTTngHdr.write(""" #include "palrt.h" #include "pal.h" @@ -680,24 +675,20 @@ bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, """) - lttnghdr_file.write("#define TRACEPOINT_PROVIDER " + providerName + "\n") - lttnghdr_file.write(""" + lTTngHdr.write("#define TRACEPOINT_PROVIDER " + providerName + "\n") + lTTngHdr.write(""" #undef TRACEPOINT_INCLUDE """) - lttnghdr_file.write("#define TRACEPOINT_INCLUDE \"./" + lttngevntheadershortname + "\"\n\n") - - lttnghdr_file.write("#if !defined(LTTNG_CORECLR_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n") - lttnghdr_file.write("#define LTTNG_CORECLR_H" + providerName + "\n") + lTTngHdr.write("#define TRACEPOINT_INCLUDE \"./" + lttngevntheadershortname + "\"\n\n") - lttnghdr_file.write("\n#include <lttng/tracepoint.h>\n\n") + lTTngHdr.write("#if !defined(LTTNG_CORECLR_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n") + lTTngHdr.write("#define LTTNG_CORECLR_H" + providerName + "\n") - lttnghdr_file.write(generateLttngHeader(providerName,allTemplates,eventNodes) + "\n") + lTTngHdr.write("\n#include <lttng/tracepoint.h>\n\n") - with open_for_update(lttngevntprov) as lttngimpl_file: - lttngimpl_file.write(stdprolog + "\n") - lttngimpl_file.write(""" + lTTngImpl.write(""" #define TRACEPOINT_DEFINE #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE @@ -709,43 +700,48 @@ bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, #define PAL_realloc realloc #include "pal/stackstring.hpp" """) - lttngimpl_file.write("#include \"" + lttngevntheadershortname + "\"\n\n") + lTTngImpl.write("#include \"" + lttngevntheadershortname + "\"\n\n") - lttngimpl_file.write("""#ifndef tracepoint_enabled + lTTngImpl.write("""#ifndef tracepoint_enabled #define tracepoint_enabled(provider, name) TRUE #define do_tracepoint tracepoint #endif -#define wcslen PAL_wcslen -bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer); -bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer); -bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer); -bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer); +bool ResizeBuffer(char *&buffer, int& size, int currLen, int newSize, bool &fixedBuffer); +bool WriteToBuffer(PCWSTR str, char *&buffer, int& offset, int& size, bool &fixedBuffer); +bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool &fixedBuffer); +bool WriteToBuffer(const BYTE *src, int len, char *&buffer, int& offset, int& size, bool &fixedBuffer); template <typename T> -bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +bool WriteToBuffer(const T &value, char *&buffer, int& offset, int& size, bool &fixedBuffer) { - if (sizeof(T) + offset > size) - { - if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer)) - return false; - } - - *(T *)(buffer + offset) = value; - offset += sizeof(T); - return true; + if (sizeof(T) + offset > size) + { + if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer)) + return false; + } + + *(T *)(buffer + offset) = value; + offset += sizeof(T); + return true; } """) - lttngimpl_file.write(generateLttngTpProvider(providerName,eventNodes,allTemplates) + "\n") - with open_for_update(lttngevntprovTp) as tpimpl_file: - tpimpl_file.write(stdprolog + "\n") + templateNodes = providerNode.getElementsByTagName('template') + eventNodes = providerNode.getElementsByTagName('event') + + allTemplates = parseTemplateNodes(templateNodes) + #generate the header + lTTngHdr.write(generateLttngHeader(providerName,allTemplates,eventNodes) + "\n") - tpimpl_file.write("\n#define TRACEPOINT_CREATE_PROBES\n") + #create the implementation of eventing functions : lttngeventprov*.cp + lTTngImpl.write(generateLttngTpProvider(providerName,eventNodes,allTemplates) + "\n") - tpimpl_file.write("#include \"./"+lttngevntheadershortname + "\"\n") + lTTngHdr.close() + lTTngImpl.close() + lTTngTpImpl.close() import argparse import sys @@ -763,7 +759,7 @@ def main(argv): args, unknown = parser.parse_known_args(argv) if unknown: print('Unknown argument(s): ', ', '.join(unknown)) - return 1 + return const.UnknownArguments sClrEtwAllMan = args.man intermediate = args.intermediate @@ -772,4 +768,4 @@ def main(argv): if __name__ == '__main__': return_code = main(sys.argv[1:]) - sys.exit(return_code)
\ No newline at end of file + sys.exit(return_code) diff --git a/src/scripts/utilities.py b/src/scripts/utilities.py deleted file mode 100644 index 6898bb7542..0000000000 --- a/src/scripts/utilities.py +++ /dev/null @@ -1,106 +0,0 @@ -from filecmp import dircmp -from hashlib import sha256 -from io import StringIO -import shutil -import os - -class WrappedStringIO(StringIO): - """A wrapper around StringIO to allow writing str objects""" - def write(self, s): - if isinstance(s, str): - s = unicode(s) - super(WrappedStringIO, self).write(s) - -class UpdateFileWriter: - """A file-like context object which will only write to a file if the result would be different - - Attributes: - filename (str): The name of the file to update - stream (WrappedStringIO): The file-like stream provided upon context enter - - Args: - filename (str): Sets the filename attribute - """ - filemode = 'w' - - def __init__(self, filename): - self.filename = filename - self.stream = None - - def __enter__(self): - self.stream = WrappedStringIO() - return self.stream - - def __exit__(self, exc_type, exc_value, traceback): - if exc_value is None: - new_content = self.stream.getvalue() - new_hash = sha256() - cur_hash = sha256() - - try: - with open(self.filename, 'r') as fstream: - cur_hash.update(fstream.read()) - file_found = True - except IOError: - file_found = False - - if file_found: - new_hash.update(new_content) - update = new_hash.digest() != cur_hash.digest() - else: - update = True - - if update: - with open(self.filename, 'w') as fstream: - fstream.write(new_content) - - self.stream.close() - -def open_for_update(filename): - return UpdateFileWriter(filename) - -def walk_recursively_and_update(dcmp): - #for different Files Copy from right to left - for name in dcmp.diff_files: - srcpath = dcmp.right + "/" + name - destpath = dcmp.left + "/" + name - print("Updating %s" % (destpath)) - if os.path.isfile(srcpath): - shutil.copyfile(srcpath, destpath) - else : - raise Exception("path: " + srcpath + "is neither a file or folder") - - #copy right only files - for name in dcmp.right_only: - srcpath = dcmp.right + "/" + name - destpath = dcmp.left + "/" + name - print("Updating %s" % (destpath)) - if os.path.isfile(srcpath): - shutil.copyfile(srcpath, destpath) - elif os.path.isdir(srcpath): - shutil.copytree(srcpath, destpath) - else : - raise Exception("path: " + srcpath + "is neither a file or folder") - - #delete left only files - for name in dcmp.left_only: - path = dcmp.left + "/" + name - print("Deleting %s" % (path)) - if os.path.isfile(path): - os.remove(path) - elif os.path.isdir(path): - shutil.rmtree(path) - else : - raise Exception("path: " + path + "is neither a file or folder") - - #call recursively - for sub_dcmp in dcmp.subdirs.values(): - walk_recursively_and_update(sub_dcmp) - -def UpdateDirectory(destpath,srcpath): - - print("Updating %s with %s" % (destpath,srcpath)) - if not os.path.exists(destpath): - os.makedirs(destpath) - dcmp = dircmp(destpath,srcpath) - walk_recursively_and_update(dcmp) |