2 ## Licensed to the .NET Foundation under one or more agreements.
3 ## The .NET Foundation licenses this file to you under the MIT license.
4 ## See the LICENSE file in the project root for more information.
6 ## Sample LTTng Instrumentation code that is generated:
9 ## #define GCFinalizersEnd_TRACEPOINT_ARGS \
11 ## const unsigned int ,Count\
13 ##TRACEPOINT_EVENT_CLASS(
16 ## GCFinalizersEnd_TRACEPOINT_ARGS,
18 ## ctf_integer(unsigned int, Count, Count)
24 ##extern "C" BOOL EventXplatEnabledGCFinalizersEnd(){ return TRUE;}
25 ##extern "C" ULONG FireEtXplatGCFinalizersEnd(
26 ## const unsigned int Count
29 ## ULONG Error = ERROR_WRITE_FAULT;
30 ## if (!EventXplatEnabledGCFinalizersEnd()){ return ERROR_SUCCESS;}
38 ## Error = ERROR_SUCCESS;
43 ###define GCFinalizersEndT_TRACEPOINT_INSTANCE(name) \
44 ##TRACEPOINT_EVENT_INSTANCE(\
48 ## GCFinalizersEnd_TRACEPOINT_ARGS \
53 from genEventing import *
54 from utilities import open_for_update
57 // Licensed to the .NET Foundation under one or more agreements.
58 // The .NET Foundation licenses this file to you under the MIT license.
59 // See the LICENSE file in the project root for more information.
61 /******************************************************************
63 DO NOT MODIFY. AUTOGENERATED FILE.
64 This file is generated using the logic from <root>/src/scripts/genLttngProvider.py
66 ******************************************************************/
69 specialCaseSizes = { "BulkType" : { "Values" : "Values_ElementSize" }, "GCBulkRootCCW" : { "Values" : "Values_ElementSize" }, "GCBulkRCW" : { "Values" : "Values_ElementSize" }, "GCBulkRootStaticVar" : { "Values" : "Values_ElementSize" } }
71 lttngDataTypeMapping ={
74 "win:Int64" :"const __int64",
75 "win:ULong" :"const ULONG",
77 "win:Struct" :"const BYTE *",
79 "win:GUID" :"const int",
80 "win:AnsiString" :"const char*",
81 "win:UnicodeString" :"const char*",
82 "win:Double" :"const double",
83 "win:Int32" :"const signed int",
84 "win:Boolean" :"const BOOL",
85 "win:UInt64" :"const unsigned __int64",
86 "win:UInt32" :"const unsigned int",
87 "win:UInt16" :"const unsigned short",
88 "win:UInt8" :"const unsigned char",
89 "win:Pointer" :"const size_t",
90 "win:Binary" :"const BYTE"
95 "win:Int64" :"ctf_integer",
96 "win:ULong" :"ctf_integer",
97 "win:count" :"ctf_sequence",
98 "win:Struct" :"ctf_sequence",
100 "win:GUID" :"ctf_sequence",
101 "win:AnsiString" :"ctf_string",
102 "win:UnicodeString" :"ctf_string",
103 "win:Double" :"ctf_float",
104 "win:Int32" :"ctf_integer",
105 "win:Boolean" :"ctf_integer",
106 "win:UInt64" :"ctf_integer",
107 "win:UInt32" :"ctf_integer",
108 "win:UInt16" :"ctf_integer",
109 "win:UInt8" :"ctf_integer", #actually a character
110 "win:Pointer" :"ctf_integer",
111 "win:Binary" :"ctf_sequence"
116 def shouldPackTemplate(template):
117 return template.num_params > MAX_LTTNG_ARGS or len(template.structs) > 0 or len(template.arrays) > 0
119 def generateArgList(template):
120 header = "TP_ARGS( \\\n"
123 if "MethodILToNative" in template.name:
126 if shouldPackTemplate(template):
127 args = " const unsigned int, length, \\\n"
128 args += " const char *, __data__ \\\n"
131 fnSig = template.signature
133 for params in fnSig.paramlist:
134 fnparam = fnSig.getParam(params)
135 wintypeName = fnparam.winType
136 typewName = lttngDataTypeMapping[wintypeName]
137 winCount = fnparam.count
138 countw = lttngDataTypeMapping[winCount]
140 arg = " " + typewName
143 arg += ", " + fnparam.name
145 args = ", \\\n".join(args) + " \\\n"
147 return header + args + footer
150 def generateFieldList(template):
151 header = " " + " TP_FIELDS(\n"
154 if shouldPackTemplate(template):
155 field_list = " ctf_integer(ULONG, length, length)\n"
156 field_list += " ctf_sequence(char, __data__, __data__, ULONG, length)"
159 fnSig = template.signature
161 for params in fnSig.paramlist:
162 fnparam = fnSig.getParam(params)
163 wintypeName = fnparam.winType
164 winCount = fnparam.count
165 countw = lttngDataTypeMapping[winCount]
166 typewName = lttngDataTypeMapping[wintypeName].replace("const ","")
170 varname = fnparam.name
173 #this is an explicit struct treat as a sequence
174 ctf_type = "ctf_sequence"
175 sizeofseq = fnparam.prop
176 field_body = ", ".join((typewName, varname, varname, "size_t", sizeofseq))
179 ctf_type = ctfDataTypeMapping[wintypeName]
180 if ctf_type == "ctf_string":
181 field_body = ", ".join((varname, varname))
183 elif ctf_type == "ctf_integer" or ctf_type == "ctf_float":
184 field_body = ", ".join((typewName, varname, varname))
186 elif ctf_type == "ctf_sequence":
187 raise Exception("ctf_sequence needs to have its memory expilicitly laid out")
190 raise Exception("no such ctf intrinsic called: " + ctf_type)
192 field_list.append(" %s(%s)" % (ctf_type, field_body))
194 field_list = "\n".join(field_list)
196 return header + field_list + footer
198 def generateLttngHeader(providerName, allTemplates, eventNodes):
200 for templateName in allTemplates:
201 template = allTemplates[templateName]
202 fnSig = allTemplates[templateName].signature
204 lTTngHdr.append("\n#define " + templateName + "_TRACEPOINT_ARGS \\\n")
207 tp_args = generateArgList(template)
208 lTTngHdr.append(tp_args)
211 lTTngHdr.append("TRACEPOINT_EVENT_CLASS(\n")
212 lTTngHdr.append(" " + providerName + ",\n")
213 lTTngHdr.append(" " + templateName + ",\n")
214 lTTngHdr.append(" " + templateName + "_TRACEPOINT_ARGS,\n")
217 tp_fields = generateFieldList(template)
218 lTTngHdr.append(tp_fields)
220 # Macro for defining event instance
221 lTTngHdr.append("\n#define " + templateName)
222 lTTngHdr.append("""T_TRACEPOINT_INSTANCE(name) \\
223 TRACEPOINT_EVENT_INSTANCE(\\
225 lTTngHdr.append(" "+providerName + ",\\\n")
226 lTTngHdr.append(" " + templateName + ",\\\n")
227 lTTngHdr.append(" name ,\\\n")
228 lTTngHdr.append(" " + templateName + "_TRACEPOINT_ARGS \\\n)")
232 #add an empty template node to just specify the event name in the event stream
233 lTTngHdr.append("\n\nTRACEPOINT_EVENT_CLASS(\n")
234 lTTngHdr.append(" " + providerName + ",\n")
235 lTTngHdr.append(" emptyTemplate ,\n")
236 lTTngHdr.append(""" TP_ARGS(),
239 #define T_TRACEPOINT_INSTANCE(name) \\
240 TRACEPOINT_EVENT_INSTANCE(\\
242 lTTngHdr.append(" " + providerName + ",\\\n")
243 lTTngHdr.append(" emptyTemplate,\\\n")
245 lTTngHdr.append(""" name ,\\
248 #end of empty template
249 # create the event instance in headers
250 lTTngHdr.append("\n")
252 for eventNode in eventNodes:
253 eventName = eventNode.getAttribute('symbol');
254 templateName = eventNode.getAttribute('template');
257 raise Exception(eventNode + " event does not have a symbol")
259 lTTngHdr.append("T_TRACEPOINT_INSTANCE(")
260 lTTngHdr.append(eventName +")\n")
263 subevent = templateName.replace(templateName,'')
264 lTTngHdr.append(templateName)
265 lTTngHdr.append("T_TRACEPOINT_INSTANCE(")
266 lTTngHdr.append(eventName + subevent + ")\n")
268 lTTngHdr.append("\n#endif /* LTTNG_CORECLR_H")
269 lTTngHdr.append(providerName + " */\n")
270 lTTngHdr.append("#include <lttng/tracepoint-event.h>")
272 return ''.join(lTTngHdr)
275 def generateMethodBody(template, providerName, eventName):
276 #emit code to init variables convert unicode to ansi string
280 return "\n do_tracepoint(%s, %s);\n" % (providerName, eventName)
282 fnSig = template.signature
284 for paramName in fnSig.paramlist:
285 fnparam = fnSig.getParam(paramName)
286 paramname = fnparam.name
288 if fnparam.winType == "win:UnicodeString":
289 result.append(" INT " + paramname + "_path_size = -1;\n")
290 result.append(" PathCharString " + paramname + "_PS;\n")
291 result.append(" INT " + paramname + "_full_name_path_size")
292 result.append(" = (wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n")
293 result.append(" CHAR* " + paramname + "_full_name = ")
294 result.append(paramname + "_PS.OpenStringBuffer(" + paramname + "_full_name_path_size );\n")
295 result.append(" if (" + paramname + "_full_name == NULL )")
296 result.append(" { return ERROR_WRITE_FAULT; }\n")
301 fnSig = template.signature
303 if not shouldPackTemplate(template):
304 linefnbody = [" do_tracepoint(%s,\n %s" % (providerName, eventName)]
306 for params in fnSig.paramlist:
307 fnparam = fnSig.getParam(params)
308 wintypeName = fnparam.winType
309 winCount = fnparam.count
310 paramname = fnparam.name
311 ctf_type = ctfDataTypeMapping.get(winCount)
315 ctf_type = ctfDataTypeMapping[wintypeName]
317 if ctf_type == "ctf_string" and wintypeName == "win:UnicodeString":
318 #emit code to convert unicode to ansi string
320 result.append(" " + paramname+ "_path_size = WideCharToMultiByte( CP_ACP, 0, ")
321 result.append(paramname + ", -1, ")
322 result.append(paramname + "_full_name, ")
323 result.append(paramname + "_full_name_path_size, NULL, NULL );\n")
325 result.append(" _ASSERTE(" +paramname+ "_path_size < " )
326 result.append(paramname + "_full_name_path_size );\n ")
328 result.append(paramname + "_PS.CloseBuffer(" + paramname + "_path_size );\n")
329 result.append(" if( " + paramname + "_path_size == 0 ){ return ERROR_INVALID_PARAMETER; }\n")
331 line += paramname + "_full_name"
332 linefnbody.append(line)
335 elif ctf_type == "ctf_sequence" or wintypeName == "win:Pointer":
336 line += "(" + lttngDataTypeMapping[wintypeName]
337 if not lttngDataTypeMapping[winCount] == " ":
338 line += lttngDataTypeMapping[winCount]
341 linefnbody.append(line + paramname)
344 linefnbody.append(line + paramname)
346 linefnbody = ",\n".join(linefnbody) + ");\n"
347 result.append(linefnbody)
348 return ''.join(result)
352 char stackBuffer[%s];
353 char *buffer = stackBuffer;
356 bool fixedBuffer = true;
359 """ % (template.estimated_size, template.estimated_size)
366 for paramName in fnSig.paramlist:
367 parameter = fnSig.getParam(paramName)
369 if paramName in template.structs:
370 size = "(int)%s_ElementSize * (int)%s" % (paramName, parameter.prop)
371 if template.name in specialCaseSizes and paramName in specialCaseSizes[template.name]:
372 size = "(int)(%s)" % specialCaseSizes[template.name][paramName]
373 pack_list.append(" success &= WriteToBuffer((const BYTE *)%s, %s, buffer, offset, size, fixedBuffer);" % (paramName, size))
374 elif paramName in template.arrays:
375 size = "sizeof(%s) * (int)%s" % (lttngDataTypeMapping[parameter.winType], parameter.prop)
376 if template.name in specialCaseSizes and paramName in specialCaseSizes[template.name]:
377 size = "(int)(%s)" % specialCaseSizes[template.name][paramName]
378 pack_list.append(" success &= WriteToBuffer((const BYTE *)%s, %s, buffer, offset, size, fixedBuffer);" % (paramName, size))
379 elif parameter.winType == "win:GUID":
380 pack_list.append(" success &= WriteToBuffer(*%s, buffer, offset, size, fixedBuffer);" % (parameter.name,))
382 pack_list.append(" success &= WriteToBuffer(%s, buffer, offset, size, fixedBuffer);" % (parameter.name,))
384 code = "\n".join(pack_list) + "\n\n"
385 tracepoint = """ if (!success)
389 return ERROR_WRITE_FAULT;
392 do_tracepoint(%s, %s, offset, buffer);\n""" % (providerName, eventName)
394 return header + code + tracepoint + footer
400 def generateLttngTpProvider(providerName, eventNodes, allTemplates):
402 for eventNode in eventNodes:
403 eventName = eventNode.getAttribute('symbol')
404 templateName = eventNode.getAttribute('template')
405 #generate EventXplatEnabled
406 lTTngImpl.append("extern \"C\" BOOL EventXplatEnabled%s(){ return tracepoint_enabled(%s, %s); }\n\n" % (eventName, providerName, eventName))
407 #generate FireEtw functions
410 fnptype.append("extern \"C\" ULONG FireEtXplat")
411 fnptype.append(eventName)
412 fnptype.append("(\n")
416 template = allTemplates[templateName]
421 fnSig = template.signature
422 for paramName in fnSig.paramlist:
423 fnparam = fnSig.getParam(paramName)
424 wintypeName = fnparam.winType
425 typewName = palDataTypeMapping[wintypeName]
426 winCount = fnparam.count
427 countw = palDataTypeMapping[winCount]
429 if paramName in template.structs:
430 linefnptype.append("%sint %s_ElementSize,\n" % (lindent, paramName))
432 linefnptype.append(lindent)
433 linefnptype.append(typewName)
435 linefnptype.append(countw)
437 linefnptype.append(" ")
438 linefnptype.append(fnparam.name)
439 linefnptype.append(",\n")
441 if len(linefnptype) > 0 :
444 fnptype.extend(linefnptype)
445 fnptype.append(")\n{\n")
446 lTTngImpl.extend(fnptype)
449 lTTngImpl.append(" if (!EventXplatEnabled%s())\n" % (eventName,))
450 lTTngImpl.append(" return ERROR_SUCCESS;\n")
452 result = generateMethodBody(template, providerName, eventName)
453 lTTngImpl.append(result)
455 lTTngImpl.append("\n return ERROR_SUCCESS;\n}\n\n")
457 return ''.join(lTTngImpl)
461 def generateLttngFiles(etwmanifest,eventprovider_directory, dryRun):
463 eventprovider_directory = eventprovider_directory + "/"
464 tree = DOM.parse(etwmanifest)
467 tracepointprovider_directory = "tracepointprovider"
468 lttng_directory = "lttng"
470 lttngevntprovPre = lttng_directory + "/eventprov"
471 lttngevntprovTpPre = lttng_directory + "/traceptprov"
473 if not os.path.exists(eventprovider_directory):
474 os.makedirs(eventprovider_directory)
476 if not os.path.exists(eventprovider_directory + lttng_directory):
477 os.makedirs(eventprovider_directory + lttng_directory)
479 if not os.path.exists(eventprovider_directory + tracepointprovider_directory):
480 os.makedirs(eventprovider_directory + tracepointprovider_directory)
482 # Generate Lttng specific instrumentation
483 for providerNode in tree.getElementsByTagName('provider'):
485 providerName = providerNode.getAttribute('name')
486 providerName = providerName.replace("Windows-",'')
487 providerName = providerName.replace("Microsoft-",'')
489 providerName_File = providerName.replace('-','')
490 providerName_File = providerName_File.lower()
491 providerName = providerName.replace('-','_')
493 lttngevntheadershortname = "tp" + providerName_File +".h"
494 lttngevntheader = eventprovider_directory + "lttng/" + lttngevntheadershortname
495 lttngevntprov = eventprovider_directory + lttngevntprovPre + providerName_File + ".cpp"
496 lttngevntprovTp = eventprovider_directory + lttngevntprovTpPre + providerName_File +".cpp"
498 templateNodes = providerNode.getElementsByTagName('template')
499 eventNodes = providerNode.getElementsByTagName('event')
500 allTemplates = parseTemplateNodes(templateNodes)
503 print(lttngevntheader)
505 print(lttngevntprovTp)
507 with open_for_update(lttngevntheader) as lttnghdr_file:
508 lttnghdr_file.write(stdprolog + "\n")
509 lttnghdr_file.write("""
513 #undef TRACEPOINT_PROVIDER
517 lttnghdr_file.write("#define TRACEPOINT_PROVIDER " + providerName + "\n")
518 lttnghdr_file.write("""
520 #undef TRACEPOINT_INCLUDE
523 lttnghdr_file.write("#define TRACEPOINT_INCLUDE \"./" + lttngevntheadershortname + "\"\n\n")
525 lttnghdr_file.write("#if !defined(LTTNG_CORECLR_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n")
526 lttnghdr_file.write("#define LTTNG_CORECLR_H" + providerName + "\n")
528 lttnghdr_file.write("\n#include <lttng/tracepoint.h>\n\n")
530 lttnghdr_file.write(generateLttngHeader(providerName,allTemplates,eventNodes) + "\n")
532 with open_for_update(lttngevntprov) as lttngimpl_file:
533 lttngimpl_file.write(stdprolog + "\n")
534 lttngimpl_file.write("""
535 #define TRACEPOINT_DEFINE
536 #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
539 #include "pal_mstypes.h"
540 #include "pal_error.h"
542 #define PAL_free free
543 #define PAL_realloc realloc
544 #include "pal/stackstring.hpp"
546 lttngimpl_file.write("#include \"" + lttngevntheadershortname + "\"\n\n")
548 lttngimpl_file.write("""#ifndef tracepoint_enabled
550 extern "C" bool XplatEventLoggerIsEnabled();
552 #define tracepoint_enabled(provider, name) XplatEventLoggerIsEnabled()
553 #define do_tracepoint tracepoint
556 #define wcslen PAL_wcslen
558 bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer);
559 bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
560 bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
561 bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
563 template <typename T>
564 bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
566 if (sizeof(T) + offset > size)
568 if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer))
572 memcpy(buffer + offset, (char *)&value, sizeof(T));
578 lttngimpl_file.write(generateLttngTpProvider(providerName,eventNodes,allTemplates) + "\n")
580 with open_for_update(lttngevntprovTp) as tpimpl_file:
581 tpimpl_file.write(stdprolog + "\n")
583 tpimpl_file.write("\n#define TRACEPOINT_CREATE_PROBES\n")
585 tpimpl_file.write("#include \"./"+lttngevntheadershortname + "\"\n")
592 #parse the command line
593 parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng logging mechanism")
595 required = parser.add_argument_group('required arguments')
596 required.add_argument('--man', type=str, required=True,
597 help='full path to manifest containig the description of events')
598 required.add_argument('--intermediate', type=str, required=True,
599 help='full path to eventprovider intermediate directory')
600 required.add_argument('--dry-run', action='store_true',
601 help='if specified, will output the names of the generated files instead of generating the files' )
602 args, unknown = parser.parse_known_args(argv)
604 print('Unknown argument(s): ', ', '.join(unknown))
607 sClrEtwAllMan = args.man
608 intermediate = args.intermediate
609 dryRun = args.dry_run
611 generateLttngFiles(sClrEtwAllMan,intermediate, dryRun)
613 if __name__ == '__main__':
614 return_code = main(sys.argv[1:])
615 sys.exit(return_code)