diff options
author | Lee Culver <leculver@microsoft.com> | 2016-05-20 13:26:19 -0700 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2016-05-20 13:26:19 -0700 |
commit | 92c2f926bd5eceea22211609ca63e27ff6a2be96 (patch) | |
tree | 9835d6838af1e1cab542a1b2a553e6821b2eddec /src/scripts | |
parent | f38ec53d628bc0ab157678864fbddf255ad6591b (diff) | |
download | coreclr-92c2f926bd5eceea22211609ca63e27ff6a2be96.tar.gz coreclr-92c2f926bd5eceea22211609ca63e27ff6a2be96.tar.bz2 coreclr-92c2f926bd5eceea22211609ca63e27ff6a2be96.zip |
Fix multiple LTTng issues (#5068)
- Only emit LTTng events when LTTng is enabled. We now use the tracepoint_enabled macro to check if an event is enabled...when the version of lttng is installed that supports it.
- Unsplit LTTng events. Previously we split LTTng events when they exceeded the field limit of LTTng. Now we emit those events as a raw byte array so that it matches their windows ETW counterparts byte-for-byte.
- Emit any event with a struct or embedded array as a raw byte array too. The structure of memory that LTTng emits is incompatible with our ETW parsing. Changing events with struct/array fields greatly simplifies the parsing of events.
Diffstat (limited to 'src/scripts')
-rw-r--r-- | src/scripts/genXplatEventing.py | 356 | ||||
-rw-r--r-- | src/scripts/genXplatLttng.py | 672 |
2 files changed, 611 insertions, 417 deletions
diff --git a/src/scripts/genXplatEventing.py b/src/scripts/genXplatEventing.py index cfa5c8de6c..6c6498d3de 100644 --- a/src/scripts/genXplatEventing.py +++ b/src/scripts/genXplatEventing.py @@ -1,4 +1,4 @@ -# +# ## Licensed to the .NET Foundation under one or more agreements. ## The .NET Foundation licenses this file to you under the MIT license. ## See the LICENSE file in the project root for more information. @@ -65,36 +65,91 @@ palDataTypeMapping ={ # 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 +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) - def __init__(self,templateName): - self.template = templateName - self.allAbstractTemplateTypes = [] # list of AbstractTemplateNames - self.allAbstractTemplateLUT = {} #dictionary of AbstractTemplate + @property + def num_params(self): + return len(self.signature.paramlist) - def append(self,abstractTemplateName,abstractFnFrame): - self.allAbstractTemplateTypes.append(abstractTemplateName) - self.allAbstractTemplateLUT[abstractTemplateName] = AbstractTemplate(abstractTemplateName,abstractFnFrame) + @property + def estimated_size(self): + total = getParamSequenceSize((self.getFnParam(paramName).winType for paramName in self.signature.paramlist), True) - def getFnFrame(self,abstractTemplateName): - return self.allAbstractTemplateLUT[abstractTemplateName].AbstractFnFrame + if total < 32: + total = 32 + elif total > 1024: + total = 1024 + + return total - 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 __repr__(self): + return ", ".join(self.paramlist) def __init__(self): self.LUT = {} # dictionary of FunctionParameter @@ -111,6 +166,8 @@ class FunctionSignature: 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 @@ -125,59 +182,15 @@ class FunctionParameter: else: self.count = "win:null" -def getTopLevelElementsByTagName(Node,tag): - dataNodes = [] - for element in Node.getElementsByTagName(tag): - if element.parentNode == Node: +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 = frozenset(["map","outType"]) usedXmlTemplateAttribes = frozenset(["name","inType","count", "length"]) @@ -187,8 +200,9 @@ def parseTemplateNodes(templateNodes): allTemplates = {} for templateNode in templateNodes: - - template = templateNode.getAttribute('tid') + structCounts = {} + arrays = {} + templateName = templateNode.getAttribute('tid') var_Dependecies = {} fnPrototypes = FunctionSignature() dataNodes = getTopLevelElementsByTagName(templateNode,'data') @@ -199,11 +213,11 @@ def parseTemplateNodes(templateNodes): 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) + raise ValueError('unknown attribute: '+ attrib_name + ' in template:'+ templateName) for dataNode in dataNodes: - variable = dataNode.getAttribute('name') - wintype = dataNode.getAttribute('inType') + variable = dataNode.getAttribute('name') + wintype = dataNode.getAttribute('inType') #count and length are the same wincount = dataNode.getAttribute('count') @@ -213,7 +227,7 @@ def parseTemplateNodes(templateNodes): var_dependency = [variable] if winlength: if wincount: - raise Exception("both count and length property found on: " + variable + "in template: " + template) + raise Exception("both count and length property found on: " + variable + "in template: " + templateName) wincount = winlength if (wincount.isdigit() and int(wincount) ==1): @@ -224,7 +238,8 @@ def parseTemplateNodes(templateNodes): var_Props = wincount elif fnPrototypes.getParam(wincount): var_Props = wincount - var_dependency.insert(0,wincount) + var_dependency.insert(0, wincount) + arrays[variable] = wincount #construct the function signature @@ -237,30 +252,24 @@ def parseTemplateNodes(templateNodes): 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') + structName = structToBeMarshalled.getAttribute('name') countVarName = structToBeMarshalled.getAttribute('count') + assert(countVarName == "Count") + assert(countVarName in fnPrototypes.paramlist) if not countVarName: - raise ValueError('Struct '+ structname+ ' in template:'+ template + 'does not have an attribute count') + 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")] - var_Props = countVarName + "*" + struct_len + "/sizeof(int)" - var_Dependecies[struct_len] = [struct_len] - var_Dependecies[struct_pointer] = [countVarName,struct_len,struct_pointer] + structCounts[structName] = countVarName + var_Dependecies[structName] = [countVarName, structName] + fnparam_pointer = FunctionParameter("win:Struct", structName, "win:count", countVarName) + fnPrototypes.append(structName, fnparam_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) + allTemplates[templateName] = Template(templateName, fnPrototypes, var_Dependecies, structCounts, arrays) return allTemplates @@ -289,27 +298,37 @@ def generateClrallEvents(eventNodes,allTemplates): fnptypeline = [] if templateName: - for subTemplate in allTemplates[templateName].allAbstractTemplateTypes: - fnSig = allTemplates[templateName].getFnFrame(subTemplate) + template = allTemplates[templateName] + fnSig = template.signature + + for params in fnSig.paramlist: + fnparam = fnSig.getParam(params) + wintypeName = fnparam.winType + typewName = palDataTypeMapping[wintypeName] + winCount = fnparam.count + countw = palDataTypeMapping[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(", ") - 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(",") + line.append(fnparam.name) + line.append(",") #remove trailing commas if len(line) > 0: @@ -350,21 +369,26 @@ def generateClrXplatEvents(eventNodes, allTemplates): 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") + template = allTemplates[templateName] + fnSig = template.signature + + for params in fnSig.paramlist: + fnparam = fnSig.getParam(params) + wintypeName = fnparam.winType + typewName = palDataTypeMapping[wintypeName] + winCount = fnparam.count + countw = palDataTypeMapping[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: @@ -390,14 +414,19 @@ def generateclrEtwDummy(eventNodes,allTemplates): fnptype.append("("); line = [] if templateName: - for subTemplate in allTemplates[templateName].allAbstractTemplateTypes: - fnSig = allTemplates[templateName].getFnFrame(subTemplate) + template = allTemplates[templateName] + fnSig = template.signature - for params in fnSig.paramlist: - fnparam = fnSig.getParam(params) - line.append(fnparam.name) + 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] @@ -423,34 +452,37 @@ def generateClralltestEvents(sClrEtwAllMan): 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' + if templateName: + template = allTemplates[templateName] + fnSig = template.signature + + for params in fnSig.paramlist: + if params in template.structs: + line.append("sizeof(Struct1),\n") + + 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.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") + if fnparam.count == "win:count": + line.append("&") + + argline = fnparam.winType.replace(":","_") + + line.append(argline) + line.append(",\n") #remove trailing commas if len(line) > 0: diff --git a/src/scripts/genXplatLttng.py b/src/scripts/genXplatLttng.py index d343b122ff..a334d8a267 100644 --- a/src/scripts/genXplatLttng.py +++ b/src/scripts/genXplatLttng.py @@ -1,4 +1,4 @@ -## +## ## Licensed to the .NET Foundation under one or more agreements. ## The .NET Foundation licenses this file to you under the MIT license. ## See the LICENSE file in the project root for more information. @@ -81,7 +81,7 @@ lttngDataTypeMapping ={ "win:Int64" :"const __int64", "win:ULong" :"const ULONG", "win:count" :"*", - "win:Struct" :"const int", + "win:Struct" :"const BYTE *", #actual spec "win:GUID" :"const int", "win:AnsiString" :"const char*", @@ -118,100 +118,127 @@ ctfDataTypeMapping ={ "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] +MAX_LTTNG_ARGS = 9 + +def shouldPackTemplate(template): + return template.num_params > MAX_LTTNG_ARGS or len(template.structs) > 0 or len(template.arrays) > 0 + +def generateArgList(template): + header = "TP_ARGS( \\\n" + footer = ")\n" + + if "MethodILToNative" in template.name: + pass + + if shouldPackTemplate(template): + args = " const unsigned int, length, \\\n" + args += " const char *, __data__ \\\n" + + else: + fnSig = template.signature + args = [] + for params in fnSig.paramlist: + fnparam = fnSig.getParam(params) + wintypeName = fnparam.winType + typewName = lttngDataTypeMapping[wintypeName] + winCount = fnparam.count + countw = lttngDataTypeMapping[winCount] + + arg = " " + typewName + if countw != " ": + arg += countw + arg += ", " + fnparam.name + args.append(arg) + args = ", \\\n".join(args) + " \\\n" + + return header + args + footer + + +def generateFieldList(template): + header = " " + " TP_FIELDS(\n" + footer = "\n )\n)\n" + + if shouldPackTemplate(template): + field_list = " ctf_integer(ULONG, length, length)\n" + field_list += " ctf_sequence(char, __data__, __data__, ULONG, length)" + + else: + fnSig = template.signature + field_list = [] + for params in fnSig.paramlist: + fnparam = fnSig.getParam(params) + wintypeName = fnparam.winType + winCount = fnparam.count + countw = lttngDataTypeMapping[winCount] + typewName = lttngDataTypeMapping[wintypeName].replace("const ","") + + field_body = None + 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 + field_body = ", ".join((typewName, varname, varname, "size_t", sizeofseq)) + + else: + ctf_type = ctfDataTypeMapping[wintypeName] + if ctf_type == "ctf_string": + field_body = ", ".join((varname, varname)) + + elif ctf_type == "ctf_integer" or ctf_type == "ctf_float": + field_body = ", ".join((typewName, varname, varname)) + + elif ctf_type == "ctf_sequence": + raise Exception("ctf_sequence needs to have its memory expilicitly laid out") - tp_args_param.append(" ") - tp_args_param.append(typewName) - if countw != " ": - tp_args_param.append(countw) + else: + raise Exception("no such ctf intrinsic called: " + ctf_type) - tp_args_param.append(" ,") - tp_args_param.append(fnparam.name) - tp_args_param.append(",\\\n") + field_list.append(" %s(%s)" % (ctf_type, field_body)) - 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 + field_list = "\n".join(field_list) - 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 ","") + return header + field_list + footer - tp_fields_body = [] - ctf_type = None - varname = fnparam.name +def generateLttngHeader(providerName, allTemplates, eventNodes): + lTTngHdr = [] + for templateName in allTemplates: + template = allTemplates[templateName] + fnSig = allTemplates[templateName].signature + + lTTngHdr.append("\n#define " + templateName + "_TRACEPOINT_ARGS \\\n") - 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) +#TP_ARGS + tp_args = generateArgList(template) + lTTngHdr.append(tp_args) - 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) +#TP_EVENT_CLASS + lTTngHdr.append("TRACEPOINT_EVENT_CLASS(\n") + lTTngHdr.append(" " + providerName + ",\n") + lTTngHdr.append(" " + templateName + ",\n") + lTTngHdr.append(" " + templateName + "_TRACEPOINT_ARGS,\n") + +#TP_FIELDS + tp_fields = generateFieldList(template) + lTTngHdr.append(tp_fields) # Macro for defining event instance - lTTngHdr.append("\n#define " + subTemplate) - lTTngHdr.append("""T_TRACEPOINT_INSTANCE(name) \\ + lTTngHdr.append("\n#define " + templateName) + 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)") + lTTngHdr.append(" "+providerName + ",\\\n") + lTTngHdr.append(" " + templateName + ",\\\n") + lTTngHdr.append(" name ,\\\n") + lTTngHdr.append(" " + templateName + "_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(" " + providerName + ",\n") lTTngHdr.append(" emptyTemplate ,\n") lTTngHdr.append(""" TP_ARGS(), TP_FIELDS() @@ -219,7 +246,7 @@ TRACEPOINT_EVENT_INSTANCE(\\ #define T_TRACEPOINT_INSTANCE(name) \\ TRACEPOINT_EVENT_INSTANCE(\\ """) - lTTngHdr.append(" " +providerName + ",\\\n") + lTTngHdr.append(" " + providerName + ",\\\n") lTTngHdr.append(" emptyTemplate,\\\n") lTTngHdr.append(""" name ,\\ @@ -228,6 +255,7 @@ TRACEPOINT_EVENT_INSTANCE(\\ #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'); @@ -239,12 +267,10 @@ TRACEPOINT_EVENT_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") + subevent = templateName.replace(templateName,'') + lTTngHdr.append(templateName) + lTTngHdr.append("T_TRACEPOINT_INSTANCE(") + lTTngHdr.append(eventName + subevent + ")\n") lTTngHdr.append("\n#endif /* LTTNG_CORECLR_H") lTTngHdr.append(providerName + " */\n") @@ -252,16 +278,128 @@ TRACEPOINT_EVENT_INSTANCE(\\ return ''.join(lTTngHdr) -def generateLttngTpProvider(providerName,eventNodes,allTemplates): + +def generateMethodBody(template, providerName, eventName): + #emit code to init variables convert unicode to ansi string + result = [] + fnSig = template.signature + + for paramName in fnSig.paramlist: + fnparam = fnSig.getParam(paramName) + paramname = fnparam.name + + if fnparam.winType == "win:UnicodeString": + result.append(" INT " + paramname + "_path_size = -1;\n") + result.append(" PathCharString " + paramname + "_PS;\n") + result.append(" INT " + paramname + "_full_name_path_size") + result.append(" = (PAL_wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n") + result.append(" CHAR* " + paramname + "_full_name = ") + result.append(paramname + "_PS.OpenStringBuffer(" + paramname + "_full_name_path_size );\n") + result.append(" if (" + paramname + "_full_name == NULL )") + result.append(" { return ERROR_WRITE_FAULT; }\n") + + result.append("\n") + + #emit tracepoints + fnSig = template.signature + + if not shouldPackTemplate(template): + linefnbody = [" do_tracepoint(%s,\n %s" % (providerName, eventName)] + + for params in fnSig.paramlist: + fnparam = fnSig.getParam(params) + wintypeName = fnparam.winType + winCount = fnparam.count + paramname = fnparam.name + ctf_type = ctfDataTypeMapping.get(winCount) + + line = " " + 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 + + result.append(" " + paramname+ "_path_size = WideCharToMultiByte( CP_ACP, 0, ") + result.append(paramname + ", -1, ") + result.append(paramname + "_full_name, ") + result.append(paramname + "_full_name_path_size, NULL, NULL );\n") + + result.append(" _ASSERTE(" +paramname+ "_path_size < " ) + result.append(paramname + "_full_name_path_size );\n ") + + result.append(paramname + "_PS.CloseBuffer(" + paramname + "_path_size );\n") + result.append(" if( " + paramname + "_path_size == 0 ){ return ERROR_INVALID_PARAMETER; }\n") + + line += paramname + "_full_name" + linefnbody.append(line) + continue + + elif ctf_type == "ctf_sequence" or wintypeName == "win:Pointer": + line += "(" + lttngDataTypeMapping[wintypeName] + if not lttngDataTypeMapping[winCount] == " ": + line += lttngDataTypeMapping[winCount] + + line += ") " + linefnbody.append(line + paramname) + + else: + linefnbody.append(line + paramname) + + linefnbody = ",\n".join(linefnbody) + ");\n" + result.append(linefnbody) + return ''.join(result) + + else: + header = """ + char stackBuffer[%s]; + char *buffer = stackBuffer; + int offset = 0; + int size = %s; + bool fixedBuffer = true; + + bool success = true; +""" % (template.estimated_size, template.estimated_size) + footer = """ + if (!fixedBuffer) + delete[] buffer; +""" + pack_list = [] + for paramName in fnSig.paramlist: + parameter = fnSig.getParam(paramName) + + if paramName in template.structs: + pack_list.append(" success &= WriteToBuffer((const BYTE *)%s, (int)%s_ElementSize * (int)%s, buffer, offset, size, fixedBuffer);" % (paramName, paramName, parameter.prop)) + elif paramName in template.arrays: + pack_list.append(" success &= WriteToBuffer((const BYTE *)%s, sizeof(%s) * (int)%s, buffer, offset, size, fixedBuffer);" % (paramName, lttngDataTypeMapping[parameter.winType], parameter.prop)) + elif parameter.winType == "win:GUID": + pack_list.append(" success &= WriteToBuffer(*%s, buffer, offset, size, fixedBuffer);" % (parameter.name,)) + else: + pack_list.append(" success &= WriteToBuffer(%s, buffer, offset, size, fixedBuffer);" % (parameter.name,)) + + code = "\n".join(pack_list) + "\n\n" + tracepoint = """ if (!success) + { + if (!fixedBuffer) + delete[] buffer; + return ERROR_WRITE_FAULT; + } + + do_tracepoint(%s, %s, offset, buffer);\n""" % (providerName, eventName) + + return header + code + tracepoint + footer + + + + + +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") + lTTngImpl.append("extern \"C\" BOOL EventXplatEnabled%s(){ return tracepoint_enabled(%s, %s); }\n\n" % (eventName, providerName, eventName)) #generate FireEtw functions fnptype = [] linefnptype = [] @@ -269,128 +407,53 @@ def generateLttngTpProvider(providerName,eventNodes,allTemplates): 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") + template = allTemplates[templateName] + else: + template = None + + if template: + fnSig = template.signature + for paramName in fnSig.paramlist: + fnparam = fnSig.getParam(paramName) + wintypeName = fnparam.winType + typewName = palDataTypeMapping[wintypeName] + winCount = fnparam.count + countw = palDataTypeMapping[winCount] + + if paramName in template.structs: + linefnptype.append("%sint %s_ElementSize,\n" % (lindent, paramName)) + + linefnptype.append(lindent) + linefnptype.append(typewName) + if countw != " ": + linefnptype.append(countw) + + linefnptype.append(" ") + linefnptype.append(fnparam.name) + linefnptype.append(",\n") if len(linefnptype) > 0 : del linefnptype[-1] fnptype.extend(linefnptype) - fnptype.append("\n)\n") - fnptype.append("{\n ULONG Error = ERROR_WRITE_FAULT;\n") + fnptype.append(")\n{\n") lTTngImpl.extend(fnptype) -#start of fn body - lTTngImpl.append(" if (!EventXplatEnabled") - lTTngImpl.append(eventName) - lTTngImpl.append("()){ return ERROR_SUCCESS;}\n") + #start of fn body + lTTngImpl.append(" if (!EventXplatEnabled%s())\n" % (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(" PathCharString " + paramname + "_PS;\n") - lTTngImpl.append(" INT " + paramname + "_full_name_path_size") - lTTngImpl.append(" = (PAL_wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n") - lTTngImpl.append(" CHAR* " + paramname + "_full_name = ") - lTTngImpl.append(paramname + "_PS.OpenStringBuffer(" + paramname + "_full_name_path_size );\n") - lTTngImpl.append(" if (" + paramname + "_full_name == NULL )") - lTTngImpl.append(" { return ERROR_WRITE_FAULT; }\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+ "_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(paramname + "_PS.CloseBuffer(" + paramname + "_path_size );\n") - lTTngImpl.append(" if( " + paramname + "_path_size == 0 ){ return ERROR_INVALID_PARAMETER; }\n") - - - 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") + if template: + result = generateMethodBody(template, providerName, eventName) + lTTngImpl.append(result) - lTTngImpl.extend(linefnbody) - lTTngImpl.append(" Error = ERROR_SUCCESS;\n") + lTTngImpl.append("\n return ERROR_SUCCESS;\n}\n\n") + return ''.join(lTTngImpl) - lTTngImpl.append("\nreturn Error;\n}\n") - return ''.join(lTTngImpl) def generateLttngFiles(etwmanifest,eventprovider_directory): @@ -414,80 +477,152 @@ def generateLttngFiles(etwmanifest,eventprovider_directory): os.makedirs(eventprovider_directory + tracepointprovider_directory) #Top level Cmake - topCmake = open(eventprovider_directory + "CMakeLists.txt", 'w') - topCmake.write(stdprolog_cmake + "\n") - topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2) + with open(eventprovider_directory + "CMakeLists.txt", 'w') as topCmake: + topCmake.write(stdprolog_cmake + "\n") + topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2) - project(eventprovider) + project(eventprovider) - set(CMAKE_INCLUDE_CURRENT_DIR ON) + 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 -""") + add_definitions(-DPAL_STDCPP_COMPAT=1) + include_directories(${COREPAL_SOURCE_DIR}/inc/rt) + include_directories(lttng) - for providerNode in tree.getElementsByTagName('provider'): - providerName = providerNode.getAttribute('name') - providerName = providerName.replace("Windows-",'') - providerName = providerName.replace("Microsoft-",'') + add_library(eventprovider + STATIC + """) - providerName_File = providerName.replace('-','') - providerName_File = providerName_File.lower() + for providerNode in tree.getElementsByTagName('provider'): + providerName = providerNode.getAttribute('name') + providerName = providerName.replace("Windows-",'') + providerName = providerName.replace("Microsoft-",'') - topCmake.write(' "'+ lttngevntprovPre + providerName_File + ".cpp" + '"\n') + providerName_File = providerName.replace('-','') + providerName_File = providerName_File.lower() - topCmake.write(""") - add_subdirectory(tracepointprovider) + topCmake.write(' "%s%s.cpp"\n' % (lttngevntprovPre, providerName_File)) + + topCmake.write(' "%shelpers.cpp"\n' % (lttngevntprovPre,)) + topCmake.write(""") + add_subdirectory(tracepointprovider) - # Install the static eventprovider library - install(TARGETS eventprovider DESTINATION lib) - """) - topCmake.close() + # Install the static eventprovider library + install(TARGETS eventprovider DESTINATION lib) + """) #TracepointProvider Cmake - tracepointprovider_Cmake = open(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt", 'w') + with open(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt", 'w') as tracepointprovider_Cmake: + tracepointprovider_Cmake.write(stdprolog_cmake + "\n") + tracepointprovider_Cmake.write("""cmake_minimum_required(VERSION 2.8.12.2) - tracepointprovider_Cmake.write(stdprolog_cmake + "\n") - tracepointprovider_Cmake.write("""cmake_minimum_required(VERSION 2.8.12.2) + project(coreclrtraceptprovider) - project(coreclrtraceptprovider) + set(CMAKE_INCLUDE_CURRENT_DIR ON) - 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_definitions(-DPAL_STDCPP_COMPAT=1) - include_directories(${COREPAL_SOURCE_DIR}/inc/rt) - include_directories(../lttng/) - add_compile_options(-fPIC) + add_library(coreclrtraceptprovider + SHARED + """) - add_library(coreclrtraceptprovider - SHARED - """) + for providerNode in tree.getElementsByTagName('provider'): + providerName = providerNode.getAttribute('name') + providerName = providerName.replace("Windows-",'') + providerName = providerName.replace("Microsoft-",'') - 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_File = providerName.replace('-','') - providerName_File = providerName_File.lower() + tracepointprovider_Cmake.write(' "../'+ lttngevntprovTpPre + providerName_File +".cpp" + '"\n') - tracepointprovider_Cmake.write(' "../'+ lttngevntprovTpPre + providerName_File +".cpp" + '"\n') + tracepointprovider_Cmake.write(""" ) - tracepointprovider_Cmake.write(""" ) + target_link_libraries(coreclrtraceptprovider + -llttng-ust + ) - target_link_libraries(coreclrtraceptprovider - -llttng-ust - ) + # Install the static coreclrtraceptprovider library + install_clr(coreclrtraceptprovider) + """) - # Install the static coreclrtraceptprovider library - install_clr(coreclrtraceptprovider) - """) - tracepointprovider_Cmake.close() + with open(eventprovider_directory + lttng_directory + "/eventprovhelpers.cpp", 'w') as helper: + helper.write(""" +#include "palrt.h" +#include "pal.h" +#include "stdlib.h" +#include "pal_mstypes.h" +#include "pal_error.h" +#include <new> +#include <memory.h> + +bool ResizeBuffer(char *&buffer, int& size, int currLen, int newSize, bool &fixedBuffer) +{ + newSize *= 1.5; + _ASSERTE(newSize > size); // check for overflow + + if (newSize < 32) + newSize = 32; + + char *newBuffer = new char[newSize]; + + memcpy(newBuffer, buffer, currLen); + + if (!fixedBuffer) + delete[] buffer; + + buffer = newBuffer; + size = newSize; + fixedBuffer = false; + + return true; +} + +bool WriteToBuffer(const BYTE *src, int len, char *&buffer, int& offset, int& size, bool &fixedBuffer) +{ + if (offset + len) + { + if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, src, len); + offset += len; + return true; +} + +bool WriteToBuffer(PCWSTR str, char *&buffer, int& offset, int& size, bool &fixedBuffer) +{ + int byteCount = (PAL_wcslen(str) + 1) * sizeof(*str); + + if (offset + byteCount) + { + if (!ResizeBuffer(buffer, size, offset, size + byteCount, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, str, byteCount); + offset += byteCount; + return true; +} + +bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool &fixedBuffer) +{ + int len = strlen(str) + 1; + if (offset + len) + { + if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, str, len); + offset += len; + return true; +}""") # Generate Lttng specific instrumentation for providerNode in tree.getElementsByTagName('provider'): @@ -552,6 +687,33 @@ def generateLttngFiles(etwmanifest,eventprovider_directory): """) lTTngImpl.write("#include \"" + lttngevntheadershortname + "\"\n\n") + lTTngImpl.write("""#ifndef tracepoint_enabled +#define tracepoint_enabled(provider, name) TRUE +#define do_tracepoint tracepoint +#endif + + +bool ResizeBuffer(char *&buffer, int& size, int currLen, int newSize, bool &fixedBuffer); +bool WriteToBuffer(PCWSTR str, char *&buffer, int& offset, int& size, bool &fixedBuffer); +bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool &fixedBuffer); +bool WriteToBuffer(const BYTE *src, int len, char *&buffer, int& offset, int& size, bool &fixedBuffer); + +template <typename T> +bool WriteToBuffer(const T &value, char *&buffer, int& offset, int& size, bool &fixedBuffer) +{ + if (sizeof(T) + offset > size) + { + if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer)) + return false; + } + + *(T *)(buffer + offset) = value; + offset += sizeof(T); + return true; +} + +""") + templateNodes = providerNode.getElementsByTagName('template') eventNodes = providerNode.getElementsByTagName('event') |