mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-08 11:37:04 +09:00
1179 lines
47 KiB
Python
1179 lines
47 KiB
Python
#
|
|
## Licensed to the .NET Foundation under one or more agreements.
|
|
## The .NET Foundation licenses this file to you under the MIT license.
|
|
#
|
|
#
|
|
#USAGE:
|
|
#Add Events: modify <root>src/vm/ClrEtwAll.man
|
|
#Look at the Code in <root>/src/scripts/genLttngProvider.py for using subroutines in this file
|
|
#
|
|
|
|
# Python 2 compatibility
|
|
from __future__ import print_function
|
|
|
|
import os
|
|
import sys
|
|
import xml.dom.minidom as DOM
|
|
from utilities import open_for_update, parseInclusionList
|
|
|
|
class RuntimeFlavor:
|
|
def __init__(self, runtime):
|
|
if runtime.lower() == "coreclr":
|
|
self.coreclr = True
|
|
self.mono = False
|
|
self.nativeaot = False
|
|
elif runtime.lower() == "mono":
|
|
self.coreclr = False
|
|
self.mono = True
|
|
self.nativeaot = False
|
|
elif runtime.lower() == "nativeaot":
|
|
self.coreclr = False
|
|
self.mono = False
|
|
self.nativeaot = True
|
|
else:
|
|
self.coreclr = True
|
|
self.mono = False
|
|
self.nativeaot = False
|
|
|
|
stdprolog="""
|
|
// Licensed to the .NET Foundation under one or more agreements.
|
|
// The .NET Foundation licenses this file to you under the MIT license.
|
|
|
|
/******************************************************************
|
|
|
|
DO NOT MODIFY. AUTOGENERATED FILE.
|
|
This file is generated using the logic from <root>/src/scripts/genEventing.py
|
|
|
|
******************************************************************/
|
|
"""
|
|
|
|
lindent = " "
|
|
|
|
coreCLRPalDataTypeMapping={
|
|
#constructed types
|
|
"win:null" :" ",
|
|
"win:Int64" :"const int64_t",
|
|
"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 uint64_t",
|
|
"win:UInt32" :"const unsigned int",
|
|
"win:UInt16" :"const unsigned short",
|
|
"win:UInt8" :"const unsigned char",
|
|
"win:Pointer" :"const void*",
|
|
"win:Binary" :"const BYTE",
|
|
}
|
|
|
|
coreCLREventPipeDataTypeMapping={
|
|
"BOOL" : "BOOL",
|
|
"LPCGUID" : "LPCGUID",
|
|
"UCHAR" : "UCHAR",
|
|
"ULONG" : "ULONG",
|
|
"ULONGLONG" : "ULONGLONG",
|
|
"WCHAR" : "WCHAR",
|
|
"BYTE" : "BYTE",
|
|
}
|
|
|
|
coreCLRUserEventDataTypeMapping={
|
|
"win:UInt8" : "TraceLoggingUInt8",
|
|
"win:UInt16" : "TraceLoggingUInt16",
|
|
"win:Int32" : "TraceLoggingInt32",
|
|
"win:UInt32" : "TraceLoggingUInt32",
|
|
"win:HexInt32" : "TraceLoggingHexInt32",
|
|
"win:UInt64" : "TraceLoggingUInt64",
|
|
"win:Int64" : "TraceLoggingInt64",
|
|
"win:HexInt64" : "TraceLoggingHexInt64",
|
|
"win:Pointer" : "TraceLoggingPointer",
|
|
"win:Boolean" : "TraceLoggingBoolean",
|
|
"win:UnicodeString" : "TraceLoggingString16",
|
|
"win:GUID" : "TraceLoggingGuid",
|
|
"win:Binary" : "TraceLoggingBinary",
|
|
"win:Double" : "TraceLoggingFloat64",
|
|
"win:AnsiString" : "TraceLoggingString",
|
|
}
|
|
|
|
coreCLRUserEventLogLevelMapping={
|
|
"win:LogAlways" : "0",
|
|
"win:Critical" : "1",
|
|
"win:Error" : "2",
|
|
"win:Warning" : "3",
|
|
"win:Informational" : "4",
|
|
"win:Verbose" : "5",
|
|
}
|
|
|
|
coreCLRUserEventArrayTypeMapping={
|
|
"win:UInt32" : "TraceLoggingUInt32Array",
|
|
"win:Binary" : "TraceLoggingUInt8Array",
|
|
"win:UInt64" : "TraceLoggingUInt64Array",
|
|
}
|
|
monoPalDataTypeMapping={
|
|
#constructed types
|
|
"win:null" :" ",
|
|
"win:Int64" :"const int64_t",
|
|
"win:ULong" :"const uint32_t",
|
|
"win:count" :"*",
|
|
"win:Struct" :"const void",
|
|
#actual spec
|
|
"win:GUID" :"const uint8_t",
|
|
"win:AnsiString" :"const char*",
|
|
"win:UnicodeString" :"const ep_char8_t*",
|
|
"win:Double" :"const double",
|
|
"win:Int32" :"const int32_t",
|
|
"win:Boolean" :"const bool",
|
|
"win:UInt64" :"const uint64_t",
|
|
"win:UInt32" :"const uint32_t",
|
|
"win:UInt16" :"const uint16_t",
|
|
"win:UInt8" :"const uint8_t",
|
|
"win:Pointer" :"const void*",
|
|
"win:Binary" :"const uint8_t",
|
|
}
|
|
|
|
monoEventPipeDataTypeMapping={
|
|
"BOOL" : "bool",
|
|
"LPCGUID" : "const uint8_t*",
|
|
"UCHAR" : "uint8_t",
|
|
"ULONG" : "uint32_t",
|
|
"ULONGLONG" : "uint64_t",
|
|
"WCHAR" : "wchar_t",
|
|
"BYTE" : "uint8_t",
|
|
}
|
|
|
|
aotPalDataTypeMapping={
|
|
#constructed types
|
|
"win:null" :" ",
|
|
"win:Int64" :"const int64_t",
|
|
"win:ULong" :"const ULONG",
|
|
"win:count" :"*",
|
|
"win:Struct" :"const void",
|
|
#actual spec
|
|
"win:GUID" :"const GUID",
|
|
"win:AnsiString" :"LPCSTR",
|
|
"win:UnicodeString" :"const WCHAR*",
|
|
"win:Double" :"const double",
|
|
"win:Int32" :"const signed int",
|
|
"win:Boolean" :"const BOOL",
|
|
"win:UInt64" :"const uint64_t",
|
|
"win:UInt32" :"const unsigned int",
|
|
"win:UInt16" :"const unsigned short",
|
|
"win:UInt8" :"const unsigned char",
|
|
"win:Pointer" :"const void*",
|
|
"win:Binary" :"const BYTE",
|
|
}
|
|
|
|
aotEventPipeDataTypeMapping={
|
|
"BOOL" : "BOOL",
|
|
"LPCGUID" : "const GUID *",
|
|
"UCHAR" : "UCHAR",
|
|
"ULONG" : "ULONG",
|
|
"ULONGLONG" : "ULONGLONG",
|
|
"WCHAR" : "WCHAR",
|
|
"BYTE" : "BYTE",
|
|
}
|
|
def getUserEventDataTypeMapping(runtimeFlavor):
|
|
if runtimeFlavor.coreclr:
|
|
return coreCLRUserEventDataTypeMapping
|
|
# elif runtimeFlavor.mono:
|
|
# return monoUserEventDataTypeMapping
|
|
# elif runtimeFlavor.nativeaot:
|
|
# return aotUserEventDataTypeMapping
|
|
|
|
def getUserEventLogLevelMapping(runtimeFlavor):
|
|
if runtimeFlavor.coreclr:
|
|
return coreCLRUserEventLogLevelMapping
|
|
# elif runtimeFlavor.mono:
|
|
# return monoUserEventLogLevelMapping
|
|
# elif runtimeFlavor.nativeaot:
|
|
# return aotUserEventLogLevelMapping
|
|
|
|
def getArrayDataTypeMapping(runtimeFlavor):
|
|
if runtimeFlavor.coreclr:
|
|
return coreCLRUserEventArrayTypeMapping
|
|
# elif runtimeFlavor.mono:
|
|
# return monoUserEventArrayTypeMapping
|
|
# elif runtimeFlavor.nativeaot:
|
|
# return aotUserEventArrayTypeMapping
|
|
|
|
def getEventPipeDataTypeMapping(runtimeFlavor):
|
|
if runtimeFlavor.coreclr:
|
|
return coreCLREventPipeDataTypeMapping
|
|
elif runtimeFlavor.mono:
|
|
return monoEventPipeDataTypeMapping
|
|
elif runtimeFlavor.nativeaot:
|
|
return aotEventPipeDataTypeMapping
|
|
|
|
def getPalDataTypeMapping(runtimeFlavor):
|
|
if runtimeFlavor.coreclr:
|
|
return coreCLRPalDataTypeMapping
|
|
elif runtimeFlavor.mono:
|
|
return monoPalDataTypeMapping
|
|
elif runtimeFlavor.nativeaot:
|
|
return aotPalDataTypeMapping
|
|
|
|
|
|
def includeProvider(providerName, runtimeFlavor):
|
|
if (runtimeFlavor.coreclr or runtimeFlavor.nativeaot) and providerName == "Microsoft-DotNETRuntimeMonoProfiler":
|
|
return False
|
|
elif runtimeFlavor.nativeaot and (providerName == "Microsoft-Windows-DotNETRuntimeRundown" or providerName == "Microsoft-Windows-DotNETRuntimeStress"):
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def includeEvent(inclusionList, providerName, eventName):
|
|
if len(inclusionList) == 0:
|
|
return True
|
|
if providerName in inclusionList and eventName in inclusionList[providerName]:
|
|
return True
|
|
elif providerName in inclusionList and "*" in inclusionList[providerName]:
|
|
return True
|
|
elif "*" in inclusionList and eventName in inclusionList["*"]:
|
|
return True
|
|
elif "*" in inclusionList and "*" in inclusionList["*"]:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def getCoreCLRMonoNativeAotTypeAdaptionDefines():
|
|
return """
|
|
#ifndef W
|
|
#define W(str) L##str
|
|
#endif
|
|
#ifndef SL
|
|
#define SL(str) str
|
|
#endif
|
|
#ifndef ERROR_SUCCESS
|
|
#define ERROR_SUCCESS 0L
|
|
#endif
|
|
#ifndef ERROR_WRITE_FAULT
|
|
#define ERROR_WRITE_FAULT 29L
|
|
#endif
|
|
"""
|
|
|
|
# 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
|
|
|
|
def getParamSequenceSize(paramSequence, estimate):
|
|
total = 0
|
|
pointers = 0
|
|
for param in paramSequence:
|
|
if param == "win:Int64":
|
|
total += 8
|
|
elif param == "win:ULong":
|
|
total += 4
|
|
elif param == "GUID":
|
|
total += 16
|
|
elif param == "win:Double":
|
|
total += 8
|
|
elif param == "win:Int32":
|
|
total += 4
|
|
elif param == "win:Boolean":
|
|
total += 4
|
|
elif param == "win:UInt64":
|
|
total += 8
|
|
elif param == "win:UInt32":
|
|
total += 4
|
|
elif param == "win:UInt16":
|
|
total += 2
|
|
elif param == "win:UInt8":
|
|
total += 1
|
|
elif param == "win:Pointer":
|
|
if estimate:
|
|
total += 8
|
|
else:
|
|
pointers += 1
|
|
elif param == "win:Binary":
|
|
total += 1
|
|
elif estimate:
|
|
if param == "win:AnsiString":
|
|
total += 32
|
|
elif param == "win:UnicodeString":
|
|
total += 64
|
|
elif param == "win:Struct":
|
|
total += 32
|
|
else:
|
|
raise Exception("Don't know size for " + param)
|
|
|
|
if estimate:
|
|
return total
|
|
|
|
return total, pointers
|
|
|
|
|
|
class Template:
|
|
def __repr__(self):
|
|
return "<Template " + self.name + ">"
|
|
|
|
def __init__(self, templateName, fnPrototypes, dependencies, structSizes, arrays):
|
|
self.name = templateName
|
|
self.signature = FunctionSignature()
|
|
self.structs = structSizes
|
|
self.arrays = arrays
|
|
|
|
for variable in fnPrototypes.paramlist:
|
|
for dependency in dependencies[variable]:
|
|
if not self.signature.getParam(dependency):
|
|
self.signature.append(dependency, fnPrototypes.getParam(dependency))
|
|
|
|
def getFnParam(self, name):
|
|
return self.signature.getParam(name)
|
|
|
|
@property
|
|
def num_params(self):
|
|
return len(self.signature.paramlist)
|
|
|
|
@property
|
|
def estimated_size(self):
|
|
total = getParamSequenceSize((self.getFnParam(paramName).winType for paramName in self.signature.paramlist), True)
|
|
|
|
if total < 32:
|
|
total = 32
|
|
elif total > 1024:
|
|
total = 1024
|
|
|
|
return total
|
|
|
|
|
|
|
|
class FunctionSignature:
|
|
def __repr__(self):
|
|
return ", ".join(self.paramlist)
|
|
|
|
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 __repr__(self):
|
|
return self.name
|
|
|
|
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
|
|
|
|
ignoredXmlTemplateAttribes = frozenset(["map","outType"])
|
|
usedXmlTemplateAttribes = frozenset(["name","inType","count", "length"])
|
|
|
|
def parseTemplateNodes(templateNodes):
|
|
|
|
#return values
|
|
allTemplates = {}
|
|
|
|
for templateNode in templateNodes:
|
|
structCounts = {}
|
|
arrays = {}
|
|
templateName = templateNode.getAttribute('tid')
|
|
var_Dependencies = {}
|
|
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:'+ templateName)
|
|
|
|
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: " + templateName)
|
|
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)
|
|
arrays[variable] = wincount
|
|
|
|
#construct the function signature
|
|
|
|
if wintype == "win:GUID":
|
|
var_Props = "sizeof(GUID)/sizeof(int)"
|
|
|
|
var_Dependencies[variable] = var_dependency
|
|
fnparam = FunctionParameter(wintype,variable,wincount,var_Props)
|
|
fnPrototypes.append(variable,fnparam)
|
|
|
|
structNodes = getTopLevelElementsByTagName(templateNode,'struct')
|
|
|
|
for structToBeMarshalled in structNodes:
|
|
structName = structToBeMarshalled.getAttribute('name')
|
|
countVarName = structToBeMarshalled.getAttribute('count')
|
|
|
|
assert(countVarName == "Count")
|
|
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")]
|
|
|
|
structCounts[structName] = countVarName
|
|
var_Dependencies[structName] = [countVarName, structName]
|
|
fnparam_pointer = FunctionParameter("win:Struct", structName, "win:count", countVarName)
|
|
fnPrototypes.append(structName, fnparam_pointer)
|
|
|
|
allTemplates[templateName] = Template(templateName, fnPrototypes, var_Dependencies, structCounts, arrays)
|
|
|
|
return allTemplates
|
|
|
|
def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, write_xplatheader, providerName, inclusionList, generatedFileType, user_events):
|
|
clrallEvents = []
|
|
for eventNode in eventNodes:
|
|
eventName = eventNode.getAttribute('symbol')
|
|
|
|
if not includeEvent(inclusionList, providerName, eventName):
|
|
continue
|
|
|
|
templateName = eventNode.getAttribute('template')
|
|
|
|
#generate EventEnabled
|
|
if includeProvider (providerName, runtimeFlavor):
|
|
if not target_cpp:
|
|
clrallEvents.append("static ")
|
|
if generatedFileType == "header-impl":
|
|
clrallEvents.append("inline ")
|
|
clrallEvents.append("%s EventEnabled" % (getEventPipeDataTypeMapping(runtimeFlavor)["BOOL"]))
|
|
clrallEvents.append(eventName)
|
|
clrallEvents.append("(void)")
|
|
if generatedFileType == "header":
|
|
clrallEvents.append(";\n")
|
|
elif generatedFileType == "source-impl-noop":
|
|
clrallEvents.append(" { return 0; }\n")
|
|
else:
|
|
clrallEvents.append(" {return ")
|
|
clrallEvents.append("EventPipeEventEnabled" + eventName + "()")
|
|
|
|
if runtimeFlavor.coreclr or write_xplatheader or runtimeFlavor.nativeaot:
|
|
if os.name == 'posix':
|
|
if user_events and runtimeFlavor.coreclr:
|
|
clrallEvents.append(" || UserEventsEventEnabled" + eventName + "()")
|
|
# native AOT does not support non-windows eventing other than via event pipe
|
|
if not runtimeFlavor.nativeaot:
|
|
clrallEvents.append(" || (XplatEventLogger" +
|
|
("::" if target_cpp else "_") +
|
|
"IsEventLoggingEnabled() && EventXplatEnabled" +
|
|
eventName + "());}\n\n")
|
|
else:
|
|
clrallEvents.append(";}\n\n")
|
|
else:
|
|
clrallEvents.append(" || EventXplatEnabled" + eventName + "();}\n\n")
|
|
else:
|
|
clrallEvents.append(";}\n\n")
|
|
|
|
#generate FireEtw functions
|
|
fnptype = []
|
|
fnbody = []
|
|
|
|
if not target_cpp:
|
|
clrallEvents.append("static ")
|
|
if not runtimeFlavor.nativeaot:
|
|
fnptype.append("inline ")
|
|
fnptype.append("%s FireEtw" % (getEventPipeDataTypeMapping(runtimeFlavor)["ULONG"]))
|
|
|
|
fnptype.append(eventName)
|
|
fnptype.append("(\n")
|
|
|
|
line = []
|
|
fnptypeline = []
|
|
|
|
if templateName:
|
|
template = allTemplates[templateName]
|
|
fnSig = template.signature
|
|
|
|
for params in fnSig.paramlist:
|
|
fnparam = fnSig.getParam(params)
|
|
wintypeName = fnparam.winType
|
|
typewName = getPalDataTypeMapping(runtimeFlavor)[wintypeName]
|
|
winCount = fnparam.count
|
|
countw = getPalDataTypeMapping(runtimeFlavor)[winCount]
|
|
|
|
|
|
if params in template.structs:
|
|
fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
|
|
|
|
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)
|
|
|
|
if params in template.structs:
|
|
line.append(fnparam.name + "_ElementSize")
|
|
line.append(", ")
|
|
|
|
line.append(fnparam.name)
|
|
line.append(",")
|
|
|
|
#remove trailing commas
|
|
if len(line) > 0:
|
|
del line[-1]
|
|
|
|
#add activity IDs
|
|
fnptypeline.append(lindent)
|
|
# source file can't have the parameter initializer
|
|
fnptypeline.append("%s ActivityId%s\n" % (getEventPipeDataTypeMapping(runtimeFlavor)["LPCGUID"], " = nullptr," if (target_cpp and (generatedFileType == "header" or generatedFileType == "header-impl")) else ","))
|
|
fnptypeline.append(lindent)
|
|
fnptypeline.append("%s RelatedActivityId" % (getEventPipeDataTypeMapping(runtimeFlavor)["LPCGUID"]))
|
|
if (target_cpp and (generatedFileType == "header" or generatedFileType == "header-impl")):
|
|
fnptypeline.append(" = nullptr")
|
|
else:
|
|
fnptypeline.append("")
|
|
|
|
fnptype.extend(fnptypeline)
|
|
fnptype.append("\n)")
|
|
if generatedFileType == "header":
|
|
fnptype.append(";\n")
|
|
fnptype.append("\n")
|
|
elif generatedFileType == "source-impl-noop":
|
|
fnptype.append("\n{ return ERROR_SUCCESS; }\n\n")
|
|
else: # source-impl
|
|
fnptype.append("\n{\n")
|
|
fnbody.append(lindent)
|
|
|
|
fnbody.append("%s status = EventPipeWriteEvent" % (getEventPipeDataTypeMapping(runtimeFlavor)["ULONG"]) + eventName + "(" + ''.join(line))
|
|
if len(line) > 0:
|
|
fnbody.append(",")
|
|
|
|
fnbody.append("ActivityId,RelatedActivityId);\n")
|
|
|
|
if user_events and runtimeFlavor.coreclr:
|
|
fnbody.append(lindent)
|
|
fnbody.append("status &= UserEventsWriteEvent" + eventName + "(" + ''.join(line))
|
|
if len(line) > 0:
|
|
fnbody.append(",")
|
|
fnbody.append("ActivityId,RelatedActivityId);\n")
|
|
|
|
if runtimeFlavor.coreclr or write_xplatheader:
|
|
fnbody.append(lindent)
|
|
fnbody.append("status &= FireEtXplat" + eventName + "(" + ''.join(line) + ");\n")
|
|
|
|
if runtimeFlavor.nativeaot:
|
|
if providerName == "Microsoft-Windows-DotNETRuntime" or providerName == "Microsoft-Windows-DotNETRuntimePrivate":
|
|
fnbody.append("#ifndef TARGET_UNIX\n")
|
|
fnbody.append(lindent)
|
|
fnbody.append("status &= ")
|
|
else:
|
|
fnbody.append("return ")
|
|
fnbody.append("FireEtXplat" + eventName + "(" + ''.join(line) + ");\n")
|
|
if providerName == "Microsoft-Windows-DotNETRuntime" or providerName == "Microsoft-Windows-DotNETRuntimePrivate":
|
|
fnbody.append("#endif\n")
|
|
|
|
fnbody.append(lindent)
|
|
fnbody.append("return status;\n")
|
|
fnbody.append("}\n\n")
|
|
|
|
clrallEvents.extend(fnptype)
|
|
if not (runtimeFlavor.nativeaot and (generatedFileType == "header" or generatedFileType == "source-impl-noop")):
|
|
clrallEvents.extend(fnbody)
|
|
|
|
return ''.join(clrallEvents)
|
|
|
|
def generateClrXplatEvents(eventNodes, allTemplates, extern, runtimeFlavor):
|
|
clrallEvents = []
|
|
for eventNode in eventNodes:
|
|
eventName = eventNode.getAttribute('symbol')
|
|
templateName = eventNode.getAttribute('template')
|
|
|
|
#generate EventEnabled
|
|
if extern: clrallEvents.append('extern "C" ')
|
|
clrallEvents.append("%s EventXplatEnabled" % (getEventPipeDataTypeMapping(runtimeFlavor)["BOOL"]))
|
|
clrallEvents.append(eventName)
|
|
clrallEvents.append("();\n")
|
|
|
|
#generate FireEtw functions
|
|
fnptype = []
|
|
fnptypeline = []
|
|
if extern: fnptype.append('extern "C" ')
|
|
fnptype.append("%s FireEtXplat" % (getEventPipeDataTypeMapping(runtimeFlavor)["ULONG"]))
|
|
fnptype.append(eventName)
|
|
fnptype.append("(\n")
|
|
|
|
if templateName:
|
|
template = allTemplates[templateName]
|
|
fnSig = template.signature
|
|
|
|
for params in fnSig.paramlist:
|
|
fnparam = fnSig.getParam(params)
|
|
wintypeName = fnparam.winType
|
|
typewName = getPalDataTypeMapping(runtimeFlavor)[wintypeName]
|
|
winCount = fnparam.count
|
|
countw = getPalDataTypeMapping(runtimeFlavor)[winCount]
|
|
|
|
|
|
if params in template.structs:
|
|
fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
|
|
|
|
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)
|
|
|
|
def generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern, target_cpp, runtimeFlavor, providerName, inclusion_list):
|
|
clrallEvents = []
|
|
for eventNode in eventNodes:
|
|
eventName = eventNode.getAttribute('symbol')
|
|
if not includeEvent(inclusion_list, providerName, eventName):
|
|
continue
|
|
|
|
templateName = eventNode.getAttribute('template')
|
|
|
|
#generate EventPipeEventEnabled and EventPipeWriteEvent functions
|
|
eventenabled = []
|
|
writeevent = []
|
|
fnptypeline = []
|
|
|
|
if extern:eventenabled.append('extern "C" ')
|
|
eventenabled.append("%s EventPipeEventEnabled" % (getEventPipeDataTypeMapping(runtimeFlavor)["BOOL"]))
|
|
eventenabled.append(eventName)
|
|
eventenabled.append("(void);\n")
|
|
|
|
if extern: writeevent.append('extern "C" ')
|
|
writeevent.append("%s EventPipeWriteEvent" % (getEventPipeDataTypeMapping(runtimeFlavor)["ULONG"]))
|
|
writeevent.append(eventName)
|
|
writeevent.append("(\n")
|
|
|
|
if templateName:
|
|
template = allTemplates[templateName]
|
|
fnSig = template.signature
|
|
|
|
for params in fnSig.paramlist:
|
|
fnparam = fnSig.getParam(params)
|
|
wintypeName = fnparam.winType
|
|
typewName = getPalDataTypeMapping(runtimeFlavor)[wintypeName]
|
|
winCount = fnparam.count
|
|
countw = getPalDataTypeMapping(runtimeFlavor)[winCount]
|
|
|
|
if params in template.structs:
|
|
fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
|
|
|
|
fnptypeline.append(lindent)
|
|
fnptypeline.append(typewName)
|
|
fnptypeline.append(countw)
|
|
fnptypeline.append(" ")
|
|
fnptypeline.append(fnparam.name)
|
|
fnptypeline.append(",\n")
|
|
|
|
fnptypeline.append(lindent)
|
|
fnptypeline.append("%s ActivityId%s\n" % (getEventPipeDataTypeMapping(runtimeFlavor)["LPCGUID"], " = nullptr," if target_cpp else ","))
|
|
fnptypeline.append(lindent)
|
|
fnptypeline.append("%s RelatedActivityId%s" % (getEventPipeDataTypeMapping(runtimeFlavor)["LPCGUID"], " = nullptr" if target_cpp else ""))
|
|
|
|
writeevent.extend(fnptypeline)
|
|
writeevent.append("\n);\n")
|
|
clrallEvents.extend(eventenabled)
|
|
clrallEvents.extend(writeevent)
|
|
|
|
return ''.join(clrallEvents)
|
|
|
|
def generateClrUserEventsWriteEvents(eventNodes, allTemplates, extern, target_cpp, runtimeFlavor, providerName, inclusion_list):
|
|
clrallEvents = []
|
|
for eventNode in eventNodes:
|
|
eventName = eventNode.getAttribute('symbol')
|
|
if not includeEvent(inclusion_list, providerName, eventName):
|
|
continue
|
|
|
|
templateName = eventNode.getAttribute('template')
|
|
|
|
#generate UserEventsEventEnabled and UserEventsWriteEvent functions
|
|
eventenabled = []
|
|
writeevent = []
|
|
fnptypeline = []
|
|
|
|
if extern:eventenabled.append('extern "C" ')
|
|
eventenabled.append("%s UserEventsEventEnabled" % (getEventPipeDataTypeMapping(runtimeFlavor)["BOOL"]))
|
|
eventenabled.append(eventName)
|
|
eventenabled.append("(void);\n")
|
|
|
|
if extern: writeevent.append('extern "C" ')
|
|
writeevent.append("%s UserEventsWriteEvent" % (getEventPipeDataTypeMapping(runtimeFlavor)["ULONG"]))
|
|
writeevent.append(eventName)
|
|
writeevent.append("(\n")
|
|
|
|
if templateName:
|
|
template = allTemplates[templateName]
|
|
fnSig = template.signature
|
|
|
|
for params in fnSig.paramlist:
|
|
fnparam = fnSig.getParam(params)
|
|
wintypeName = fnparam.winType
|
|
typewName = getPalDataTypeMapping(runtimeFlavor)[wintypeName]
|
|
winCount = fnparam.count
|
|
countw = getPalDataTypeMapping(runtimeFlavor)[winCount]
|
|
|
|
if params in template.structs:
|
|
fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
|
|
|
|
fnptypeline.append(lindent)
|
|
fnptypeline.append(typewName)
|
|
fnptypeline.append(countw)
|
|
fnptypeline.append(" ")
|
|
fnptypeline.append(fnparam.name)
|
|
fnptypeline.append(",\n")
|
|
|
|
fnptypeline.append(lindent)
|
|
fnptypeline.append("%s ActivityId%s\n" % (getEventPipeDataTypeMapping(runtimeFlavor)["LPCGUID"], " = nullptr," if target_cpp else ","))
|
|
fnptypeline.append(lindent)
|
|
fnptypeline.append("%s RelatedActivityId%s" % (getEventPipeDataTypeMapping(runtimeFlavor)["LPCGUID"], " = nullptr" if target_cpp else ""))
|
|
|
|
writeevent.extend(fnptypeline)
|
|
writeevent.append("\n);\n")
|
|
clrallEvents.extend(eventenabled)
|
|
clrallEvents.extend(writeevent)
|
|
|
|
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:
|
|
template = allTemplates[templateName]
|
|
fnSig = template.signature
|
|
|
|
for params in fnSig.paramlist:
|
|
fnparam = fnSig.getParam(params)
|
|
|
|
if params in template.structs:
|
|
line.append(fnparam.name + "_ElementSize")
|
|
line.append(", ")
|
|
|
|
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 generateEtmDummyHeader(sClrEtwAllMan,clretwdummy):
|
|
|
|
if not clretwdummy:
|
|
return
|
|
|
|
tree = DOM.parse(sClrEtwAllMan)
|
|
|
|
incDir = os.path.dirname(os.path.realpath(clretwdummy))
|
|
if not os.path.exists(incDir):
|
|
os.makedirs(incDir)
|
|
|
|
with open_for_update(clretwdummy) as Clretwdummy:
|
|
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")
|
|
|
|
def convertToLevelId(level):
|
|
if level == "win:LogAlways":
|
|
return 0
|
|
if level == "win:Critical":
|
|
return 1
|
|
if level == "win:Error":
|
|
return 2
|
|
if level == "win:Warning":
|
|
return 3
|
|
if level == "win:Informational":
|
|
return 4
|
|
if level == "win:Verbose":
|
|
return 5
|
|
raise Exception("unknown level " + level)
|
|
|
|
def getKeywordsMaskCombined(keywords, keywordsToMask):
|
|
mask = 0
|
|
for keyword in keywords.split(" "):
|
|
if keyword == "":
|
|
continue
|
|
mask |= keywordsToMask[keyword]
|
|
|
|
return mask
|
|
|
|
def updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, clrallevents, inclusion_list, generatedFileType, user_events):
|
|
is_windows = os.name == 'nt'
|
|
with open_for_update(clrallevents) as Clrallevents:
|
|
Clrallevents.write(stdprolog)
|
|
if generatedFileType=="header-impl":
|
|
if runtimeFlavor.mono:
|
|
Clrallevents.write(getCoreCLRMonoNativeAotTypeAdaptionDefines() + "\n")
|
|
if runtimeFlavor.coreclr or write_xplatheader:
|
|
Clrallevents.write('#include "clrxplatevents.h"\n')
|
|
Clrallevents.write('#include "clreventpipewriteevents.h"\n')
|
|
if user_events and runtimeFlavor.coreclr:
|
|
Clrallevents.write('#include "clrusereventswriteevents.h"\n')
|
|
elif generatedFileType == "header":
|
|
Clrallevents.write('#ifndef CLR_ETW_ALL_MAIN_H\n')
|
|
Clrallevents.write('#define CLR_ETW_ALL_MAIN_H\n\n')
|
|
elif generatedFileType == "source-impl":
|
|
Clrallevents.write('#include <common.h>\n')
|
|
Clrallevents.write('#include <PalRedhawk.h>\n')
|
|
Clrallevents.write('#include "clretwallmain.h"\n')
|
|
Clrallevents.write('#include "clreventpipewriteevents.h"\n')
|
|
if user_events and runtimeFlavor.coreclr:
|
|
Clrallevents.write('#include "clrusereventswriteevents.h"\n')
|
|
Clrallevents.write('#ifdef FEATURE_ETW\n')
|
|
Clrallevents.write('#include "ClrEtwAll.h"\n')
|
|
Clrallevents.write('#endif\n')
|
|
Clrallevents.write('\n')
|
|
elif generatedFileType == "source-impl-noop":
|
|
Clrallevents.write('#include <CommonTypes.h>\n')
|
|
Clrallevents.write('#include <CommonMacros.h>\n\n')
|
|
Clrallevents.write('#include <PalRedhawk.h>\n\n')
|
|
Clrallevents.write('#ifndef ERROR_SUCCESS\n')
|
|
Clrallevents.write('#define ERROR_SUCCESS 0L\n')
|
|
Clrallevents.write('#endif\n\n')
|
|
|
|
# define DOTNET_TRACE_CONTEXT depending on the platform
|
|
if is_windows and not runtimeFlavor.nativeaot:
|
|
Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT
|
|
if runtimeFlavor.coreclr or write_xplatheader:
|
|
Clrallevents.write(dotnet_trace_context_typedef_windows + "\n")
|
|
else:
|
|
Clrallevents.write("\n")
|
|
|
|
if not is_windows and runtimeFlavor.coreclr:
|
|
Clrallevents.write(user_events_trace_context_typedef)
|
|
|
|
if not is_windows and not write_xplatheader and not runtimeFlavor.nativeaot:
|
|
Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT
|
|
Clrallevents.write("\n")
|
|
|
|
# Hack to write etw specific information to nativeaot
|
|
for providerNode in tree.getElementsByTagName('provider'):
|
|
providerName = providerNode.getAttribute('name')
|
|
templateNodes = providerNode.getElementsByTagName('template')
|
|
allTemplates = parseTemplateNodes(templateNodes)
|
|
eventNodes = providerNode.getElementsByTagName('event')
|
|
|
|
#vm header:
|
|
Clrallevents.write(generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, write_xplatheader, providerName, inclusion_list, generatedFileType, user_events))
|
|
|
|
providerName = providerNode.getAttribute('name')
|
|
providerSymbol = providerNode.getAttribute('symbol')
|
|
|
|
eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context"
|
|
if is_windows and not (write_xplatheader or runtimeFlavor.nativeaot):
|
|
Clrallevents.write(('constexpr ' if target_cpp else 'static const ') + 'EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n')
|
|
|
|
if not is_windows and not write_xplatheader and not runtimeFlavor.nativeaot:
|
|
Clrallevents.write('__attribute__((weak)) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n')
|
|
|
|
if generatedFileType == "header":
|
|
Clrallevents.write("#endif // __CLR_ETW_ALL_MAIN_H__\n")
|
|
|
|
def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern, write_xplatheader, target_cpp, runtimeFlavor, inclusion_list, user_events):
|
|
|
|
generateEtmDummyHeader(sClrEtwAllMan,etmDummyFile)
|
|
tree = DOM.parse(sClrEtwAllMan)
|
|
|
|
if not incDir:
|
|
return
|
|
|
|
if not os.path.exists(incDir):
|
|
os.makedirs(incDir)
|
|
|
|
eventpipe_trace_context_typedef = """
|
|
#if !defined(EVENTPIPE_TRACE_CONTEXT_DEF)
|
|
#define EVENTPIPE_TRACE_CONTEXT_DEF
|
|
typedef struct _EVENTPIPE_TRACE_CONTEXT
|
|
{
|
|
const %s * Name;
|
|
%s Level;
|
|
bool IsEnabled;
|
|
%s EnabledKeywordsBitmask;
|
|
} EVENTPIPE_TRACE_CONTEXT, *PEVENTPIPE_TRACE_CONTEXT;
|
|
#endif // EVENTPIPE_TRACE_CONTEXT_DEF
|
|
""" % (getEventPipeDataTypeMapping(runtimeFlavor)["WCHAR"], getEventPipeDataTypeMapping(runtimeFlavor)["UCHAR"], getEventPipeDataTypeMapping(runtimeFlavor)["ULONGLONG"])
|
|
|
|
user_events_trace_context_typedef = """
|
|
#if !defined(USER_EVENTS_TRACE_CONTEXT_DEF)
|
|
#define USER_EVENTS_TRACE_CONTEXT_DEF
|
|
typedef struct _USER_EVENTS_TRACE_CONTEXT
|
|
{
|
|
UCHAR id;
|
|
} USER_EVENTS_TRACE_CONTEXT, *PUSER_EVENTS_TRACE_CONTEXT;
|
|
#endif // USER_EVENTS_TRACE_CONTEXT_DEF
|
|
"""
|
|
|
|
lttng_trace_context_typedef = """
|
|
#if !defined(LTTNG_TRACE_CONTEXT_DEF)
|
|
#define LTTNG_TRACE_CONTEXT_DEF
|
|
typedef struct _LTTNG_TRACE_CONTEXT
|
|
{
|
|
WCHAR const * Name;
|
|
UCHAR Level;
|
|
bool IsEnabled;
|
|
ULONGLONG EnabledKeywordsBitmask;
|
|
} LTTNG_TRACE_CONTEXT, *PLTTNG_TRACE_CONTEXT;
|
|
#endif // LTTNG_TRACE_CONTEXT_DEF
|
|
"""
|
|
|
|
dotnet_trace_context_typedef_windows = """
|
|
#if !defined(DOTNET_TRACE_CONTEXT_DEF)
|
|
#define DOTNET_TRACE_CONTEXT_DEF
|
|
typedef struct _DOTNET_TRACE_CONTEXT
|
|
{
|
|
PMCGEN_TRACE_CONTEXT EtwProvider;
|
|
EVENTPIPE_TRACE_CONTEXT EventPipeProvider;
|
|
} DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT;
|
|
#endif // DOTNET_TRACE_CONTEXT_DEF
|
|
"""
|
|
|
|
dotnet_trace_context_typedef_unix = """
|
|
#if !defined(DOTNET_TRACE_CONTEXT_DEF)
|
|
#define DOTNET_TRACE_CONTEXT_DEF
|
|
typedef struct _DOTNET_TRACE_CONTEXT
|
|
{
|
|
EVENTPIPE_TRACE_CONTEXT EventPipeProvider;
|
|
PLTTNG_TRACE_CONTEXT LttngProvider;
|
|
USER_EVENTS_TRACE_CONTEXT UserEventsProvider;
|
|
} DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT;
|
|
#endif // DOTNET_TRACE_CONTEXT_DEF
|
|
"""
|
|
|
|
is_windows = os.name == 'nt'
|
|
|
|
# Write the main source(s) for FireETW* functions
|
|
# nativeaot requires header and source file to be separated as well as a noop implementation
|
|
if runtimeFlavor.nativeaot:
|
|
updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.cpp"), inclusion_list, "source-impl", user_events)
|
|
updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.h"), inclusion_list, "header", user_events)
|
|
updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "disabledclretwallmain.cpp"), inclusion_list, "source-impl-noop", user_events)
|
|
else:
|
|
updateclreventsfile(write_xplatheader, target_cpp, runtimeFlavor, eventpipe_trace_context_typedef, dotnet_trace_context_typedef_windows, user_events_trace_context_typedef, tree, os.path.join(incDir, "clretwallmain.h"), inclusion_list, "header-impl", user_events)
|
|
|
|
if write_xplatheader:
|
|
clrproviders = os.path.join(incDir, "clrproviders.h")
|
|
with open_for_update(clrproviders) as Clrproviders:
|
|
Clrproviders.write("""
|
|
typedef struct _EVENT_DESCRIPTOR
|
|
{
|
|
int const Level;
|
|
ULONGLONG const Keyword;
|
|
} EVENT_DESCRIPTOR;
|
|
""")
|
|
if not is_windows and not runtimeFlavor.nativeaot:
|
|
Clrproviders.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT
|
|
Clrproviders.write(lttng_trace_context_typedef) # define LTTNG_TRACE_CONTEXT
|
|
Clrproviders.write(user_events_trace_context_typedef)
|
|
Clrproviders.write(dotnet_trace_context_typedef_unix + "\n")
|
|
|
|
allProviders = []
|
|
nbProviders = 0
|
|
for providerNode in tree.getElementsByTagName('provider'):
|
|
keywords = []
|
|
keywordsToMask = {}
|
|
providerName = str(providerNode.getAttribute('name'))
|
|
providerSymbol = str(providerNode.getAttribute('symbol'))
|
|
nbProviders += 1
|
|
nbKeywords = 0
|
|
if not is_windows and not runtimeFlavor.nativeaot:
|
|
eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context"
|
|
Clrproviders.write('__attribute__((weak)) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n')
|
|
lttngProviderCtxName = providerSymbol + "_LTTNG_Context"
|
|
Clrproviders.write('__attribute__((weak)) LTTNG_TRACE_CONTEXT ' + lttngProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n')
|
|
|
|
Clrproviders.write("// Keywords\n");
|
|
for keywordNode in providerNode.getElementsByTagName('keyword'):
|
|
keywordName = keywordNode.getAttribute('name')
|
|
keywordMask = keywordNode.getAttribute('mask')
|
|
keywordSymbol = keywordNode.getAttribute('symbol')
|
|
Clrproviders.write("#define " + keywordSymbol + " " + keywordMask + "\n")
|
|
|
|
keywords.append("{ \"" + keywordName + "\", " + keywordMask + " }")
|
|
keywordsToMask[keywordName] = int(keywordMask, 16)
|
|
nbKeywords += 1
|
|
|
|
for eventNode in providerNode.getElementsByTagName('event'):
|
|
levelName = eventNode.getAttribute('level')
|
|
symbolName = eventNode.getAttribute('symbol')
|
|
keywords = eventNode.getAttribute('keywords')
|
|
level = convertToLevelId(levelName)
|
|
Clrproviders.write(("constexpr " if target_cpp else "static const ") + "EVENT_DESCRIPTOR " + symbolName + " = { " + str(level) + ", " + hex(getKeywordsMaskCombined(keywords, keywordsToMask)) + " };\n")
|
|
|
|
allProviders.append("&" + providerSymbol + "_LTTNG_Context")
|
|
|
|
# define and initialize runtime providers' DOTNET_TRACE_CONTEXT depending on the platform
|
|
if not is_windows and not runtimeFlavor.nativeaot:
|
|
Clrproviders.write('#define NB_PROVIDERS ' + str(nbProviders) + '\n')
|
|
Clrproviders.write(('constexpr ' if target_cpp else 'static const ') + 'LTTNG_TRACE_CONTEXT * ALL_LTTNG_PROVIDERS_CONTEXT[NB_PROVIDERS] = { ')
|
|
Clrproviders.write(', '.join(allProviders))
|
|
Clrproviders.write(' };\n')
|
|
|
|
|
|
clreventpipewriteevents = os.path.join(incDir, "clreventpipewriteevents.h")
|
|
with open_for_update(clreventpipewriteevents) as Clreventpipewriteevents:
|
|
Clreventpipewriteevents.write(stdprolog + "\n")
|
|
|
|
for providerNode in tree.getElementsByTagName('provider'):
|
|
providerName = providerNode.getAttribute('name')
|
|
templateNodes = providerNode.getElementsByTagName('template')
|
|
allTemplates = parseTemplateNodes(templateNodes)
|
|
eventNodes = providerNode.getElementsByTagName('event')
|
|
|
|
#eventpipe: create clreventpipewriteevents.h
|
|
Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern, target_cpp, runtimeFlavor, providerName, inclusion_list) + "\n")
|
|
|
|
if user_events and runtimeFlavor.coreclr:
|
|
clrusereventswriteeventsPath = os.path.join(incDir, "clrusereventswriteevents.h")
|
|
with open_for_update(clrusereventswriteeventsPath) as clrusereventswriteevents:
|
|
clrusereventswriteevents.write(stdprolog + "\n")
|
|
|
|
for providerNode in tree.getElementsByTagName('provider'):
|
|
providerName = providerNode.getAttribute('name')
|
|
templateNodes = providerNode.getElementsByTagName('template')
|
|
allTemplates = parseTemplateNodes(templateNodes)
|
|
eventNodes = providerNode.getElementsByTagName('event')
|
|
|
|
#user_events: create clrusereventswriteevents.h
|
|
clrusereventswriteevents.write(generateClrUserEventsWriteEvents(eventNodes, allTemplates, extern, target_cpp, runtimeFlavor, providerName, inclusion_list) + "\n")
|
|
|
|
# Write secondary headers for FireEtXplat* and EventPipe* functions
|
|
if write_xplatheader:
|
|
clrxplatevents = os.path.join(incDir, "clrxplatevents.h")
|
|
with open_for_update(clrxplatevents) as Clrxplatevents:
|
|
Clrxplatevents.write(stdprolog + "\n")
|
|
|
|
for providerNode in tree.getElementsByTagName('provider'):
|
|
templateNodes = providerNode.getElementsByTagName('template')
|
|
allTemplates = parseTemplateNodes(templateNodes)
|
|
eventNodes = providerNode.getElementsByTagName('event')
|
|
|
|
#pal: create clrallevents.h
|
|
Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates, extern, runtimeFlavor) + "\n")
|
|
|
|
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 containing the description of events')
|
|
required.add_argument('--incdir', type=str, default=None,
|
|
help='full path to directory where the header files will be generated')
|
|
required.add_argument('--inc', type=str,default="",
|
|
help='full path to inclusion list')
|
|
required.add_argument('--dummy', type=str,default=None,
|
|
help='full path to file that will have dummy definitions of FireEtw functions')
|
|
required.add_argument('--runtimeflavor', type=str,default="CoreCLR",
|
|
help='runtime flavor')
|
|
required.add_argument('--nonextern', action='store_true',
|
|
help='if specified, will not generated extern function stub headers' )
|
|
required.add_argument('--noxplatheader', action='store_true',
|
|
help='if specified, will not write a generated cross-platform header' )
|
|
required.add_argument('--userevents', action='store_true',
|
|
help='if specified, will emit support for user_events' )
|
|
args, unknown = parser.parse_known_args(argv)
|
|
if unknown:
|
|
print('Unknown argument(s): ', ', '.join(unknown))
|
|
return 1
|
|
|
|
sClrEtwAllMan = args.man
|
|
incdir = args.incdir
|
|
inclusion_filename = args.inc
|
|
etmDummyFile = args.dummy
|
|
runtimeFlavor = RuntimeFlavor(args.runtimeflavor)
|
|
extern = not args.nonextern
|
|
write_xplatheader = not args.noxplatheader
|
|
user_events = args.userevents
|
|
|
|
target_cpp = True
|
|
if runtimeFlavor.mono:
|
|
extern = False
|
|
target_cpp = False
|
|
write_xplatheader = False
|
|
|
|
inclusion_list = parseInclusionList(inclusion_filename)
|
|
|
|
generatePlatformIndependentFiles(sClrEtwAllMan, incdir, etmDummyFile, extern, write_xplatheader, target_cpp, runtimeFlavor, inclusion_list, user_events)
|
|
|
|
if __name__ == '__main__':
|
|
return_code = main(sys.argv[1:])
|
|
sys.exit(return_code)
|