summaryrefslogtreecommitdiff
path: root/src/scripts
diff options
context:
space:
mode:
authorRama <ramarag@microsoft.com>2015-12-21 19:26:52 -0800
committerRama <ramarag@microsoft.com>2015-12-28 15:41:59 -0800
commitf1f40524c17035247666ca7f04e9dd41c5d1c172 (patch)
tree098d7521298cc8302e82e3958f867a0b62906397 /src/scripts
parent4be02beac6b35dc675956c55ed0ab7b947fd5c4f (diff)
downloadcoreclr-f1f40524c17035247666ca7f04e9dd41c5d1c172.tar.gz
coreclr-f1f40524c17035247666ca7f04e9dd41c5d1c172.tar.bz2
coreclr-f1f40524c17035247666ca7f04e9dd41c5d1c172.zip
Automating Event Logging Infrastructure: With this change the infrastructure required for Event Logging
will be generated as part of build
Diffstat (limited to 'src/scripts')
-rw-r--r--src/scripts/genWinEtw.py127
-rw-r--r--src/scripts/genXplatEventing.py807
-rw-r--r--src/scripts/genXplatLttng.py600
3 files changed, 1534 insertions, 0 deletions
diff --git a/src/scripts/genWinEtw.py b/src/scripts/genWinEtw.py
new file mode 100644
index 0000000000..52bcbd4763
--- /dev/null
+++ b/src/scripts/genWinEtw.py
@@ -0,0 +1,127 @@
+
+##
+## Copyright (c) Microsoft. All rights reserved.
+## Licensed under the MIT license. See LICENSE file in the project root for full license information.
+##
+#
+
+import os
+from genXplatEventing import *
+
+stdprolog="""
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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')
+ print >>outHeader, stdprolog
+
+ print >>outHeader, "#include \"" + os.path.basename(inHeader) + '"'
+ print >>outHeader, "#define NO_OF_ETW_PROVIDERS " + str(numOfProviders)
+ print >>outHeader, "#define MAX_BYTES_PER_ETW_PROVIDER " + str(nMaxEventBytesPerProvider)
+ print >>outHeader, "EXTERN_C __declspec(selectany) const BYTE etwStackSupportedEvents[NO_OF_ETW_PROVIDERS][MAX_BYTES_PER_ETW_PROVIDER] = \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("},")
+ print >>outHeader,''.join(line)
+ print >>outHeader, "};"
+
+ 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/genXplatEventing.py b/src/scripts/genXplatEventing.py
new file mode 100644
index 0000000000..0f4033e18f
--- /dev/null
+++ b/src/scripts/genXplatEventing.py
@@ -0,0 +1,807 @@
+##
+## Copyright (c) Microsoft. All rights reserved.
+## Licensed under the MIT license. See LICENSE file in the project root for full license information.
+##
+#
+#USAGE:
+#Add Events: modify <root>src/vm/ClrEtwAll.man
+#Look at the Code in <root>/src/inc/genXplatLttng.py for using subroutines in this file
+#
+
+import os
+import xml.dom.minidom as DOM
+from sets import Set
+
+stdprolog="""
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+/******************************************************************
+
+DO NOT MODIFY. AUTOGENERATED FILE.
+This file is generated using the logic from <root>/src/scripts/genXplatEventing.py
+
+******************************************************************/
+"""
+
+stdprolog_cmake="""
+#
+#
+#******************************************************************
+
+#DO NOT MODIFY. AUTOGENERATED FILE.
+#This file is generated using the logic from <root>/src/scripts/genXplatEventing.py
+
+#******************************************************************
+"""
+
+lindent = " ";
+palDataTypeMapping ={
+ #constructed types
+ "win:null" :" ",
+ "win:Int64" :"const __int64",
+ "win:ULong" :"const ULONG",
+ "win:count" :"*",
+ "win:Struct" :"const void",
+ #actual spec
+ "win:GUID" :"const GUID",
+ "win:AnsiString" :"LPCSTR",
+ "win:UnicodeString" :"PCWSTR",
+ "win:Double" :"const double",
+ "win:Int32" :"const signed int",
+ "win:Boolean" :"const BOOL",
+ "win:UInt64" :"const unsigned __int64",
+ "win:UInt32" :"const unsigned int",
+ "win:UInt16" :"const unsigned short",
+ "win:UInt8" :"const unsigned char",
+ "win:Pointer" :"const void*",
+ "win:Binary" :"const BYTE"
+ }
+# A Template represents an ETW template can contain 1 or more AbstractTemplates
+# The AbstractTemplate contains FunctionSignature
+# FunctionSignature consist of FunctionParameter representing each parameter in it's signature
+
+class AbstractTemplate:
+ def __init__(self,abstractTemplateName,abstractFnFrame):
+ self.abstractTemplateName = abstractTemplateName
+ self.AbstractFnFrame = abstractFnFrame
+
+
+class Template:
+
+ def __init__(self,templateName):
+ self.template = templateName
+ self.allAbstractTemplateTypes = [] # list of AbstractTemplateNames
+ self.allAbstractTemplateLUT = {} #dictionary of AbstractTemplate
+
+ def append(self,abstractTemplateName,abstractFnFrame):
+ self.allAbstractTemplateTypes.append(abstractTemplateName)
+ self.allAbstractTemplateLUT[abstractTemplateName] = AbstractTemplate(abstractTemplateName,abstractFnFrame)
+
+ def getFnFrame(self,abstractTemplateName):
+ return self.allAbstractTemplateLUT[abstractTemplateName].AbstractFnFrame
+
+ def getAbstractVarProps(self,abstractTemplateName):
+ return self.allAbstractTemplateLUT[abstractTemplateName].AbstractVarProps
+
+ def getFnParam(self,name):
+ for subtemplate in self.allAbstractTemplateTypes:
+ frame = self.getFnFrame(subtemplate)
+ if frame.getParam(name):
+ return frame.getParam(name)
+ return None
+
+class FunctionSignature:
+
+ def __init__(self):
+ self.LUT = {} # dictionary of FunctionParameter
+ self.paramlist = [] # list of parameters to maintain their order in signature
+
+ def append(self,variable,fnparam):
+ self.LUT[variable] = fnparam
+ self.paramlist.append(variable)
+
+ def getParam(self,variable):
+ return self.LUT.get(variable)
+
+ def getLength(self):
+ return len(self.paramlist)
+
+class FunctionParameter:
+
+ def __init__(self,winType,name,count,prop):
+ self.winType = winType #ETW type as given in the manifest
+ self.name = name #parameter name as given in the manifest
+ self.prop = prop #any special property as determined by the manifest and developer
+ #self.count #indicates if the parameter is a pointer
+ if count == "win:null":
+ self.count = "win:null"
+ elif count or winType == "win:GUID" or count == "win:count":
+ #special case for GUIDS, consider them as structs
+ self.count = "win:count"
+ else:
+ self.count = "win:null"
+
+
+def getTopLevelElementsByTagName(Node,tag):
+
+ dataNodes = []
+ for element in Node.getElementsByTagName(tag):
+ if element.parentNode == Node:
+ dataNodes.append(element)
+
+ return dataNodes
+
+def bucketizeAbstractTemplates(template,fnPrototypes,var_Dependecies):
+ # At this point we have the complete argument list, now break them into chunks of 10
+ # As Abstract Template supports a maximum of 10 arguments
+ abstractTemplateName = template;
+ subevent_cnt = 1;
+ templateProp = Template(template)
+ abstractFnFrame = FunctionSignature()
+
+ for variable in fnPrototypes.paramlist:
+ for dependency in var_Dependecies[variable]:
+ if not abstractFnFrame.getParam(dependency):
+ abstractFnFrame.append(dependency,fnPrototypes.getParam(dependency))
+
+ frameCount = abstractFnFrame.getLength()
+ if frameCount == 10:
+
+ templateProp.append(abstractTemplateName,abstractFnFrame)
+ abstractTemplateName = template + "_" + str(subevent_cnt)
+ subevent_cnt += 1
+
+ if len(var_Dependecies[variable]) > 1:
+ #check if the frame's dependencies are all present
+ depExists = True
+ for depends in var_Dependecies[variable]:
+ if not abstractFnFrame.getParam(depends):
+ depExists = False
+ break
+ if not depExists:
+ raise ValueError('Abstract Template: '+ abstractTemplateName+ ' does not have all its dependecies in the frame, write required Logic here and test it out, the parameter whose dependency is missing is :'+ variable)
+ #psuedo code:
+ # 1. add a missing dependecies to the frame of the current parameter
+ # 2. Check if the frame has enough space, if there is continue adding missing dependencies
+ # 3. Else Save the current Frame and start a new frame and follow step 1 and 2
+ # 4. Add the current parameter and proceed
+
+ #create a new fn frame
+ abstractFnFrame = FunctionSignature()
+
+
+ #subevent_cnt == 1 represents argumentless templates
+ if abstractFnFrame.getLength() > 0 or subevent_cnt == 1:
+ templateProp.append(abstractTemplateName,abstractFnFrame)
+
+ return templateProp
+
+ignoredXmlTemplateAttribes = Set(["map","outType"])
+usedXmlTemplateAttribes = Set(["name","inType","count", "length"])
+
+def parseTemplateNodes(templateNodes):
+
+ #return values
+ allTemplates = {}
+
+ for templateNode in templateNodes:
+
+ template = templateNode.getAttribute('tid')
+ var_Dependecies = {}
+ fnPrototypes = FunctionSignature()
+ dataNodes = getTopLevelElementsByTagName(templateNode,'data')
+
+ # Validate that no new attributes has been added to manifest
+ for dataNode in dataNodes:
+ nodeMap = dataNode.attributes
+ for attrib in nodeMap.values():
+ attrib_name = attrib.name
+ if attrib_name not in ignoredXmlTemplateAttribes and attrib_name not in usedXmlTemplateAttribes:
+ raise ValueError('unknown attribute: '+ attrib_name + ' in template:'+ template)
+
+ for dataNode in dataNodes:
+ variable = dataNode.getAttribute('name')
+ wintype = dataNode.getAttribute('inType')
+
+ #count and length are the same
+ wincount = dataNode.getAttribute('count')
+ winlength = dataNode.getAttribute('length');
+
+ var_Props = None
+ var_dependency = [variable]
+ if winlength:
+ if wincount:
+ raise Exception("both count and length property found on: " + variable + "in template: " + template)
+ wincount = winlength
+
+ if (wincount.isdigit() and int(wincount) ==1):
+ wincount = ''
+
+ if wincount:
+ if (wincount.isdigit()):
+ var_Props = wincount
+ elif fnPrototypes.getParam(wincount):
+ var_Props = wincount
+ var_dependency.insert(0,wincount)
+
+ #construct the function signature
+
+
+ if wintype == "win:GUID":
+ var_Props = "sizeof(GUID)/sizeof(int)"
+
+ var_Dependecies[variable] = var_dependency
+ fnparam = FunctionParameter(wintype,variable,wincount,var_Props)
+ fnPrototypes.append(variable,fnparam)
+
+ structNodes = getTopLevelElementsByTagName(templateNode,'struct')
+
+ count = 0;
+ for structToBeMarshalled in structNodes:
+ struct_len = "Arg"+ str(count) + "_Struct_Len_"
+ struct_pointer = "Arg"+ str(count) + "_Struct_Pointer_"
+ count += 1
+
+ #populate the Property- used in codegen
+ structname = structToBeMarshalled.getAttribute('name')
+ countVarName = structToBeMarshalled.getAttribute('count')
+
+ if not countVarName:
+ raise ValueError('Struct '+ structname+ ' in template:'+ template + 'does not have an attribute count')
+
+ var_Props = countVarName + "*" + struct_len + "/sizeof(int)"
+ var_Dependecies[struct_len] = [struct_len]
+ var_Dependecies[struct_pointer] = [countVarName,struct_len,struct_pointer]
+
+ fnparam_len = FunctionParameter("win:ULong",struct_len,"win:null",None)
+ fnparam_pointer = FunctionParameter("win:Struct",struct_pointer,"win:count",var_Props)
+
+ fnPrototypes.append(struct_len,fnparam_len)
+ fnPrototypes.append(struct_pointer,fnparam_pointer)
+
+ allTemplates[template] = bucketizeAbstractTemplates(template,fnPrototypes,var_Dependecies)
+
+ return allTemplates
+
+def generateClrallEvents(eventNodes,allTemplates):
+ clrallEvents = []
+ for eventNode in eventNodes:
+ eventName = eventNode.getAttribute('symbol')
+ templateName = eventNode.getAttribute('template')
+
+ #generate EventEnabled
+ clrallEvents.append("inline BOOL EventEnabled")
+ clrallEvents.append(eventName)
+ clrallEvents.append("() {return XplatEventLogger::IsEventLoggingEnabled() && EventXplatEnabled")
+ clrallEvents.append(eventName+"();}\n\n")
+ #generate FireEtw functions
+ fnptype = []
+ fnbody = []
+ fnptype.append("inline ULONG FireEtw")
+ fnptype.append(eventName)
+ fnptype.append("(\n")
+ fnbody.append(lindent)
+ fnbody.append("if (!EventEnabled")
+ fnbody.append(eventName)
+ fnbody.append("()) {return ERROR_SUCCESS;}\n")
+ line = []
+ fnptypeline = []
+
+ if templateName:
+ for subTemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subTemplate)
+
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ wintypeName = fnparam.winType
+ typewName = palDataTypeMapping[wintypeName]
+ winCount = fnparam.count
+ countw = palDataTypeMapping[winCount]
+ fnptypeline.append(lindent)
+ fnptypeline.append(typewName)
+ fnptypeline.append(countw)
+ fnptypeline.append(" ")
+ fnptypeline.append(fnparam.name)
+ fnptypeline.append(",\n")
+
+ #fnsignature
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ line.append(fnparam.name)
+ line.append(",")
+
+ #remove trailing commas
+ if len(line) > 0:
+ del line[-1]
+ if len(fnptypeline) > 0:
+ del fnptypeline[-1]
+
+ fnptype.extend(fnptypeline)
+ fnptype.append("\n)\n{\n")
+ fnbody.append(lindent)
+ fnbody.append("return FireEtXplat")
+ fnbody.append(eventName)
+ fnbody.append("(")
+ fnbody.extend(line)
+ fnbody.append(");\n")
+ fnbody.append("}\n\n")
+
+ clrallEvents.extend(fnptype)
+ clrallEvents.extend(fnbody)
+
+ return ''.join(clrallEvents)
+
+def generateClrXplatEvents(eventNodes, allTemplates):
+ clrallEvents = []
+ for eventNode in eventNodes:
+ eventName = eventNode.getAttribute('symbol')
+ templateName = eventNode.getAttribute('template')
+
+ #generate EventEnabled
+ clrallEvents.append("extern \"C\" BOOL EventXplatEnabled")
+ clrallEvents.append(eventName)
+ clrallEvents.append("();\n")
+ #generate FireEtw functions
+ fnptype = []
+ fnptypeline = []
+ fnptype.append("extern \"C\" ULONG FireEtXplat")
+ fnptype.append(eventName)
+ fnptype.append("(\n")
+
+ if templateName:
+ for subTemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subTemplate)
+
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ wintypeName = fnparam.winType
+ typewName = palDataTypeMapping[wintypeName]
+ winCount = fnparam.count
+ countw = palDataTypeMapping[winCount]
+ fnptypeline.append(lindent)
+ fnptypeline.append(typewName)
+ fnptypeline.append(countw)
+ fnptypeline.append(" ")
+ fnptypeline.append(fnparam.name)
+ fnptypeline.append(",\n")
+
+ #remove trailing commas
+ if len(fnptypeline) > 0:
+ del fnptypeline[-1]
+
+ fnptype.extend(fnptypeline)
+ fnptype.append("\n);\n")
+ clrallEvents.extend(fnptype)
+
+ return ''.join(clrallEvents)
+
+#generates the dummy header file which is used by the VM as entry point to the logging Functions
+def generateclrEtwDummy(eventNodes,allTemplates):
+ clretmEvents = []
+ for eventNode in eventNodes:
+ eventName = eventNode.getAttribute('symbol')
+ templateName = eventNode.getAttribute('template')
+
+ fnptype = []
+ #generate FireEtw functions
+ fnptype.append("#define FireEtw")
+ fnptype.append(eventName)
+ fnptype.append("(");
+ line = []
+ if templateName:
+ for subTemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subTemplate)
+
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ line.append(fnparam.name)
+ line.append(", ")
+
+ #remove trailing commas
+ if len(line) > 0:
+ del line[-1]
+
+ fnptype.extend(line)
+ fnptype.append(") 0\n")
+ clretmEvents.extend(fnptype)
+
+ return ''.join(clretmEvents)
+
+def generateClralltestEvents(sClrEtwAllMan):
+ tree = DOM.parse(sClrEtwAllMan)
+
+ clrtestEvents = []
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
+ for eventNode in eventNodes:
+ eventName = eventNode.getAttribute('symbol')
+ templateName = eventNode.getAttribute('template')
+ clrtestEvents.append(" EventXplatEnabled" + eventName + "();\n")
+ clrtestEvents.append("Error |= FireEtXplat" + eventName + "(\n")
+
+
+ line =[]
+ if templateName :
+ for subTemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subTemplate)
+
+ for params in fnSig.paramlist:
+ argline =''
+ fnparam = fnSig.getParam(params)
+ if fnparam.name.lower() == 'count':
+ argline = '2'
+ else:
+ if fnparam.winType == "win:Binary":
+ argline = 'win_Binary'
+ elif fnparam.winType == "win:Pointer" and fnparam.count == "win:count":
+ argline = "(const void**)&var11"
+ elif fnparam.winType == "win:Pointer" :
+ argline = "(const void*)var11"
+ elif fnparam.winType =="win:AnsiString":
+ argline = '" Testing AniString "'
+ elif fnparam.winType =="win:UnicodeString":
+ argline = 'W(" Testing UnicodeString ")'
+ else:
+ if fnparam.count == "win:count":
+ line.append("&")
+
+ argline = fnparam.winType.replace(":","_")
+
+ line.append(argline)
+ line.append(",\n")
+
+ #remove trailing commas
+ if len(line) > 0:
+ del line[-1]
+ line.append("\n")
+ line.append(");\n")
+ clrtestEvents.extend(line)
+
+ return ''.join(clrtestEvents)
+
+
+
+
+def generateSanityTest(sClrEtwAllMan,testDir):
+ if not os.path.exists(testDir):
+ os.makedirs(testDir)
+
+ cmake_file = testDir + "/CMakeLists.txt"
+ test_cpp = testDir + "/clralltestevents.cpp"
+ testinfo = testDir + "/testinfo.dat"
+ Cmake_file = open(cmake_file,'w')
+ Test_cpp = open(test_cpp,'w')
+ Testinfo = open(testinfo,'w')
+
+ #CMake File:
+ print >>Cmake_file, stdprolog_cmake
+ print >>Cmake_file, """
+ cmake_minimum_required(VERSION 2.8.12.2)
+ set(CMAKE_INCLUDE_CURRENT_DIR ON)
+ set(SOURCES
+ """
+ print >>Cmake_file, test_cpp
+ print >>Cmake_file, """
+ )
+ include_directories($ENV{__GeneratedIntermediatesDir}/inc)
+ include_directories(${COREPAL_SOURCE_DIR}/inc/rt)
+
+ add_executable(eventprovidertest
+ ${SOURCES}
+ )
+ set(EVENT_PROVIDER_DEPENDENCIES "")
+ set(EVENT_PROVIDER_LINKER_OTPTIONS "")
+ if(CMAKE_SYSTEM_NAME STREQUAL Linux)
+ add_definitions(-DFEATURE_EVENT_TRACE=1)
+ list(APPEND EVENT_PROVIDER_DEPENDENCIES
+ coreclrtraceptprovider
+ eventprovider
+ )
+ list(APPEND EVENT_PROVIDER_LINKER_OTPTIONS
+ ${EVENT_PROVIDER_DEPENDENCIES}
+ )
+
+ endif(CMAKE_SYSTEM_NAME STREQUAL Linux)
+
+ add_dependencies(eventprovidertest ${EVENT_PROVIDER_DEPENDENCIES} coreclrpal)
+ target_link_libraries(eventprovidertest
+ coreclrpal
+ ${EVENT_PROVIDER_LINKER_OTPTIONS}
+ )
+ """
+ print >>Testinfo, """
+ 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
+ print >>Test_cpp, stdprolog
+ print >>Test_cpp, """
+/*=====================================================================
+**
+** Source: clralltestevents.cpp
+**
+** Purpose: Ensure Correctness of Eventing code
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+#include <clrxplatevents.h>
+
+typedef struct _Struct1 {
+ ULONG Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+} Struct1;
+
+Struct1 var21[2] = { { 245, 13, 14, "deadbea" }, { 542, 0, 14, "deadflu" } };
+
+Struct1* var11 = var21;
+Struct1* win_Struct = var21;
+
+GUID win_GUID ={ 245, 13, 14, "deadbea" };
+double win_Double =34.04;
+ULONG win_ULong = 34;
+BOOL win_Boolean = FALSE;
+unsigned __int64 win_UInt64 = 114;
+unsigned int win_UInt32 = 4;
+unsigned short win_UInt16 = 12;
+unsigned char win_UInt8 = 9;
+int win_Int32 = 12;
+BYTE* win_Binary =(BYTE*)var21 ;
+int __cdecl main(int argc, char **argv)
+{
+
+ /* Initialize the PAL.
+ */
+
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ULONG Error = ERROR_SUCCESS;
+#if defined(FEATURE_EVENT_TRACE)
+ Trace("\\n Starting functional eventing APIs tests \\n");
+"""
+
+ print >>Test_cpp, generateClralltestEvents(sClrEtwAllMan)
+ print >>Test_cpp,"""
+/* 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");
+#endif //defined(FEATURE_EVENT_TRACE)
+ PAL_Terminate();
+ return PASS;
+ }
+
+"""
+ Cmake_file.close()
+ Test_cpp.close()
+ Testinfo.close()
+
+def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy):
+ tree = DOM.parse(sClrEtwAllMan)
+
+ incDir = os.path.dirname(os.path.realpath(clretwdummy))
+ if not os.path.exists(incDir):
+ os.makedirs(incDir)
+ Clretwdummy = open(clretwdummy,'w')
+ print >>Clretwdummy, stdprolog
+
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
+ #pal: create etmdummy.h
+ print >>Clretwdummy,generateclrEtwDummy(eventNodes,allTemplates)
+
+ Clretwdummy.close()
+
+def generatePlformIndependentFiles(sClrEtwAllMan,incDir,etmDummyFile, testDir):
+ tree = DOM.parse(sClrEtwAllMan)
+ if not os.path.exists(incDir):
+ os.makedirs(incDir)
+
+ generateSanityTest(sClrEtwAllMan,testDir)
+ generateEtmDummyHeader(sClrEtwAllMan,etmDummyFile)
+ clrallevents = incDir + "/clretwallmain.h"
+ clrxplatevents = incDir + "/clrxplatevents.h"
+
+ Clrallevents = open(clrallevents,'w')
+ Clrxplatevents = open(clrxplatevents,'w')
+
+ print >>Clrallevents, stdprolog
+ print >>Clrxplatevents, stdprolog
+
+ print >>Clrallevents, "\n#include \"clrxplatevents.h\"\n"
+
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
+ #vm header:
+ print >>Clrallevents,generateClrallEvents(eventNodes,allTemplates)
+
+ #pal: create clrallevents.h
+ print >>Clrxplatevents, generateClrXplatEvents(eventNodes,allTemplates)
+
+
+ Clrxplatevents.close()
+ Clrallevents.close()
+
+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'):
+
+ 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
+
+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('--inc', type=str, required=True,
+ help='full path to directory where the header files will be generated')
+ required.add_argument('--dummy', type=str, required=True,
+ help='full path to file that will have dummy definitions of FireEtw functions')
+ required.add_argument('--testdir', type=str, required=True,
+ help='full path to directory where the test assets will be deployed' )
+ args, unknown = parser.parse_known_args(argv)
+ if unknown:
+ print('Unknown argument(s): ', ', '.join(unknown))
+ return const.UnknownArguments
+
+ sClrEtwAllMan = args.man
+ exclusionListFile = args.exc
+ incdir = args.inc
+ etmDummyFile = args.dummy
+ testDir = args.testdir
+
+ checkConsistency(sClrEtwAllMan, exclusionListFile)
+ generatePlformIndependentFiles(sClrEtwAllMan,incdir,etmDummyFile,testDir)
+
+if __name__ == '__main__':
+ return_code = main(sys.argv[1:])
+ sys.exit(return_code)
+
+
+
diff --git a/src/scripts/genXplatLttng.py b/src/scripts/genXplatLttng.py
new file mode 100644
index 0000000000..1a1652e22b
--- /dev/null
+++ b/src/scripts/genXplatLttng.py
@@ -0,0 +1,600 @@
+##
+## Copyright (c) Microsoft. All rights reserved.
+## Licensed under the MIT license. See LICENSE file in the project root for full license information.
+##
+## Sample LTTng Instrumentation code that is generated:
+##
+## HEADER:
+## #define GCFinalizersEnd_TRACEPOINT_ARGS \
+##TP_ARGS(\
+## const unsigned int ,Count\
+##)
+##TRACEPOINT_EVENT_CLASS(
+## DotNETRuntime,
+## GCFinalizersEnd,
+## GCFinalizersEnd_TRACEPOINT_ARGS,
+## TP_FIELDS(
+## ctf_integer(unsigned int, Count, Count)
+## )
+##)
+##
+##CPP :
+##
+##extern "C" BOOL EventXplatEnabledGCFinalizersEnd(){ return TRUE;}
+##extern "C" ULONG FireEtXplatGCFinalizersEnd(
+## const unsigned int Count
+##)
+##{
+## ULONG Error = ERROR_WRITE_FAULT;
+## if (!EventXplatEnabledGCFinalizersEnd()){ return ERROR_SUCCESS;}
+##
+##
+## tracepoint(
+## DotNETRuntime,
+## GCFinalizersEnd,
+## Count
+## );
+## Error = ERROR_SUCCESS;
+##
+##return Error;
+##}
+##
+###define GCFinalizersEndT_TRACEPOINT_INSTANCE(name) \
+##TRACEPOINT_EVENT_INSTANCE(\
+## DotNETRuntime,\
+## GCFinalizersEnd,\
+## name ,\
+## GCFinalizersEnd_TRACEPOINT_ARGS \
+##)
+#
+
+import os
+from genXplatEventing import *
+
+stdprolog="""
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+/******************************************************************
+
+DO NOT MODIFY. AUTOGENERATED FILE.
+This file is generated using the logic from <root>/src/scripts/genXplatLttng.py
+
+******************************************************************/
+"""
+stdprolog_cmake="""
+#
+#
+#******************************************************************
+
+#DO NOT MODIFY. AUTOGENERATED FILE.
+#This file is generated using the logic from <root>/src/scripts/genXplatLttng.py
+
+#******************************************************************
+"""
+
+lttngDataTypeMapping ={
+ #constructed types
+ "win:null" :" ",
+ "win:Int64" :"const __int64",
+ "win:ULong" :"const ULONG",
+ "win:count" :"*",
+ "win:Struct" :"const int",
+ #actual spec
+ "win:GUID" :"const int",
+ "win:AnsiString" :"const char*",
+ "win:UnicodeString" :"const char*",
+ "win:Double" :"const double",
+ "win:Int32" :"const signed int",
+ "win:Boolean" :"const BOOL",
+ "win:UInt64" :"const unsigned __int64",
+ "win:UInt32" :"const unsigned int",
+ "win:UInt16" :"const unsigned short",
+ "win:UInt8" :"const unsigned char",
+ "win:Pointer" :"const size_t",
+ "win:Binary" :"const BYTE"
+ }
+
+ctfDataTypeMapping ={
+ #constructed types
+ "win:Int64" :"ctf_integer",
+ "win:ULong" :"ctf_integer",
+ "win:count" :"ctf_sequence",
+ "win:Struct" :"ctf_sequence",
+ #actual spec
+ "win:GUID" :"ctf_sequence",
+ "win:AnsiString" :"ctf_string",
+ "win:UnicodeString" :"ctf_string",
+ "win:Double" :"ctf_float",
+ "win:Int32" :"ctf_integer",
+ "win:Boolean" :"ctf_integer",
+ "win:UInt64" :"ctf_integer",
+ "win:UInt32" :"ctf_integer",
+ "win:UInt16" :"ctf_integer",
+ "win:UInt8" :"ctf_integer", #actually a character
+ "win:Pointer" :"ctf_integer",
+ "win:Binary" :"ctf_sequence"
+ }
+
+def generateLttngHeader(providerName,allTemplates,eventNodes):
+ lTTngHdr = []
+ for templateName in allTemplates.keys():
+ for subTemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subTemplate)
+#TP_ARGS
+ tp_args = []
+ tp_args_param = []
+ tp_args.append("\n#define ")
+ tp_args.append(subTemplate)
+ tp_args.append('_TRACEPOINT_ARGS \\\n')
+ tp_args.append('TP_ARGS(\\\n')
+
+
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ wintypeName = fnparam.winType
+ typewName = lttngDataTypeMapping[wintypeName]
+ winCount = fnparam.count
+ countw = lttngDataTypeMapping[winCount]
+
+ tp_args_param.append(" ")
+ tp_args_param.append(typewName)
+ if countw != " ":
+ tp_args_param.append(countw)
+
+ tp_args_param.append(" ,")
+ tp_args_param.append(fnparam.name)
+ tp_args_param.append(",\\\n")
+
+ if len(tp_args_param) > 0:
+ del tp_args_param[-1]
+ tp_args.extend(tp_args_param)
+ tp_args.append("\\\n)\n")
+ lTTngHdr.extend(tp_args)
+#TP_EVENT_CLASS
+ tp_fields =[]
+ tp_fields.append("TRACEPOINT_EVENT_CLASS(\n")
+ tp_fields.append(" " + providerName + ",\n")
+ tp_fields.append(" " + subTemplate + ",\n")
+ tp_fields.append(" " + subTemplate + "_TRACEPOINT_ARGS,\n")
+ tp_fields.append(" " + " TP_FIELDS(\n")
+#TP_FIELDS
+
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ wintypeName = fnparam.winType
+ typewName = lttngDataTypeMapping[wintypeName]
+ winCount = fnparam.count
+ countw = lttngDataTypeMapping[winCount]
+ typewName = typewName.replace("const ","")
+
+ tp_fields_body = []
+ ctf_type = None
+ varname = fnparam.name
+
+ if fnparam.prop:
+ #this is an explicit struct treat as a sequence
+ ctf_type = "ctf_sequence"
+ sizeofseq = fnparam.prop
+ tp_fields_body.append(typewName + ", " + varname +", " + varname + ",size_t,")
+ tp_fields_body.append(sizeofseq)
+
+ else:
+ ctf_type = ctfDataTypeMapping[wintypeName]
+ if ctf_type == "ctf_string":
+ tp_fields_body.append(varname + ", " + varname)
+ elif ctf_type == "ctf_integer" or ctf_type == "ctf_float":
+ tp_fields_body.append(typewName + ", " + varname +", " + varname)
+ elif ctf_type == "ctf_sequence":
+ raise Exception("ctf_sequence needs to have its memory expilicitly laid out")
+ else:
+ raise Exception("no such ctf intrinsic called: " + ctf_type)
+
+
+ tp_fields.append(" ")
+ tp_fields.append(ctf_type + "(")
+ tp_fields.extend(tp_fields_body)
+ tp_fields.append(")\n")
+
+ tp_fields.append(" )\n)\n")
+ lTTngHdr.extend(tp_fields)
+
+# Macro for defining event instance
+ lTTngHdr.append("\n#define " + subTemplate)
+ lTTngHdr.append("""T_TRACEPOINT_INSTANCE(name) \\
+TRACEPOINT_EVENT_INSTANCE(\\
+""")
+ lTTngHdr.append(" "+providerName + ",\\\n")
+ lTTngHdr.append(" " + subTemplate + ",\\\n")
+ lTTngHdr.append(" name ,\\\n")
+ lTTngHdr.append(" " + subTemplate + "_TRACEPOINT_ARGS \\\n)")
+
+#add an empty template node to just specify the event name in the event stream
+ lTTngHdr.append("\n\nTRACEPOINT_EVENT_CLASS(\n")
+ lTTngHdr.append(" " +providerName + ",\n")
+ lTTngHdr.append(" emptyTemplate ,\n")
+ lTTngHdr.append(""" TP_ARGS(),
+ TP_FIELDS()
+)
+#define T_TRACEPOINT_INSTANCE(name) \\
+TRACEPOINT_EVENT_INSTANCE(\\
+""")
+ lTTngHdr.append(" " +providerName + ",\\\n")
+ lTTngHdr.append(" emptyTemplate,\\\n")
+
+ lTTngHdr.append(""" name ,\\
+ TP_ARGS()\\
+)""")
+#end of empty template
+# create the event instance in headers
+ lTTngHdr.append("\n")
+ for eventNode in eventNodes:
+ eventName = eventNode.getAttribute('symbol');
+ templateName = eventNode.getAttribute('template');
+
+ if not eventName :
+ raise Exception(eventNode + " event does not have a symbol")
+ if not templateName:
+ lTTngHdr.append("T_TRACEPOINT_INSTANCE(")
+ lTTngHdr.append(eventName +")\n")
+ continue
+
+ for subtemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ subevent = subtemplate;
+ subevent = subevent.replace(templateName,'')
+ lTTngHdr.append(subtemplate)
+ lTTngHdr.append("T_TRACEPOINT_INSTANCE(")
+ lTTngHdr.append(eventName + subevent + ")\n")
+
+ lTTngHdr.append("\n#endif /* LTTNG_CORECLR_H")
+ lTTngHdr.append(providerName + " */\n")
+ lTTngHdr.append("#include <lttng/tracepoint-event.h>")
+
+ return ''.join(lTTngHdr)
+
+def generateLttngTpProvider(providerName,eventNodes,allTemplates):
+ lTTngImpl = []
+ for eventNode in eventNodes:
+ eventName = eventNode.getAttribute('symbol')
+ templateName = eventNode.getAttribute('template')
+ vars_to_be_freed = [] #vars representing the allocation we make
+ #generate EventXplatEnabled
+ lTTngImpl.append("extern \"C\" BOOL EventXplatEnabled")
+ lTTngImpl.append(eventName)
+ lTTngImpl.append("(){ return TRUE;}\n")
+ #generate FireEtw functions
+ fnptype = []
+ linefnptype = []
+ fnptype.append("extern \"C\" ULONG FireEtXplat")
+ fnptype.append(eventName)
+ fnptype.append("(\n")
+
+
+ if templateName:
+ for subtemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subtemplate)
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ wintypeName = fnparam.winType
+ typewName = palDataTypeMapping[wintypeName]
+ winCount = fnparam.count
+ countw = palDataTypeMapping[winCount]
+
+ 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("{\n ULONG Error = ERROR_WRITE_FAULT;\n")
+ lTTngImpl.extend(fnptype)
+
+#start of fn body
+ lTTngImpl.append(" if (!EventXplatEnabled")
+ lTTngImpl.append(eventName)
+ lTTngImpl.append("()){ return ERROR_SUCCESS;}\n")
+
+ linefnbody = []
+ if templateName:
+ #emit code to init variables convert unicode to ansi string
+ for subtemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subtemplate)
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ wintypeName = fnparam.winType
+ paramname = fnparam.name
+
+ if wintypeName == "win:UnicodeString":
+ lTTngImpl.append(" INT " + paramname + "_path_size = -1;\n")
+ lTTngImpl.append(" INT " + paramname + "_full_name_path_size")
+ lTTngImpl.append(" = WideCharToMultiByte( CP_ACP, 0, " + paramname + ", -1, NULL, 0, NULL, NULL );\n")
+ lTTngImpl.append(" CHAR* " + paramname + "_full_name = NULL;\n")
+
+ lTTngImpl.append("\n")
+
+#emit tracepoints
+ for subtemplate in allTemplates[templateName].allAbstractTemplateTypes:
+ fnSig = allTemplates[templateName].getFnFrame(subtemplate)
+
+ subevent = subtemplate
+ subevent = subevent.replace(templateName,'')
+ linefnbody.append("\n tracepoint(\n")
+ linefnbody.append(" " + providerName + ",\n")
+ linefnbody.append(" " + eventName + subevent)
+ linefnbody.append(",\n")
+
+ for params in fnSig.paramlist:
+ fnparam = fnSig.getParam(params)
+ wintypeName = fnparam.winType
+ winCount = fnparam.count
+ paramname = fnparam.name
+ ctf_type = ctfDataTypeMapping.get(winCount)
+
+ linefnbody.append(" ")
+ if not ctf_type:
+ ctf_type = ctfDataTypeMapping[wintypeName]
+
+ if ctf_type == "ctf_string" and wintypeName == "win:UnicodeString":
+ #emit code to convert unicode to ansi string
+ lTTngImpl.append(" "+ paramname + "_full_name = (CHAR*)malloc(")
+ lTTngImpl.append(paramname + "_full_name_path_size*sizeof(CHAR));\n")
+
+ lTTngImpl.append(" _ASSERTE("+paramname+ "_full_name != NULL);\n")
+ lTTngImpl.append(" if(" + paramname + "_full_name == NULL){goto LExit;}\n\n")
+
+ lTTngImpl.append(" " + paramname+ "_path_size = WideCharToMultiByte( CP_ACP, 0, ")
+ lTTngImpl.append(paramname + ", -1, ")
+ lTTngImpl.append(paramname + "_full_name, ")
+ lTTngImpl.append(paramname + "_full_name_path_size, NULL, NULL );\n")
+
+ lTTngImpl.append(" _ASSERTE(" +paramname+ "_path_size == " )
+ lTTngImpl.append(paramname + "_full_name_path_size );\n")
+
+ lTTngImpl.append(" if( " + paramname + "_path_size == 0 ){ Error = ERROR_INVALID_PARAMETER; goto LExit;}\n")
+
+ vars_to_be_freed.append(paramname + "_full_name")
+
+ linefnbody.append(paramname + "_full_name")
+ linefnbody.append(",\n")
+ continue
+
+ elif ctf_type == "ctf_sequence" or wintypeName == "win:Pointer":
+ linefnbody.append("(" + lttngDataTypeMapping[wintypeName])
+ if not lttngDataTypeMapping[winCount] == " ":
+ linefnbody.append( lttngDataTypeMapping[winCount])
+
+ linefnbody.append(") ")
+
+ linefnbody.append(paramname)
+ linefnbody.append(",\n")
+
+ if len(linefnbody) > 0 :
+ del linefnbody[-1]
+ linefnbody.append("\n );\n")
+
+ else:
+ linefnbody.append("\n tracepoint(\n")
+ linefnbody.append(" "+providerName + ",\n")
+ linefnbody.append(" "+eventName)
+ linefnbody.append("\n );\n")
+
+ lTTngImpl.extend(linefnbody)
+ lTTngImpl.append(" Error = ERROR_SUCCESS;\n")
+
+ if len(vars_to_be_freed) > 0:
+ lTTngImpl.append("LExit:\n")
+ vars_to_be_freed.reverse()
+ for var in vars_to_be_freed:
+ lTTngImpl.append(" if ("+ var + " != NULL) {free(" )
+ lTTngImpl.append(var)
+ lTTngImpl.append(");}\n")
+
+ lTTngImpl.append("\nreturn Error;\n}\n")
+
+ return ''.join(lTTngImpl)
+
+def generateLttngFiles(etwmanifest,intermediate):
+
+ tree = DOM.parse(etwmanifest)
+
+ if not os.path.exists(intermediate):
+ os.makedirs(intermediate)
+
+ eventprovider_directory = intermediate + "/eventprovider/"
+ tracepointprovider_directory = eventprovider_directory + "/tracepointprovider"
+ lttng_directory = eventprovider_directory + "/lttng/"
+ lttngevntprovPre = lttng_directory + "/eventprov"
+ lttngevntprovTpPre = lttng_directory + "/traceptprov"
+
+ if not os.path.exists(eventprovider_directory):
+ os.makedirs(eventprovider_directory)
+
+ if not os.path.exists(lttng_directory):
+ os.makedirs(lttng_directory)
+
+ if not os.path.exists(tracepointprovider_directory):
+ os.makedirs(tracepointprovider_directory)
+
+
+#Top level Cmake
+ topCmake = open(eventprovider_directory + "/CMakeLists.txt", 'w')
+ print >>topCmake, stdprolog_cmake
+ print >>topCmake, """cmake_minimum_required(VERSION 2.8.12.2)
+
+ project(eventprovider)
+
+ set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+ add_definitions(-DPAL_STDCPP_COMPAT=1)
+ include_directories(${COREPAL_SOURCE_DIR}/inc/rt)
+ include_directories(lttng)
+
+ add_library(eventprovider
+ STATIC
+"""
+
+ for providerNode in tree.getElementsByTagName('provider'):
+ providerName = providerNode.getAttribute('name')
+ providerName = providerName.replace("Windows-",'')
+ providerName = providerName.replace("Microsoft-",'')
+
+ providerName_File = providerName.replace('-','')
+ providerName_File = providerName_File.lower()
+
+ print >>topCmake,' "'+ lttngevntprovPre + providerName_File + ".cpp" + '"'
+
+ print >>topCmake, """)
+ add_subdirectory(tracepointprovider)
+
+ # Install the static eventprovider library
+ install (TARGETS eventprovider DESTINATION lib)"""
+ topCmake.close()
+
+#TracepointProvider Cmake
+
+ tracepointprovider_Cmake = open(tracepointprovider_directory + "/CMakeLists.txt", 'w')
+
+ print >>tracepointprovider_Cmake, stdprolog_cmake
+ print >>tracepointprovider_Cmake, """cmake_minimum_required(VERSION 2.8.12.2)
+
+ project(coreclrtraceptprovider)
+
+ set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+ add_definitions(-DPAL_STDCPP_COMPAT=1)
+ include_directories(${COREPAL_SOURCE_DIR}/inc/rt)
+ include_directories(../lttng/)
+ add_compile_options(-fPIC)
+
+ add_library(coreclrtraceptprovider
+ SHARED"""
+
+ for providerNode in tree.getElementsByTagName('provider'):
+ providerName = providerNode.getAttribute('name')
+ providerName = providerName.replace("Windows-",'')
+ providerName = providerName.replace("Microsoft-",'')
+
+ providerName_File = providerName.replace('-','')
+ providerName_File = providerName_File.lower()
+
+ print >>tracepointprovider_Cmake,' "'+ lttngevntprovTpPre + providerName_File +".cpp" + '"'
+
+ print >>tracepointprovider_Cmake, """ )
+
+ target_link_libraries(coreclrtraceptprovider
+ -llttng-ust
+ )
+
+ #Install the static coreclrtraceptprovider library
+ install (TARGETS coreclrtraceptprovider DESTINATION .)"""
+ tracepointprovider_Cmake.close()
+
+# Generate Lttng specific instrumentation
+ for providerNode in tree.getElementsByTagName('provider'):
+
+ providerName = providerNode.getAttribute('name')
+ providerName = providerName.replace("Windows-",'')
+ providerName = providerName.replace("Microsoft-",'')
+
+ providerName_File = providerName.replace('-','')
+ providerName_File = providerName_File.lower()
+ providerName = providerName.replace('-','_')
+
+ lttngevntheadershortname = "tp" + providerName_File +".h";
+ lttngevntheader = eventprovider_directory +"lttng/"+ lttngevntheadershortname
+ lttngevntprov = lttngevntprovPre + providerName_File + ".cpp"
+ lttngevntprovTp = lttngevntprovTpPre + providerName_File +".cpp"
+
+
+ lTTngHdr = open(lttngevntheader, 'w')
+ lTTngImpl = open(lttngevntprov, 'w')
+ lTTngTpImpl = open(lttngevntprovTp, 'w')
+
+ print >>lTTngHdr, stdprolog
+ print >>lTTngImpl, stdprolog
+ print >>lTTngTpImpl, stdprolog
+
+ print >>lTTngTpImpl,"\n#define TRACEPOINT_CREATE_PROBES\n"
+
+
+ print >>lTTngTpImpl,"#include \"./"+lttngevntheadershortname + "\""
+
+ print >>lTTngHdr, """
+#include "palrt.h"
+#include "pal.h"
+
+#undef TRACEPOINT_PROVIDER
+"""
+
+
+ print >>lTTngHdr, "#define TRACEPOINT_PROVIDER " + providerName
+ print >>lTTngHdr,"""
+
+#undef TRACEPOINT_INCLUDE"""
+
+ print >>lTTngHdr,"#define TRACEPOINT_INCLUDE \"./" + lttngevntheadershortname + "\"\n"
+
+
+ print >>lTTngHdr, "#if !defined(LTTNG_CORECLR_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n"
+ print >>lTTngHdr, "#define LTTNG_CORECLR_H" + providerName
+
+ print >>lTTngHdr, "\n#include <lttng/tracepoint.h>\n"
+
+ print >>lTTngImpl, """
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE"""
+ print >>lTTngImpl,"#include \"" + lttngevntheadershortname + "\"\n"
+
+
+
+ templateNodes = providerNode.getElementsByTagName('template')
+ eventNodes = providerNode.getElementsByTagName('event')
+
+ allTemplates = parseTemplateNodes(templateNodes)
+ #generate the header
+ print >>lTTngHdr,generateLttngHeader(providerName,allTemplates,eventNodes)
+
+ #create the implementation of eventing functions : lttngeventprov*.cp
+ print >>lTTngImpl,generateLttngTpProvider(providerName,eventNodes,allTemplates)
+
+ lTTngHdr.close()
+ lTTngImpl.close()
+ lTTngTpImpl.close()
+
+import argparse
+import sys
+
+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 intermediate directory')
+ args, unknown = parser.parse_known_args(argv)
+ if unknown:
+ print('Unknown argument(s): ', ', '.join(unknown))
+ return const.UnknownArguments
+
+ sClrEtwAllMan = args.man
+ intermediate = args.intermediate
+
+ generateLttngFiles(sClrEtwAllMan,intermediate)
+
+if __name__ == '__main__':
+ return_code = main(sys.argv[1:])
+ sys.exit(return_code)
+