diff options
Diffstat (limited to 'src/scripts/genXplatLttng.py')
-rw-r--r-- | src/scripts/genXplatLttng.py | 600 |
1 files changed, 600 insertions, 0 deletions
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) + |