[Tizen] Implement detecting of sanitized libraries
[platform/upstream/coreclr.git] / src / scripts / genEventing.py
1 #
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.
5 #
6 #
7 #USAGE:
8 #Add Events: modify <root>src/vm/ClrEtwAll.man
9 #Look at the Code in  <root>/src/scripts/genLttngProvider.py for using subroutines in this file
10 #
11
12 # Python 2 compatibility
13 from __future__ import print_function
14
15 import os
16 import xml.dom.minidom as DOM
17 from utilities import open_for_update
18
19 stdprolog="""
20 // Licensed to the .NET Foundation under one or more agreements.
21 // The .NET Foundation licenses this file to you under the MIT license.
22 // See the LICENSE file in the project root for more information.
23
24 /******************************************************************
25
26 DO NOT MODIFY. AUTOGENERATED FILE.
27 This file is generated using the logic from <root>/src/scripts/genEventing.py
28
29 ******************************************************************/
30 """
31
32 lindent = "    ";
33 palDataTypeMapping ={
34         #constructed types
35         "win:null"          :" ",
36         "win:Int64"         :"const __int64",
37         "win:ULong"         :"const ULONG",
38         "win:count"         :"*",
39         "win:Struct"        :"const void",
40         #actual spec
41         "win:GUID"          :"const GUID",
42         "win:AnsiString"    :"LPCSTR",
43         "win:UnicodeString" :"PCWSTR",
44         "win:Double"        :"const double",
45         "win:Int32"         :"const signed int",
46         "win:Boolean"       :"const BOOL",
47         "win:UInt64"        :"const unsigned __int64",
48         "win:UInt32"        :"const unsigned int",
49         "win:UInt16"        :"const unsigned short",
50         "win:UInt8"         :"const unsigned char",
51         "win:Pointer"       :"const void*",
52         "win:Binary"        :"const BYTE"
53         }
54 # A Template represents an ETW template can contain 1 or more AbstractTemplates
55 # The AbstractTemplate contains FunctionSignature
56 # FunctionSignature consist of FunctionParameter representing each parameter in it's signature
57
58 def getParamSequenceSize(paramSequence, estimate):
59     total = 0
60     pointers = 0
61     for param in paramSequence:
62         if param == "win:Int64":
63             total += 8
64         elif param == "win:ULong":
65             total += 4
66         elif param == "GUID":
67             total += 16
68         elif param == "win:Double":
69             total += 8
70         elif param == "win:Int32":
71             total += 4
72         elif param == "win:Boolean":
73             total += 4
74         elif param == "win:UInt64":
75             total += 8
76         elif param == "win:UInt32":
77             total += 4
78         elif param == "win:UInt16":
79             total += 2
80         elif param == "win:UInt8":
81             total += 1
82         elif param == "win:Pointer":
83             if estimate:
84                 total += 8
85             else:
86                 pointers += 1
87         elif param == "win:Binary":
88             total += 1
89         elif estimate:
90             if param == "win:AnsiString":
91                 total += 32
92             elif param == "win:UnicodeString":
93                 total += 64
94             elif param == "win:Struct":
95                 total += 32
96         else:
97             raise Exception("Don't know size for " + param)
98
99     if estimate:
100         return total
101
102     return total, pointers
103
104
105 class Template:
106     def __repr__(self):
107         return "<Template " + self.name + ">"
108
109     def __init__(self, templateName, fnPrototypes, dependencies, structSizes, arrays):
110         self.name = templateName
111         self.signature = FunctionSignature()
112         self.structs = structSizes
113         self.arrays = arrays
114
115         for variable in fnPrototypes.paramlist:
116             for dependency in dependencies[variable]:
117                 if not self.signature.getParam(dependency):
118                     self.signature.append(dependency, fnPrototypes.getParam(dependency))
119
120     def getFnParam(self, name):
121         return self.signature.getParam(name)
122
123     @property
124     def num_params(self):
125         return len(self.signature.paramlist)
126
127     @property
128     def estimated_size(self):
129         total = getParamSequenceSize((self.getFnParam(paramName).winType for paramName in self.signature.paramlist), True)
130
131         if total < 32:
132             total = 32
133         elif total > 1024:
134             total = 1024
135
136         return total
137
138
139
140 class FunctionSignature:
141     def __repr__(self):
142         return ", ".join(self.paramlist)
143
144     def __init__(self):
145         self.LUT       = {} # dictionary of FunctionParameter
146         self.paramlist = [] # list of parameters to maintain their order in signature
147
148     def append(self,variable,fnparam):
149         self.LUT[variable] = fnparam
150         self.paramlist.append(variable)
151
152     def getParam(self,variable):
153         return self.LUT.get(variable)
154
155     def getLength(self):
156         return len(self.paramlist)
157
158 class FunctionParameter:
159     def __repr__(self):
160         return self.name
161
162     def __init__(self,winType,name,count,prop):
163         self.winType  = winType   #ETW type as given in the manifest
164         self.name     = name      #parameter name as given in the manifest
165         self.prop     = prop      #any special property as determined by the manifest and developer
166         #self.count               #indicates if the parameter is a pointer
167         if  count == "win:null":
168             self.count    = "win:null"
169         elif count or winType == "win:GUID" or count == "win:count":
170         #special case for GUIDS, consider them as structs
171             self.count    = "win:count"
172         else:
173             self.count    = "win:null"
174
175
176 def getTopLevelElementsByTagName(node,tag):
177     dataNodes = []
178     for element in node.getElementsByTagName(tag):
179         if element.parentNode == node:
180             dataNodes.append(element)
181
182     return dataNodes
183
184 ignoredXmlTemplateAttribes = frozenset(["map","outType"])
185 usedXmlTemplateAttribes    = frozenset(["name","inType","count", "length"])
186
187 def parseTemplateNodes(templateNodes):
188
189     #return values
190     allTemplates           = {}
191
192     for templateNode in templateNodes:
193         structCounts = {}
194         arrays = {}
195         templateName    = templateNode.getAttribute('tid')
196         var_Dependecies = {}
197         fnPrototypes    = FunctionSignature()
198         dataNodes       = getTopLevelElementsByTagName(templateNode,'data')
199
200         # Validate that no new attributes has been added to manifest
201         for dataNode in dataNodes:
202             nodeMap = dataNode.attributes
203             for attrib in nodeMap.values():
204                 attrib_name = attrib.name
205                 if attrib_name not in ignoredXmlTemplateAttribes and attrib_name not in usedXmlTemplateAttribes:
206                     raise ValueError('unknown attribute: '+ attrib_name + ' in template:'+ templateName)
207
208         for dataNode in dataNodes:
209             variable = dataNode.getAttribute('name')
210             wintype = dataNode.getAttribute('inType')
211
212             #count and length are the same
213             wincount  = dataNode.getAttribute('count')
214             winlength = dataNode.getAttribute('length');
215
216             var_Props = None
217             var_dependency = [variable]
218             if  winlength:
219                 if wincount:
220                     raise Exception("both count and length property found on: " + variable + "in template: " + templateName)
221                 wincount = winlength
222
223             if (wincount.isdigit() and int(wincount) ==1):
224                 wincount = ''
225
226             if  wincount:
227                 if (wincount.isdigit()):
228                     var_Props = wincount
229                 elif  fnPrototypes.getParam(wincount):
230                     var_Props = wincount
231                     var_dependency.insert(0, wincount)
232                     arrays[variable] = wincount
233
234             #construct the function signature
235
236             if  wintype == "win:GUID":
237                 var_Props = "sizeof(GUID)/sizeof(int)"
238
239             var_Dependecies[variable] = var_dependency
240             fnparam        = FunctionParameter(wintype,variable,wincount,var_Props)
241             fnPrototypes.append(variable,fnparam)
242
243         structNodes = getTopLevelElementsByTagName(templateNode,'struct')
244
245         for structToBeMarshalled in structNodes:
246             structName   = structToBeMarshalled.getAttribute('name')
247             countVarName = structToBeMarshalled.getAttribute('count')
248
249             assert(countVarName == "Count")
250             assert(countVarName in fnPrototypes.paramlist)
251             if not countVarName:
252                 raise ValueError("Struct '%s' in template '%s' does not have an attribute count." % (structName, templateName))
253
254             names = [x.attributes['name'].value for x in structToBeMarshalled.getElementsByTagName("data")]
255             types = [x.attributes['inType'].value for x in structToBeMarshalled.getElementsByTagName("data")]
256
257             structCounts[structName] = countVarName
258             var_Dependecies[structName] = [countVarName, structName]
259             fnparam_pointer = FunctionParameter("win:Struct", structName, "win:count", countVarName)
260             fnPrototypes.append(structName, fnparam_pointer)
261
262         allTemplates[templateName] = Template(templateName, fnPrototypes, var_Dependecies, structCounts, arrays)
263
264     return allTemplates
265
266 def generateClrallEvents(eventNodes,allTemplates):
267     clrallEvents = []
268     for eventNode in eventNodes:
269         eventName    = eventNode.getAttribute('symbol')
270         templateName = eventNode.getAttribute('template')
271
272         #generate EventEnabled
273         clrallEvents.append("inline BOOL EventEnabled")
274         clrallEvents.append(eventName)
275         clrallEvents.append("() {return ")
276         clrallEvents.append("EventPipeEventEnabled" + eventName + "()")
277
278         if os.name == 'posix':
279             clrallEvents.append("|| (XplatEventLogger::IsEventLoggingEnabled() && EventXplatEnabled" + eventName + "());}\n\n")
280         else:
281             clrallEvents.append(";}\n\n")
282         #generate FireEtw functions
283         fnptype     = []
284         fnbody      = []
285         fnptype.append("inline ULONG FireEtw")
286         fnptype.append(eventName)
287         fnptype.append("(\n")
288
289         line        = []
290         fnptypeline = []
291
292         if templateName:
293             template = allTemplates[templateName]
294             fnSig = template.signature
295
296             for params in fnSig.paramlist:
297                 fnparam     = fnSig.getParam(params)
298                 wintypeName = fnparam.winType
299                 typewName   = palDataTypeMapping[wintypeName]
300                 winCount    = fnparam.count
301                 countw      = palDataTypeMapping[winCount]
302
303
304                 if params in template.structs:
305                     fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
306
307                 fnptypeline.append(lindent)
308                 fnptypeline.append(typewName)
309                 fnptypeline.append(countw)
310                 fnptypeline.append(" ")
311                 fnptypeline.append(fnparam.name)
312                 fnptypeline.append(",\n")
313
314             #fnsignature
315             for params in fnSig.paramlist:
316                 fnparam     = fnSig.getParam(params)
317
318                 if params in template.structs:
319                     line.append(fnparam.name + "_ElementSize")
320                     line.append(", ")
321
322                 line.append(fnparam.name)
323                 line.append(",")
324
325             #remove trailing commas
326             if len(line) > 0:
327                 del line[-1]
328             if len(fnptypeline) > 0:
329                 del fnptypeline[-1]
330
331         fnptype.extend(fnptypeline)
332         fnptype.append("\n)\n{\n")
333         fnbody.append(lindent)
334         fnbody.append("ULONG status = EventPipeWriteEvent" + eventName + "(" + ''.join(line) + ");\n")
335         fnbody.append(lindent)
336         fnbody.append("status &= FireEtXplat" + eventName + "(" + ''.join(line) + ");\n")
337         fnbody.append(lindent)
338         fnbody.append("return status;\n")
339         fnbody.append("}\n\n")
340
341         clrallEvents.extend(fnptype)
342         clrallEvents.extend(fnbody)
343
344     return ''.join(clrallEvents)
345
346 def generateClrXplatEvents(eventNodes, allTemplates, extern):
347     clrallEvents = []
348     for eventNode in eventNodes:
349         eventName    = eventNode.getAttribute('symbol')
350         templateName = eventNode.getAttribute('template')
351
352         #generate EventEnabled
353         if extern: clrallEvents.append('extern "C" ')
354         clrallEvents.append("BOOL EventXplatEnabled")
355         clrallEvents.append(eventName)
356         clrallEvents.append("();\n")
357
358         #generate FireEtw functions
359         fnptype     = []
360         fnptypeline = []
361         if extern: fnptype.append('extern "C" ')
362         fnptype.append("ULONG FireEtXplat")
363         fnptype.append(eventName)
364         fnptype.append("(\n")
365
366         if templateName:
367             template = allTemplates[templateName]
368             fnSig = template.signature
369
370             for params in fnSig.paramlist:
371                 fnparam     = fnSig.getParam(params)
372                 wintypeName = fnparam.winType
373                 typewName   = palDataTypeMapping[wintypeName]
374                 winCount    = fnparam.count
375                 countw      = palDataTypeMapping[winCount]
376
377
378                 if params in template.structs:
379                     fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
380
381                 fnptypeline.append(lindent)
382                 fnptypeline.append(typewName)
383                 fnptypeline.append(countw)
384                 fnptypeline.append(" ")
385                 fnptypeline.append(fnparam.name)
386                 fnptypeline.append(",\n")
387
388             #remove trailing commas
389             if len(fnptypeline) > 0:
390                 del fnptypeline[-1]
391
392         fnptype.extend(fnptypeline)
393         fnptype.append("\n);\n")
394         clrallEvents.extend(fnptype)
395
396     return ''.join(clrallEvents)
397
398 def generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern):
399     clrallEvents = []
400     for eventNode in eventNodes:
401         eventName    = eventNode.getAttribute('symbol')
402         templateName = eventNode.getAttribute('template')
403
404         #generate EventPipeEventEnabled and EventPipeWriteEvent functions
405         eventenabled = []
406         writeevent   = []
407         fnptypeline  = []
408
409         if extern:eventenabled.append('extern "C" ')
410         eventenabled.append("BOOL EventPipeEventEnabled")
411         eventenabled.append(eventName)
412         eventenabled.append("();\n")
413
414         if extern: writeevent.append('extern "C" ')
415         writeevent.append("ULONG EventPipeWriteEvent")
416         writeevent.append(eventName)
417         writeevent.append("(\n")
418
419         if templateName:
420             template = allTemplates[templateName]
421             fnSig    = template.signature
422
423             for params in fnSig.paramlist:
424                 fnparam     = fnSig.getParam(params)
425                 wintypeName = fnparam.winType
426                 typewName   = palDataTypeMapping[wintypeName]
427                 winCount    = fnparam.count
428                 countw      = palDataTypeMapping[winCount]
429
430                 if params in template.structs:
431                     fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
432
433                 fnptypeline.append(lindent)
434                 fnptypeline.append(typewName)
435                 fnptypeline.append(countw)
436                 fnptypeline.append(" ")
437                 fnptypeline.append(fnparam.name)
438                 fnptypeline.append(",\n")
439
440             #remove trailing commas
441             if len(fnptypeline) > 0:
442                 del fnptypeline[-1]
443
444         writeevent.extend(fnptypeline)
445         writeevent.append("\n);\n")
446         clrallEvents.extend(eventenabled)
447         clrallEvents.extend(writeevent)
448
449     return ''.join(clrallEvents)
450
451 #generates the dummy header file which is used by the VM as entry point to the logging Functions
452 def generateclrEtwDummy(eventNodes,allTemplates):
453     clretmEvents = []
454     for eventNode in eventNodes:
455         eventName    = eventNode.getAttribute('symbol')
456         templateName = eventNode.getAttribute('template')
457
458         fnptype     = []
459         #generate FireEtw functions
460         fnptype.append("#define FireEtw")
461         fnptype.append(eventName)
462         fnptype.append("(");
463         line        = []
464         if templateName:
465             template = allTemplates[templateName]
466             fnSig = template.signature
467
468             for params in fnSig.paramlist:
469                 fnparam     = fnSig.getParam(params)
470
471                 if params in template.structs:
472                     line.append(fnparam.name + "_ElementSize")
473                     line.append(", ")
474
475                 line.append(fnparam.name)
476                 line.append(", ")
477
478             #remove trailing commas
479             if len(line) > 0:
480                 del line[-1]
481
482         fnptype.extend(line)
483         fnptype.append(") 0\n")
484         clretmEvents.extend(fnptype)
485
486     return ''.join(clretmEvents)
487
488 def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy):
489
490     if not clretwdummy:
491         return
492
493     tree           = DOM.parse(sClrEtwAllMan)
494
495     incDir = os.path.dirname(os.path.realpath(clretwdummy))
496     if not os.path.exists(incDir):
497         os.makedirs(incDir)
498
499     with open_for_update(clretwdummy) as Clretwdummy:
500         Clretwdummy.write(stdprolog + "\n")
501
502         for providerNode in tree.getElementsByTagName('provider'):
503             templateNodes = providerNode.getElementsByTagName('template')
504             allTemplates  = parseTemplateNodes(templateNodes)
505             eventNodes = providerNode.getElementsByTagName('event')
506             #pal: create etmdummy.h
507             Clretwdummy.write(generateclrEtwDummy(eventNodes, allTemplates) + "\n")
508
509 def convertToLevelId(level):
510     if level == "win:LogAlways":
511        return 0
512     if level == "win:Critical":
513        return 1
514     if level == "win:Error":
515        return 2
516     if level == "win:Warning":
517        return 3
518     if level == "win:Informational":
519        return 4
520     if level == "win:Verbose":
521        return 5
522     raise Exception("unknown level " + level)
523
524 def getKeywordsMaskCombined(keywords, keywordsToMask):
525     mask = 0
526     for keyword in keywords.split(" "):
527        if keyword == "":
528           continue
529        mask |= keywordsToMask[keyword]
530
531     return mask
532
533 def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern, write_xplatheader):
534
535     generateEtmDummyHeader(sClrEtwAllMan,etmDummyFile)
536     tree           = DOM.parse(sClrEtwAllMan)
537
538     if not incDir:
539         return
540
541     if not os.path.exists(incDir):
542         os.makedirs(incDir)
543
544     eventpipe_trace_context_typedef = """
545 #if !defined(EVENTPIPE_TRACE_CONTEXT_DEF)
546 #define EVENTPIPE_TRACE_CONTEXT_DEF
547 typedef struct _EVENTPIPE_TRACE_CONTEXT
548 {
549     WCHAR const * Name;
550     UCHAR Level;
551     bool IsEnabled;
552     ULONGLONG EnabledKeywordsBitmask;
553 } EVENTPIPE_TRACE_CONTEXT, *PEVENTPIPE_TRACE_CONTEXT;
554 #endif // EVENTPIPE_TRACE_CONTEXT_DEF
555 """
556
557     lttng_trace_context_typedef = """
558 #if !defined(LTTNG_TRACE_CONTEXT_DEF)
559 #define LTTNG_TRACE_CONTEXT_DEF
560 typedef struct _LTTNG_TRACE_CONTEXT
561 {
562     WCHAR const * Name;
563     UCHAR Level;
564     bool IsEnabled;
565     ULONGLONG EnabledKeywordsBitmask;
566 } LTTNG_TRACE_CONTEXT, *PLTTNG_TRACE_CONTEXT;
567 #endif // LTTNG_TRACE_CONTEXT_DEF
568 """
569
570     dotnet_trace_context_typedef_windows = """
571 #if !defined(DOTNET_TRACE_CONTEXT_DEF)
572 #define DOTNET_TRACE_CONTEXT_DEF
573 typedef struct _DOTNET_TRACE_CONTEXT
574 {
575     PMCGEN_TRACE_CONTEXT EtwProvider;
576     EVENTPIPE_TRACE_CONTEXT EventPipeProvider;
577 } DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT;
578 #endif // DOTNET_TRACE_CONTEXT_DEF
579 """
580
581     dotnet_trace_context_typedef_unix = """
582 #if !defined(DOTNET_TRACE_CONTEXT_DEF)
583 #define DOTNET_TRACE_CONTEXT_DEF
584 typedef struct _DOTNET_TRACE_CONTEXT
585 {
586     EVENTPIPE_TRACE_CONTEXT EventPipeProvider;
587     PLTTNG_TRACE_CONTEXT LttngProvider;
588 } DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT;
589 #endif // DOTNET_TRACE_CONTEXT_DEF
590 """
591
592     trace_context_instdef_windows = """
593 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context = { &MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context };
594
595 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context = { &MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context };
596
597 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context = { &MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context };
598
599 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context = { &MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_Context, MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context };
600 """
601
602     trace_context_instdef_unix = """
603 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_LTTNG_Context };
604
605 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_LTTNG_Context };
606
607 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_LTTNG_Context };
608
609 EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_LTTNG_Context };
610 """
611
612     # Write the main header for FireETW* functions
613     clrallevents = os.path.join(incDir, "clretwallmain.h")
614     is_windows = os.name == 'nt'
615     with open_for_update(clrallevents) as Clrallevents:
616         Clrallevents.write(stdprolog)
617         Clrallevents.write("""
618 #include "clrxplatevents.h"
619 #include "clreventpipewriteevents.h"
620
621 """)
622
623         # define DOTNET_TRACE_CONTEXT depending on the platform
624         if is_windows:
625             Clrallevents.write(eventpipe_trace_context_typedef)  # define EVENTPIPE_TRACE_CONTEXT
626             Clrallevents.write(dotnet_trace_context_typedef_windows)
627
628         for providerNode in tree.getElementsByTagName('provider'):
629             templateNodes = providerNode.getElementsByTagName('template')
630             allTemplates  = parseTemplateNodes(templateNodes)
631             eventNodes = providerNode.getElementsByTagName('event')
632
633             #vm header:
634             Clrallevents.write(generateClrallEvents(eventNodes, allTemplates) + "\n")
635
636             providerName = providerNode.getAttribute('name')
637             providerSymbol = providerNode.getAttribute('symbol')
638
639             if is_windows:
640                 eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context"
641                 Clrallevents.write('EXTERN_C __declspec(selectany) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n')
642
643         # define and initialize runtime providers' DOTNET_TRACE_CONTEXT depending on the platform
644         if is_windows:
645             Clrallevents.write(trace_context_instdef_windows)
646
647     if write_xplatheader:
648         clrproviders = os.path.join(incDir, "clrproviders.h")
649         with open_for_update(clrproviders) as Clrproviders:
650             Clrproviders.write("""
651     typedef struct _EVENT_DESCRIPTOR
652     {
653         int const Level;
654         ULONGLONG const Keyword;
655     } EVENT_DESCRIPTOR;
656     """)
657
658             if not is_windows:
659                 Clrproviders.write(eventpipe_trace_context_typedef)  # define EVENTPIPE_TRACE_CONTEXT
660                 Clrproviders.write(lttng_trace_context_typedef)  # define LTTNG_TRACE_CONTEXT
661                 Clrproviders.write(dotnet_trace_context_typedef_unix)
662
663             allProviders = []
664             nbProviders = 0
665             for providerNode in tree.getElementsByTagName('provider'):
666                 keywords = []
667                 keywordsToMask = {}
668                 providerName = str(providerNode.getAttribute('name'))
669                 providerSymbol = str(providerNode.getAttribute('symbol'))
670                 nbProviders += 1
671                 nbKeywords = 0
672                 if not is_windows:
673                     eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context"
674                     Clrproviders.write('EXTERN_C __declspec(selectany) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n')
675                     lttngProviderCtxName = providerSymbol + "_LTTNG_Context"
676                     Clrproviders.write('EXTERN_C __declspec(selectany) LTTNG_TRACE_CONTEXT ' + lttngProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n')
677
678                 Clrproviders.write("// Keywords\n");
679                 for keywordNode in providerNode.getElementsByTagName('keyword'):
680                     keywordName = keywordNode.getAttribute('name')
681                     keywordMask = keywordNode.getAttribute('mask')
682                     keywordSymbol = keywordNode.getAttribute('symbol')
683                     Clrproviders.write("#define " + keywordSymbol + " " + keywordMask + "\n")
684
685                     keywords.append("{ \"" + keywordName + "\", " + keywordMask + " }")
686                     keywordsToMask[keywordName] = int(keywordMask, 16)
687                     nbKeywords += 1
688
689                 for eventNode in providerNode.getElementsByTagName('event'):
690                     levelName = eventNode.getAttribute('level')
691                     symbolName = eventNode.getAttribute('symbol')
692                     keywords = eventNode.getAttribute('keywords')
693                     level = convertToLevelId(levelName)
694                     Clrproviders.write("EXTERN_C __declspec(selectany) EVENT_DESCRIPTOR const " + symbolName + " = { " + str(level) + ", " + hex(getKeywordsMaskCombined(keywords, keywordsToMask)) + " };\n")
695
696                 allProviders.append("&" + providerSymbol + "_LTTNG_Context")
697
698             # define and initialize runtime providers' DOTNET_TRACE_CONTEXT depending on the platform
699             if not is_windows:
700                 Clrproviders.write('#define NB_PROVIDERS ' + str(nbProviders) + '\n')
701                 Clrproviders.write('EXTERN_C __declspec(selectany) LTTNG_TRACE_CONTEXT * const ALL_LTTNG_PROVIDERS_CONTEXT[NB_PROVIDERS] = { ')
702                 Clrproviders.write(', '.join(allProviders))
703                 Clrproviders.write(' };\n')
704                 Clrproviders.write(trace_context_instdef_unix)
705
706
707     clreventpipewriteevents = os.path.join(incDir, "clreventpipewriteevents.h")
708     with open_for_update(clreventpipewriteevents) as Clreventpipewriteevents:
709         Clreventpipewriteevents.write(stdprolog + "\n")
710
711         for providerNode in tree.getElementsByTagName('provider'):
712             templateNodes = providerNode.getElementsByTagName('template')
713             allTemplates  = parseTemplateNodes(templateNodes)
714             eventNodes = providerNode.getElementsByTagName('event')
715
716             #eventpipe: create clreventpipewriteevents.h
717             Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern) + "\n")
718                 
719     # Write secondary headers for FireEtXplat* and EventPipe* functions
720     if write_xplatheader:
721         clrxplatevents = os.path.join(incDir, "clrxplatevents.h")
722         with open_for_update(clrxplatevents) as Clrxplatevents:
723             Clrxplatevents.write(stdprolog + "\n")
724
725             for providerNode in tree.getElementsByTagName('provider'):
726                 templateNodes = providerNode.getElementsByTagName('template')
727                 allTemplates  = parseTemplateNodes(templateNodes)
728                 eventNodes = providerNode.getElementsByTagName('event')
729
730                 #pal: create clrallevents.h
731                 Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates, extern) + "\n")
732
733 import argparse
734 import sys
735
736 def main(argv):
737
738     #parse the command line
739     parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng logging mechanism")
740
741     required = parser.add_argument_group('required arguments')
742     required.add_argument('--man',  type=str, required=True,
743                                     help='full path to manifest containig the description of events')
744     required.add_argument('--inc',  type=str, default=None,
745                                     help='full path to directory where the header files will be generated')
746     required.add_argument('--dummy',  type=str,default=None,
747                                     help='full path to file that will have dummy definitions of FireEtw functions')
748     required.add_argument('--nonextern', action='store_true',
749                                     help='if specified, will not generated extern function stub headers' )
750     required.add_argument('--noxplatheader', action='store_true',
751                                     help='if specified, will not write a generated cross-platform header' )
752     args, unknown = parser.parse_known_args(argv)
753     if unknown:
754         print('Unknown argument(s): ', ', '.join(unknown))
755         return 1
756
757     sClrEtwAllMan     = args.man
758     incdir            = args.inc
759     etmDummyFile      = args.dummy
760     extern            = not args.nonextern
761     write_xplatheader = not args.noxplatheader
762
763     generatePlatformIndependentFiles(sClrEtwAllMan, incdir, etmDummyFile, extern, write_xplatheader)
764
765 if __name__ == '__main__':
766     return_code = main(sys.argv[1:])
767     sys.exit(return_code)