summaryrefslogtreecommitdiff
path: root/src/scripts
diff options
context:
space:
mode:
authorVictor "Nate" Graf <nategraf1@gmail.com>2017-12-20 18:07:52 -0800
committerGitHub <noreply@github.com>2017-12-20 18:07:52 -0800
commit7524d72d4f0f634fe5407280b83c25181dc8c556 (patch)
tree119c7edbbd7b3a0aec47d55334d52d1471e3a3da /src/scripts
parent9891c8ba8f84ff646455b4493447295c591665f4 (diff)
downloadcoreclr-7524d72d4f0f634fe5407280b83c25181dc8c556.tar.gz
coreclr-7524d72d4f0f634fe5407280b83c25181dc8c556.tar.bz2
coreclr-7524d72d4f0f634fe5407280b83c25181dc8c556.zip
Enable EventPipe across Unix and Windows (#14772)
* [squashed] most work complete to enable EventPipe on Windows * Eventpipe now builds on Windows * Ensure evevntpipe is intialized on Windows * Resolve the location of python from build.cmd * Ensure eventing files are generated when needed * moving linkage declaration to cmake * create new event from constructor * enable FEATURE_EVENT_TRACE and FEATURE_PERF_TRACE everywhere * [WIP] checkpoint in fixing contarct errors * add another possible python location * Fix double delete bug in EventPipeConfiguration destructor * Fix typo in function name * Revert changes to .gitgnore * bump to netstandard1.6 in preperation for new version of TraceEvent * Revert changes to groovy files * revert changes to perf-prep scripts * add common.h and use nothrow * Fix issue which was causing double delete of configprovider * Add new test utilizing TraceEvent * Remove accidentally added local directory reference * Add comment to explain the addition of misc/tracepointprovider.cpp * Add back sys.exit(0) and refactor * Change conditional to be more direct * Better handle NULL config * Initialize m_deleteDefered * Eliminate obsolete field * Fix spelling error * Fix nits * Make smaple progiler timing functions easier to read * Move projects back to netstandard1.4 * Incomplete improvements to EventPipeTrace test * Add event integrity checks to test * Clean up some left over code * Add EventSource based test * Remove unused PAL tests on Windows * Fix Linux build breaks * Minor changes to CMake files * Remove //HACK for hack that was previously removed * Fix formatting and negate a #ifdef * Add conditional to ensure PERFTRACING is not enabled without EVENT_TRACE * Take lock on EventPipeProvider and EventPipeConfiguration destruction * Load winmm.dll at runtime * Change function name and compile conditions * Move typedef into #ifndef * Use the correct config in setup * Change lifecycle managment of EventPipeConfiguration's configuration provider * Enable EventPipe tests pri0 and disable broken tests * Replace python3 only error with python2 compatable one * Make common.csproj build pri0 * Change TraceEvent version to 2.0.2 to match published verison * Address cross build failure * Remove use of undefined variable * Add crossgen fix to .cmd * Use more specific types to avoid marshalling errors * Use Assert-style statements and remove one check * Fix cross arch build * Fix flipped branch * Bring build.cmd changes to build.sh * Fix cmake writing * Revert "Bring build.cmd changes to build.sh" This reverts commit 893c6492548d8bc9859ebba5b1b810aa630fac63. * remove stdlib.h * Fix out of order null check
Diffstat (limited to 'src/scripts')
-rw-r--r--src/scripts/Utilities.py49
-rw-r--r--src/scripts/check-definitions.py24
-rw-r--r--src/scripts/genDummyProvider.py211
-rw-r--r--src/scripts/genEtwProvider.py312
-rw-r--r--src/scripts/genEventPipe.py313
-rw-r--r--src/scripts/genEventing.py (renamed from src/scripts/genXplatEventing.py)387
-rw-r--r--src/scripts/genLttngProvider.py (renamed from src/scripts/genXplatLttng.py)228
-rw-r--r--src/scripts/genWinEtw.py125
-rw-r--r--src/scripts/utilities.py106
9 files changed, 1082 insertions, 673 deletions
diff --git a/src/scripts/Utilities.py b/src/scripts/Utilities.py
deleted file mode 100644
index c1ceec8e9f..0000000000
--- a/src/scripts/Utilities.py
+++ /dev/null
@@ -1,49 +0,0 @@
-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 59b309a3e6..4f1026d4ef 100644
--- a/src/scripts/check-definitions.py
+++ b/src/scripts/check-definitions.py
@@ -33,18 +33,17 @@ debug = 0
# For the native part, return the sorted definition array.
def loadDefinitionFile(filename):
result = []
+
try:
- f = open(filename, 'r')
- except:
+ 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
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
@@ -108,9 +107,10 @@ def getDiff(arrNative, arrManaged):
def printPotentiallyCritical(arrDefinitions, referencedFilename, arrIgnore):
- f = open(referencedFilename, 'r')
- content = f.read()
- f.close()
+ content = None
+ with open(referencedFilename, 'r') as f:
+ content = f.read()
+
for keyword in arrDefinitions:
skip = 0
diff --git a/src/scripts/genDummyProvider.py b/src/scripts/genDummyProvider.py
new file mode 100644
index 0000000000..0704554263
--- /dev/null
+++ b/src/scripts/genDummyProvider.py
@@ -0,0 +1,211 @@
+##
+## 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
new file mode 100644
index 0000000000..fc9d43800f
--- /dev/null
+++ b/src/scripts/genEtwProvider.py
@@ -0,0 +1,312 @@
+##
+## 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 8a970794c0..96755ea459 100644
--- a/src/scripts/genEventPipe.py
+++ b/src/scripts/genEventPipe.py
@@ -1,10 +1,11 @@
from __future__ import print_function
-from genXplatEventing import *
-from genXplatLttng import *
+from genEventing import *
+from genLttngProvider import *
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.
+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.
@@ -14,6 +15,7 @@ DO NOT MODIFY. AUTOGENERATED FILE.
This file is generated using the logic from <root>/src/scripts/genEventPipe.py
******************************************************************/
+
"""
stdprolog_cmake = """#
@@ -24,11 +26,54 @@ 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, exclusionListFile):
+ providerName, eventNodes, allTemplates, extern):
providerPrettyName = providerName.replace("Windows-", '')
providerPrettyName = providerPrettyName.replace("Microsoft-", '')
providerPrettyName = providerPrettyName.replace('-', '_')
@@ -47,54 +92,24 @@ def generateClrEventPipeWriteEventsImpl(
templateName = eventNode.getAttribute('template')
# generate EventPipeEventEnabled function
- eventEnabledImpl = """bool EventPipeEventEnabled%s()
+ eventEnabledImpl = generateMethodSignatureEnabled(eventName) + """
{
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
- 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")
+ fnptype.append(generateMethodSignatureWrite(eventName, template, extern))
+ fnptype.append("\n{\n")
checking = """ if (!EventPipeEventEnabled%s())
return ERROR_SUCCESS;
""" % (eventName)
@@ -115,8 +130,9 @@ def generateClrEventPipeWriteEventsImpl(
WriteEventImpl.append("\n return ERROR_SUCCESS;\n}\n\n")
# EventPipeProvider and EventPipeEvent initialization
+ if extern: WriteEventImpl.append('extern "C" ')
WriteEventImpl.append(
- "extern \"C\" void Init" +
+ "void Init" +
providerPrettyName +
"()\n{\n")
WriteEventImpl.append(
@@ -134,7 +150,6 @@ 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);
@@ -150,8 +165,8 @@ def generateWriteEventBody(template, providerName, eventName):
header = """
char stackBuffer[%s];
char *buffer = stackBuffer;
- unsigned int offset = 0;
- unsigned int size = %s;
+ size_t offset = 0;
+ size_t size = %s;
bool fixedBuffer = true;
bool success = true;
@@ -198,7 +213,7 @@ def generateWriteEventBody(template, providerName, eventName):
}\n\n"""
body = " EventPipe::WriteEvent(*EventPipeEvent" + \
- eventName + ", (BYTE *)buffer, offset);\n"
+ eventName + ", (BYTE *)buffer, (unsigned int)offset);\n"
footer = """
if (!fixedBuffer)
@@ -221,20 +236,23 @@ def generateEventKeywords(eventKeywords):
return mask
-def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory):
+def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory, extern):
tree = DOM.parse(etwmanifest)
- with open(eventpipe_directory + "CMakeLists.txt", 'w') as topCmake:
- topCmake.write(stdprolog_cmake + "\n")
- topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2)
+ 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("""
- project(eventpipe)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+include_directories(${CLR_DIR}/src/vm)
- set(CMAKE_INCLUDE_CURRENT_DIR ON)
- include_directories(${CLR_DIR}/src/vm)
-
- add_library(eventpipe
- STATIC\n""")
+""")
+ if extern: cmake_file.write("add_library")
+ else: cmake_file.write("add_library_clr")
+ cmake_file.write("""(eventpipe
+ STATIC\n""")
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
@@ -244,34 +262,41 @@ def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory):
providerName_File = providerName.replace('-', '')
providerName_File = providerName_File.lower()
- 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()
+ 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("""
+# Install the static eventpipe library
+install(TARGETS eventpipe DESTINATION lib)
+""")
-def generateEventPipeHelperFile(etwmanifest, eventpipe_directory):
- with open(eventpipe_directory + "eventpipehelpers.cpp", 'w') as helper:
- helper.write(stdprolog)
+def generateEventPipeHelperFile(etwmanifest, eventpipe_directory, extern):
+ with open_for_update(os.path.join(eventpipe_directory, "eventpipehelpers.cpp")) as helper:
+ helper.write(stdprolog_cpp)
helper.write("""
-#include "stdlib.h"
-
-bool ResizeBuffer(char *&buffer, unsigned int& size, unsigned int currLen, unsigned int newSize, bool &fixedBuffer)
+#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)
{
- newSize *= 1.5;
+ newSize = (size_t)(newSize * 1.5);
_ASSERTE(newSize > size); // check for overflow
if (newSize < 32)
newSize = 32;
- char *newBuffer = new char[newSize];
+ char *newBuffer = new (nothrow) char[newSize];
+
+ if (newBuffer == NULL)
+ return false;
memcpy(newBuffer, buffer, currLen);
@@ -285,7 +310,7 @@ bool ResizeBuffer(char *&buffer, unsigned int& size, unsigned int currLen, unsig
return true;
}
-bool WriteToBuffer(const BYTE *src, unsigned int len, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
+bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
if(!src) return true;
if (offset + len > size)
@@ -299,10 +324,10 @@ bool WriteToBuffer(const BYTE *src, unsigned int len, char *&buffer, unsigned in
return true;
}
-bool WriteToBuffer(PCWSTR str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
+bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
if(!str) return true;
- unsigned int byteCount = (PAL_wcslen(str) + 1) * sizeof(*str);
+ size_t byteCount = (wcslen(str) + 1) * sizeof(*str);
if (offset + byteCount > size)
{
@@ -315,10 +340,10 @@ bool WriteToBuffer(PCWSTR str, char *&buffer, unsigned int& offset, unsigned int
return true;
}
-bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
+bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
if(!str) return true;
- unsigned int len = strlen(str) + 1;
+ size_t len = strlen(str) + 1;
if (offset + len > size)
{
if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer))
@@ -339,12 +364,18 @@ bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigne
providerPrettyName = providerName.replace("Windows-", '')
providerPrettyName = providerPrettyName.replace("Microsoft-", '')
providerPrettyName = providerPrettyName.replace('-', '_')
+ if extern: helper.write(
+ 'extern "C" '
+ )
helper.write(
- "extern \"C\" void Init" +
+ "void Init" +
providerPrettyName +
"();\n\n")
- helper.write("extern \"C\" void InitProvidersAndEvents()\n{\n")
+ if extern: helper.write(
+ 'extern "C" '
+ )
+ helper.write("void InitProvidersAndEvents()\n{\n")
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
providerPrettyName = providerName.replace("Windows-", '')
@@ -355,11 +386,20 @@ bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigne
helper.close()
-
def generateEventPipeImplFiles(
- etwmanifest, eventpipe_directory, exclusionListFile):
+ etwmanifest, eventpipe_directory, extern):
tree = DOM.parse(etwmanifest)
- coreclrRoot = os.getcwd()
+
+ # 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")
+
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
@@ -368,74 +408,77 @@ def generateEventPipeImplFiles(
providerName_File = providerPrettyName.replace('-', '')
providerName_File = providerName_File.lower()
providerPrettyName = providerPrettyName.replace('-', '_')
- eventpipefile = eventpipe_directory + providerName_File + ".cpp"
- eventpipeImpl = open(eventpipefile, 'w')
- eventpipeImpl.write(stdprolog)
+ 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"
- 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\"
+#if defined(FEATURE_PAL)
+#define wcslen PAL_wcslen
+#endif
-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);
+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);
template <typename T>
-bool WriteToBuffer(const T &value, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
-{
+bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& 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;
-}
+}}
-""" % (coreclrRoot, coreclrRoot, coreclrRoot, coreclrRoot)
+""".format(root=src_dirname.replace('\\', '/'))
- 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,
- exclusionListFile) + "\n")
- eventpipeImpl.close()
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
+ eventpipeImpl.write(
+ generateClrEventPipeWriteEventsImpl(
+ providerName,
+ eventNodes,
+ allTemplates,
+ extern) + "\n")
def generateEventPipeFiles(
- etwmanifest, eventpipe_directory, exclusionListFile):
- eventpipe_directory = eventpipe_directory + "/"
+ etwmanifest, intermediate, extern):
+ eventpipe_directory = os.path.join(intermediate, eventpipe_dirname)
tree = DOM.parse(etwmanifest)
if not os.path.exists(eventpipe_directory):
os.makedirs(eventpipe_directory)
- # generate Cmake file
- generateEventPipeCmakeFile(etwmanifest, eventpipe_directory)
+ # generate CMake file
+ generateEventPipeCmakeFile(etwmanifest, intermediate, extern)
# generate helper file
- generateEventPipeHelperFile(etwmanifest, eventpipe_directory)
+ generateEventPipeHelperFile(etwmanifest, eventpipe_directory, extern)
# generate all keywords
for keywordNode in tree.getElementsByTagName('keyword'):
@@ -447,12 +490,12 @@ def generateEventPipeFiles(
generateEventPipeImplFiles(
etwmanifest,
eventpipe_directory,
- exclusionListFile)
+ extern
+ )
import argparse
import sys
-
def main(argv):
# parse the command line
@@ -464,19 +507,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('--exc', type=str, required=True,
- help='full path to exclusion list')
+ required.add_argument('--nonextern', action='store_true',
+ help='if specified, will generate files to be compiled into the CLR rather than extern' )
args, unknown = parser.parse_known_args(argv)
if unknown:
print('Unknown argument(s): ', ', '.join(unknown))
- return const.UnknownArguments
+ return 1
sClrEtwAllMan = args.man
intermediate = args.intermediate
- exclusionListFile = args.exc
+ extern = not args.nonextern
- generateEventPipeFiles(sClrEtwAllMan, intermediate, exclusionListFile)
+ generateEventPipeFiles(sClrEtwAllMan, intermediate, extern)
if __name__ == '__main__':
return_code = main(sys.argv[1:])
- sys.exit(return_code)
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genXplatEventing.py b/src/scripts/genEventing.py
index 4c9ce873b7..d6d6afbb90 100644
--- a/src/scripts/genXplatEventing.py
+++ b/src/scripts/genEventing.py
@@ -6,7 +6,7 @@
#
#USAGE:
#Add Events: modify <root>src/vm/ClrEtwAll.man
-#Look at the Code in <root>/src/scripts/genXplatLttng.py for using subroutines in this file
+#Look at the Code in <root>/src/scripts/genLttngProvider.py for using subroutines in this file
#
# Python 2 compatibility
@@ -14,6 +14,7 @@ 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.
@@ -23,7 +24,7 @@ stdprolog="""
/******************************************************************
DO NOT MODIFY. AUTOGENERATED FILE.
-This file is generated using the logic from <root>/src/scripts/genXplatEventing.py
+This file is generated using the logic from <root>/src/scripts/genEventing.py
******************************************************************/
"""
@@ -34,7 +35,7 @@ stdprolog_cmake="""
#******************************************************************
#DO NOT MODIFY. AUTOGENERATED FILE.
-#This file is generated using the logic from <root>/src/scripts/genXplatEventing.py
+#This file is generated using the logic from <root>/src/scripts/genEventing.py
#******************************************************************
"""
@@ -260,7 +261,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")]
@@ -305,8 +306,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))
@@ -321,7 +322,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(", ")
@@ -349,20 +350,23 @@ def generateClrallEvents(eventNodes,allTemplates):
return ''.join(clrallEvents)
-def generateClrXplatEvents(eventNodes, allTemplates):
+def generateClrXplatEvents(eventNodes, allTemplates, extern):
clrallEvents = []
for eventNode in eventNodes:
eventName = eventNode.getAttribute('symbol')
templateName = eventNode.getAttribute('template')
#generate EventEnabled
- clrallEvents.append("extern \"C\" BOOL EventXplatEnabled")
+ if extern: clrallEvents.append('extern "C" ')
+ clrallEvents.append("BOOL EventXplatEnabled")
clrallEvents.append(eventName)
clrallEvents.append("();\n")
+
#generate FireEtw functions
fnptype = []
fnptypeline = []
- fnptype.append("extern \"C\" ULONG FireEtXplat")
+ if extern: fnptype.append('extern "C" ')
+ fnptype.append("ULONG FireEtXplat")
fnptype.append(eventName)
fnptype.append("(\n")
@@ -377,7 +381,7 @@ def generateClrXplatEvents(eventNodes, allTemplates):
winCount = fnparam.count
countw = palDataTypeMapping[winCount]
-
+
if params in template.structs:
fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
@@ -398,7 +402,7 @@ def generateClrXplatEvents(eventNodes, allTemplates):
return ''.join(clrallEvents)
-def generateClrEventPipeWriteEvents(eventNodes, allTemplates):
+def generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern):
clrallEvents = []
for eventNode in eventNodes:
eventName = eventNode.getAttribute('symbol')
@@ -409,11 +413,13 @@ def generateClrEventPipeWriteEvents(eventNodes, allTemplates):
writeevent = []
fnptypeline = []
- eventenabled.append("extern \"C\" bool EventPipeEventEnabled")
+ if extern:eventenabled.append('extern "C" ')
+ eventenabled.append("BOOL EventPipeEventEnabled")
eventenabled.append(eventName)
eventenabled.append("();\n")
- writeevent.append("extern \"C\" ULONG EventPipeWriteEvent")
+ if extern: writeevent.append('extern "C" ')
+ writeevent.append("ULONG EventPipeWriteEvent")
writeevent.append(eventName)
writeevent.append("(\n")
@@ -554,63 +560,70 @@ 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:
- 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})
+ 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}
+ )
+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.
+#
- 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
- """)
+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
- Test_cpp.write(stdprolog)
- Test_cpp.write("""
+ with open_for_update(testDir + "/" + test_cpp) as Test_cpp:
+ Test_cpp.write(stdprolog)
+ Test_cpp.write("""
/*=====================================================================
**
** Source: clralltestevents.cpp
@@ -619,7 +632,9 @@ def generateSanityTest(sClrEtwAllMan,testDir):
**
**
**===================================================================*/
+#if FEATURE_PAL
#include <palsuite.h>
+#endif //FEATURE_PAL
#include <clrxplatevents.h>
typedef struct _Struct1 {
@@ -646,39 +661,42 @@ 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("""
-/* Shutdown the PAL.
- */
-
- if (Error != ERROR_SUCCESS)
- {
- Fail("One or more eventing Apis failed\\n ");
- return FAIL;
- }
- Trace("\\n All eventing APIs were fired succesfully \\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)
- PAL_Terminate();
- return PASS;
- }
+#if defined(FEATURE_PAL)
+
+/* Shutdown the PAL.
+*/
+
+ PAL_Terminate();
+#endif
+ return PASS;
+ }
""")
- Cmake_file.close()
- Test_cpp.close()
Testinfo.close()
def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy):
@@ -693,19 +711,17 @@ def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy):
if not os.path.exists(incDir):
os.makedirs(incDir)
- 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")
+ with open_for_update(clretwdummy) as Clretwdummy:
+ Clretwdummy.write(stdprolog + "\n")
- Clretwdummy.close()
+ 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")
-def generatePlformIndependentFiles(sClrEtwAllMan,incDir,etmDummyFile):
+def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern):
generateEtmDummyHeader(sClrEtwAllMan,etmDummyFile)
tree = DOM.parse(sClrEtwAllMan)
@@ -717,152 +733,43 @@ def generatePlformIndependentFiles(sClrEtwAllMan,incDir,etmDummyFile):
if not os.path.exists(incDir):
os.makedirs(incDir)
- clrallevents = incDir + "/clretwallmain.h"
- clrxplatevents = incDir + "/clrxplatevents.h"
- clreventpipewriteevents = incDir + "/clreventpipewriteevents.h"
-
- Clrallevents = open(clrallevents,'w')
- Clrxplatevents = open(clrxplatevents,'w')
- Clreventpipewriteevents = open(clreventpipewriteevents,'w')
+ # 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.write(stdprolog + "\n")
- Clrxplatevents.write(stdprolog + "\n")
- Clreventpipewriteevents.write(stdprolog + "\n")
+""")
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
- 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")
+ #vm header:
+ Clrallevents.write(generateClrallEvents(eventNodes, allTemplates) + "\n")
- #pal: create clrallevents.h
- Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates) + "\n")
- #eventpipe: create clreventpipewriteevents.h
- Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(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")
- Clrxplatevents.close()
- Clrallevents.close()
- Clreventpipewriteevents.close()
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
-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'):
+ #pal: create clrallevents.h
+ Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates, extern) + "\n")
- stackSupportSpecified = {}
- eventNodes = providerNode.getElementsByTagName('event')
- templateNodes = providerNode.getElementsByTagName('template')
- eventProvider = providerNode.getAttribute('name')
- allTemplates = parseTemplateNodes(templateNodes)
+ #eventpipe: create clreventpipewriteevents.h
+ Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern) + "\n")
- 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
@@ -874,28 +781,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 const.UnknownArguments
+ return 1
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)
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genXplatLttng.py b/src/scripts/genLttngProvider.py
index 9959895f5a..382cb74675 100644
--- a/src/scripts/genXplatLttng.py
+++ b/src/scripts/genLttngProvider.py
@@ -50,7 +50,8 @@
#
import os
-from genXplatEventing import *
+from genEventing import *
+from utilities import open_for_update
stdprolog="""
// Licensed to the .NET Foundation under one or more agreements.
@@ -60,7 +61,7 @@ stdprolog="""
/******************************************************************
DO NOT MODIFY. AUTOGENERATED FILE.
-This file is generated using the logic from <root>/src/scripts/genXplatLttng.py
+This file is generated using the logic from <root>/src/scripts/genLttngProvider.py
******************************************************************/
"""
@@ -70,7 +71,7 @@ stdprolog_cmake="""
#******************************************************************
#DO NOT MODIFY. AUTOGENERATED FILE.
-#This file is generated using the logic from <root>/src/scripts/genXplatLttng.py
+#This file is generated using the logic from <root>/src/scripts/genLttngProvider.py
#******************************************************************
"""
@@ -159,7 +160,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)"
@@ -209,7 +210,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
@@ -289,7 +290,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
@@ -298,7 +299,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(" = (PAL_wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n")
+ result.append(" = (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 )")
@@ -308,7 +309,7 @@ def generateMethodBody(template, providerName, eventName):
#emit tracepoints
fnSig = template.signature
-
+
if not shouldPackTemplate(template):
linefnbody = [" do_tracepoint(%s,\n %s" % (providerName, eventName)]
@@ -360,8 +361,8 @@ def generateMethodBody(template, providerName, eventName):
header = """
char stackBuffer[%s];
char *buffer = stackBuffer;
- int offset = 0;
- int size = %s;
+ size_t offset = 0;
+ size_t size = %s;
bool fixedBuffer = true;
bool success = true;
@@ -401,7 +402,7 @@ def generateMethodBody(template, providerName, eventName):
do_tracepoint(%s, %s, offset, buffer);\n""" % (providerName, eventName)
return header + code + tracepoint + footer
-
+
@@ -420,7 +421,7 @@ def generateLttngTpProvider(providerName, eventNodes, allTemplates):
fnptype.append(eventName)
fnptype.append("(\n")
-
+
if templateName:
template = allTemplates[templateName]
else:
@@ -489,7 +490,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
os.makedirs(eventprovider_directory + tracepointprovider_directory)
#Top level Cmake
- with open(eventprovider_directory + "CMakeLists.txt", 'w') as topCmake:
+ with open_for_update(eventprovider_directory + "CMakeLists.txt") as topCmake:
topCmake.write(stdprolog_cmake + "\n")
topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2)
@@ -514,7 +515,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)
@@ -525,7 +526,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
#TracepointProvider Cmake
- with open(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt", 'w') as tracepointprovider_Cmake:
+ with open_for_update(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt") as tracepointprovider_Cmake:
tracepointprovider_Cmake.write(stdprolog_cmake + "\n")
tracepointprovider_Cmake.write("""cmake_minimum_required(VERSION 2.8.12.2)
@@ -562,7 +563,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
install_clr(coreclrtraceptprovider)
""")
- with open(eventprovider_directory + lttng_directory + "/eventprovhelpers.cpp", 'w') as helper:
+ with open_for_update(eventprovider_directory + lttng_directory + "/eventprovhelpers.cpp") as helper:
helper.write("""
#include "palrt.h"
#include "pal.h"
@@ -572,72 +573,81 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
#include <new>
#include <memory.h>
-bool ResizeBuffer(char *&buffer, int& size, int currLen, int newSize, bool &fixedBuffer)
+#define wcslen PAL_wcslen
+
+bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer)
{
- newSize *= 1.5;
- _ASSERTE(newSize > size); // check for overflow
+ newSize = (size_t)(newSize * 1.5);
+ _ASSERTE(newSize > size); // check for overflow
if (newSize < 32)
newSize = 32;
- char *newBuffer = new char[newSize];
+ // We can't use coreclr includes here so we use std::nothrow
+ // rather than the coreclr version
+ char *newBuffer = new (std::nothrow) char[newSize];
- memcpy(newBuffer, buffer, currLen);
+ if (newBuffer == NULL)
+ return false;
- if (!fixedBuffer)
- delete[] buffer;
+ memcpy(newBuffer, buffer, currLen);
- buffer = newBuffer;
- size = newSize;
- fixedBuffer = false;
+ if (!fixedBuffer)
+ delete[] buffer;
- return true;
+ buffer = newBuffer;
+ size = newSize;
+ fixedBuffer = false;
+
+ return true;
}
-bool WriteToBuffer(const BYTE *src, int len, char *&buffer, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& 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, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
- 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;
+ 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;
}
-bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
- 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;
-}""")
+ 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;
+}
+
+""")
# Generate Lttng specific instrumentation
for providerNode in tree.getElementsByTagName('provider'):
@@ -650,24 +660,19 @@ bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool
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"
- 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")
+ templateNodes = providerNode.getElementsByTagName('template')
+ eventNodes = providerNode.getElementsByTagName('event')
+ allTemplates = parseTemplateNodes(templateNodes)
- lTTngTpImpl.write("#include \"./"+lttngevntheadershortname + "\"\n")
- lTTngHdr.write("""
+ with open_for_update(lttngevntheader) as lttnghdr_file:
+ lttnghdr_file.write(stdprolog + "\n")
+ lttnghdr_file.write("""
#include "palrt.h"
#include "pal.h"
@@ -675,20 +680,24 @@ bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool
""")
- lTTngHdr.write("#define TRACEPOINT_PROVIDER " + providerName + "\n")
- lTTngHdr.write("""
+ lttnghdr_file.write("#define TRACEPOINT_PROVIDER " + providerName + "\n")
+ lttnghdr_file.write("""
#undef TRACEPOINT_INCLUDE
""")
- lTTngHdr.write("#define TRACEPOINT_INCLUDE \"./" + lttngevntheadershortname + "\"\n\n")
+ 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("#if !defined(LTTNG_CORECLR_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n")
- lTTngHdr.write("#define LTTNG_CORECLR_H" + providerName + "\n")
+ lttnghdr_file.write("\n#include <lttng/tracepoint.h>\n\n")
- lTTngHdr.write("\n#include <lttng/tracepoint.h>\n\n")
+ lttnghdr_file.write(generateLttngHeader(providerName,allTemplates,eventNodes) + "\n")
- lTTngImpl.write("""
+ with open_for_update(lttngevntprov) as lttngimpl_file:
+ lttngimpl_file.write(stdprolog + "\n")
+ lttngimpl_file.write("""
#define TRACEPOINT_DEFINE
#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
@@ -700,48 +709,43 @@ bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool
#define PAL_realloc realloc
#include "pal/stackstring.hpp"
""")
- lTTngImpl.write("#include \"" + lttngevntheadershortname + "\"\n\n")
+ lttngimpl_file.write("#include \"" + lttngevntheadershortname + "\"\n\n")
- lTTngImpl.write("""#ifndef tracepoint_enabled
+ lttngimpl_file.write("""#ifndef tracepoint_enabled
#define tracepoint_enabled(provider, name) TRUE
#define do_tracepoint tracepoint
#endif
+#define wcslen PAL_wcslen
-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);
+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);
template <typename T>
-bool WriteToBuffer(const T &value, char *&buffer, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& 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")
- templateNodes = providerNode.getElementsByTagName('template')
- eventNodes = providerNode.getElementsByTagName('event')
-
- allTemplates = parseTemplateNodes(templateNodes)
- #generate the header
- lTTngHdr.write(generateLttngHeader(providerName,allTemplates,eventNodes) + "\n")
+ with open_for_update(lttngevntprovTp) as tpimpl_file:
+ tpimpl_file.write(stdprolog + "\n")
- #create the implementation of eventing functions : lttngeventprov*.cp
- lTTngImpl.write(generateLttngTpProvider(providerName,eventNodes,allTemplates) + "\n")
+ tpimpl_file.write("\n#define TRACEPOINT_CREATE_PROBES\n")
- lTTngHdr.close()
- lTTngImpl.close()
- lTTngTpImpl.close()
+ tpimpl_file.write("#include \"./"+lttngevntheadershortname + "\"\n")
import argparse
import sys
@@ -759,7 +763,7 @@ def main(argv):
args, unknown = parser.parse_known_args(argv)
if unknown:
print('Unknown argument(s): ', ', '.join(unknown))
- return const.UnknownArguments
+ return 1
sClrEtwAllMan = args.man
intermediate = args.intermediate
@@ -768,4 +772,4 @@ def main(argv):
if __name__ == '__main__':
return_code = main(sys.argv[1:])
- sys.exit(return_code)
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genWinEtw.py b/src/scripts/genWinEtw.py
deleted file mode 100644
index aa75f680cd..0000000000
--- a/src/scripts/genWinEtw.py
+++ /dev/null
@@ -1,125 +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.
-#
-
-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/utilities.py b/src/scripts/utilities.py
new file mode 100644
index 0000000000..6898bb7542
--- /dev/null
+++ b/src/scripts/utilities.py
@@ -0,0 +1,106 @@
+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)