lttng.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. #-------------------------------------------------------------------------------------------------------
  2. # Copyright (C) Microsoft. All rights reserved.
  3. # Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. #-------------------------------------------------------------------------------------------------------
  5. import xml.dom.minidom as DOM
  6. lttngDataTypeMapping = {
  7. "win:null" :" ",
  8. "win:Int64" :"const __int64",
  9. "win:ULong" :"const unsigned long",
  10. "win:count" :"*",
  11. "win:Struct" :"const char *",
  12. "win:GUID" :"const int",
  13. "win:AnsiString" :"const char*",
  14. "win:UnicodeString" :"const char*",
  15. "win:Double" :"const double",
  16. "win:Int32" :"const signed int",
  17. "win:HexInt32" :"const signed int",
  18. "win:Boolean" :"const bool",
  19. "win:UInt64" :"const unsigned __int64",
  20. "win:UInt32" :"const unsigned int",
  21. "win:UInt16" :"const unsigned short",
  22. "win:UInt8" :"const unsigned char",
  23. "win:Int8" :"const char",
  24. "win:Pointer" :"const uintptr_t",
  25. "win:Binary" :"const char"
  26. }
  27. ctfDataTypeMapping = {
  28. "win:Int64" :"ctf_integer",
  29. "win:HexInt64" :"ctf_integer_hex",
  30. "win:ULong" :"ctf_integer",
  31. "win:count" :"ctf_sequence",
  32. "win:Struct" :"ctf_sequence",
  33. "win:GUID" :"ctf_sequence",
  34. "win:AnsiString" :"ctf_string",
  35. "win:UnicodeString" :"ctf_string",
  36. "win:Double" :"ctf_float",
  37. "win:Int32" :"ctf_integer",
  38. "win:HexInt32" :"ctf_integer_hex",
  39. "win:Boolean" :"ctf_integer",
  40. "win:UInt64" :"ctf_integer",
  41. "win:UInt32" :"ctf_integer",
  42. "win:UInt16" :"ctf_integer",
  43. "win:HexInt16" :"ctf_integer_hex",
  44. "win:UInt8" :"ctf_integer", #actually a character
  45. "win:Int8" :"ctf_integer", #actually a character
  46. "win:Pointer" :"ctf_integer",
  47. "win:Binary" :"ctf_sequence",
  48. "xs:string" :"ctf_string",
  49. "xs:unsignedLong" :"ctf_integer",
  50. "xs:unsignedInt" :"ctf_integer"
  51. }
  52. palDataTypeMapping ={
  53. "win:null" :" ",
  54. "win:Int64" :"const __int64",
  55. "win:ULong" :"const unsigned long",
  56. "win:count" :"*",
  57. "win:Struct" :"const void",
  58. "win:GUID" :"const GUID",
  59. "win:AnsiString" :"LPCSTR",
  60. "win:UnicodeString" :"PCWSTR",
  61. "win:Double" :"const double",
  62. "win:Int32" :"const signed int",
  63. "win:HexInt32" :"const signed int",
  64. "win:Boolean" :"const bool",
  65. "win:UInt64" :"const unsigned __int64",
  66. "win:UInt32" :"const unsigned int",
  67. "win:UInt16" :"const unsigned short",
  68. "win:UInt8" :"const unsigned char",
  69. "win:Int8" :"const char",
  70. "win:Pointer" :"const void*",
  71. "win:Binary" :"const char"
  72. }
  73. MAX_LTTNG_ARGS = 10
  74. def getParamSequenceSize(paramSequence, estimate):
  75. total = 0
  76. pointers =0
  77. for param in paramSequence:
  78. if param in ["win:Int64", "win:UInt64", "win:Double"]:
  79. total += 8
  80. elif param in ["win:ULong", "win:Int32", "win:Boolean",]:
  81. total += 4
  82. elif param == "GUID":
  83. total += 16
  84. elif param in ["win:UInt16"]:
  85. total += 2
  86. elif param in ["win:Uint8", "win:Binary"]:
  87. total += 1
  88. elif param == "win:Pointer":
  89. if estimate:
  90. total += 8
  91. else:
  92. pointers += 1
  93. elif estimate:
  94. if param in ["win:AnsiString", "win:Struct"]:
  95. total += 32
  96. elif param in ["win:UnicodeString"]:
  97. total += 64
  98. else:
  99. raise Exception ("Don't know size of " + param)
  100. if estimate:
  101. return total
  102. return total, pointers
  103. class Template:
  104. def __repr__(self):
  105. return "<Template " + self.name + " />"
  106. def __init__(self, name, prototypes, dependencies, structCounts, arrayCounts):
  107. self.name = name
  108. self.signature = FunctionSignature()
  109. self.structCounts = structCounts
  110. self.arrayCounts = arrayCounts
  111. for variable in prototypes.paramList:
  112. for dependency in dependencies[variable]:
  113. if not self.signature.getParam(dependency):
  114. self.signature.append(dependency, prototypes.getParam(dependency))
  115. @property
  116. def num_params(self):
  117. return len(self.signature.paramList)
  118. def getParam(self, name):
  119. return self.signature.getParam(name)
  120. @property
  121. def estimatedSize(self):
  122. total = getParamSequenceSize((self.getParam(paramName).winType for paramName in self.signature.paramList), True)
  123. if total < 32:
  124. return 32
  125. elif total > 1024:
  126. return 1024
  127. return total
  128. class FunctionSignature:
  129. def __repr__(self):
  130. return ', '.join(self.paramList)
  131. def __init__(self):
  132. self.LUT = {}
  133. self.paramList = []
  134. def append(self, variable, param):
  135. self.LUT[variable] = param
  136. self.paramList.append(variable)
  137. def getParam(self, variable):
  138. return self.LUT.get(variable)
  139. def getLength(self):
  140. return len(self.paramList)
  141. class FunctionParameter:
  142. def __repr__(self):
  143. return self.name
  144. def __init__(self, winType, name, count, outType, length):
  145. self.winType = winType
  146. self.outType = outType
  147. self.name = name
  148. self.length = length
  149. self.count = "win:null"
  150. if winType == "win:GUID" or count == "win:count":
  151. self.count = "win:count"
  152. ignoredXmlAttributes = frozenset(["map"])
  153. usedXmlAttributes = frozenset(["name", "inType", "count", "length", "outType"])
  154. knownXmlAttributes = ignoredXmlAttributes | usedXmlAttributes
  155. def checkKnownAttributes(nodes, templateName):
  156. for node in nodes:
  157. nodeMap = node.attributes
  158. for attribute in nodeMap.values():
  159. if attribute.name not in knownXmlAttributes:
  160. raise ValueError('Unknown attribute: ' + attribute.name + ' in template ' + templateName)
  161. def getTopLevelElementsByTagName(node, tag):
  162. return [e for e in node.getElementsByTagName(tag) if e.parentNode == node]
  163. def parseTemplateNodes(templateNodes):
  164. templates = {}
  165. for templateNode in templateNodes:
  166. templateName = templateNode.getAttribute('tid')
  167. dataNodes = getTopLevelElementsByTagName(templateNode, 'data')
  168. checkKnownAttributes(dataNodes, templateName)
  169. functionPrototypes = FunctionSignature()
  170. arrayCounts = {}
  171. structCounts = {}
  172. var_Dependencies = {}
  173. for dataNode in dataNodes:
  174. variable = dataNode.getAttribute('name')
  175. wintype = dataNode.getAttribute('inType')
  176. outType = dataNode.getAttribute('outType')
  177. wincount = dataNode.getAttribute('count')
  178. winLength = dataNode.getAttribute('length')
  179. var_dependency = [variable]
  180. if winLength:
  181. if wincount:
  182. raise Exception("Both count and length properties found on " + variable + " in template " + templateName)
  183. if wincount.isdigit() and int(wincount) == 1:
  184. wincount = ''
  185. if wincount:
  186. if wincount.isdigit():
  187. raise Exception("Expect constant count to be length")
  188. elif functionPrototypes.getParam(wincount):
  189. var_dependency.insert(0, wincount)
  190. arrayCounts[variable] = wincount
  191. var_Dependencies[variable] = var_dependency
  192. functionParameter = FunctionParameter(wintype, variable, wincount, outType, winLength)
  193. functionPrototypes.append(variable, functionParameter)
  194. structNodes = getTopLevelElementsByTagName(templateNode, 'struct')
  195. for structNode in structNodes:
  196. structName = structNode.getAttribute('name')
  197. countName = structNode.getAttribute('count')
  198. assert(countName in functionPrototypes.paramList)
  199. #childData = structNode.getElementsByTagName("data")
  200. #names = [x.attributes['name'].value for x in childData]
  201. #types = [x.attributes['inType'].value for x in childData]
  202. structCounts[structName] = countName
  203. var_Dependencies[structName] = [countName, structName]
  204. functionParameterPointer = FunctionParameter("win:Struct", structName, "win:count", None, None)
  205. functionPrototypes.append(structName, functionParameterPointer)
  206. templates[templateName] = Template(templateName, functionPrototypes, var_Dependencies, structCounts, arrayCounts)
  207. return templates
  208. def shouldPackTemplate(template):
  209. return template.num_params > MAX_LTTNG_ARGS or len(template.structCounts) > 0 or len(template.arrayCounts) > 0
  210. def generateArgList(template):
  211. # Construct a TP_ARGS macro call, as defined in another macro, e.g.
  212. #
  213. # TP_ARGS( \
  214. # int, my_integer_arg, \
  215. # char*, my_string_arg \
  216. # )
  217. header = "TP_ARGS( \\\n"
  218. footer = "\\\n)"
  219. args = []
  220. if shouldPackTemplate(template):
  221. args.append(" const unsigned int, length")
  222. args.append(" const char *, __data__")
  223. else:
  224. signature = template.signature
  225. for param in signature.paramList:
  226. functionParam = signature.getParam(param)
  227. wintypeName = functionParam.winType
  228. mappedType = lttngDataTypeMapping[wintypeName]
  229. winCount = functionParam.count
  230. mappedCount = lttngDataTypeMapping[winCount]
  231. arg = " " + mappedType
  232. if mappedCount != " ":
  233. arg += mappedCount
  234. elif functionParam.length:
  235. arg += "*"
  236. arg += ", " + functionParam.name
  237. args.append(arg)
  238. return header + ", \\\n".join(args) + footer
  239. def generateFieldList(template):
  240. # Construct a TP_FIELDS macro call, e.g.
  241. # TP_FIELDS(
  242. # ctf_string(my_string_field, my_string_arg)
  243. # ctf_integer(int, my_integer_field, my_integer_arg)
  244. # )
  245. header = " " + " TP_FIELDS(\n"
  246. footer = "\n )"
  247. fieldList = []
  248. if shouldPackTemplate(template):
  249. fieldList.append(" ctf_integer(unsigned long, length, length)")
  250. fieldList.append(" ctf_sequence(char, __data__, __data__, unsigned long, length)")
  251. else:
  252. signature = template.signature
  253. for param in signature.paramList:
  254. functionParam = signature.getParam(param)
  255. wintypeName = functionParam.winType
  256. winCount = functionParam.count
  257. mappedCount = lttngDataTypeMapping[winCount]
  258. mappedType = lttngDataTypeMapping[wintypeName].replace("const ", "")
  259. if functionParam.outType:
  260. wintypeName = functionParam.outType
  261. ctf_type = None
  262. field_body = None
  263. varname = functionParam.name
  264. if param in template.structCounts or param in template.arrayCounts:
  265. # This is a struct, treat as a sequence
  266. countVar = template.structCounts.get(param, template.arrayCounts.get(param))
  267. ctf_type = "ctf_sequence"
  268. field_body = ", ".join((mappedType, varname, varname, "size_t", functionParam.prop))
  269. elif functionParam.length:
  270. ctf_type = "ctf_sequence"
  271. field_body = ", ".join((mappedType, varname, varname, "size_t", functionParam.length))
  272. else:
  273. ctf_type = ctfDataTypeMapping[wintypeName]
  274. if ctf_type == "ctf_string":
  275. field_body = ", ".join((varname, varname))
  276. elif ctf_type == "ctf_integer" or ctf_type == "ctf_integer_hex" or ctf_type == "ctf_float":
  277. field_body = ", ".join((mappedType, varname, varname))
  278. elif ctf_type == "ctf_sequence":
  279. raise Exception("ctf_sequence needs special handling: " + template.name + " " + param)
  280. else:
  281. raise Exception("Unhandled ctf intrinsic: " + ctf_type)
  282. # fieldList.append("// " + wintypeName)
  283. fieldList.append(" %s(%s)" % (ctf_type, field_body))
  284. return header + "\n".join(fieldList) + footer
  285. def generateLttngHeader(providerName, lttngEventHeaderShortName, templates, events):
  286. headerLines = []
  287. headerLines.append("")
  288. headerLines.append("#ifdef __int64")
  289. headerLines.append("#if TARGET_64")
  290. headerLines.append("#undef __int64")
  291. headerLines.append("#else")
  292. headerLines.append("#error \"Linux and OSX builds only support 64bit platforms\"")
  293. headerLines.append("#endif // TARGET_64")
  294. headerLines.append("#endif // __int64")
  295. headerLines.append("#undef TRACEPOINT_PROVIDER")
  296. headerLines.append("#undef TRACEPOINT_INCLUDE")
  297. headerLines.append("")
  298. headerLines.append("#define TRACEPOINT_PROVIDER " + providerName + "\n")
  299. headerLines.append("#define TRACEPOINT_INCLUDE \"./" + lttngEventHeaderShortName + "\"\n\n")
  300. headerLines.append("#if !defined(LTTNG_CHAKRA_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n")
  301. headerLines.append("#define LTTNG_CHAKRA_H" + providerName +"\n")
  302. headerLines.append("\n#include <lttng/tracepoint.h>\n\n")
  303. for templateName in templates:
  304. template = templates[templateName]
  305. functionSignature = template.signature
  306. headerLines.append("")
  307. headerLines.append("#define " + templateName + "_TRACEPOINT_ARGS \\")
  308. tracepointArgs = generateArgList(template)
  309. headerLines.append(tracepointArgs)
  310. headerLines.append("TRACEPOINT_EVENT_CLASS(")
  311. headerLines.append(" " + providerName + ",")
  312. headerLines.append(" " + templateName + ",")
  313. headerLines.append(" " + templateName + "_TRACEPOINT_ARGS,")
  314. tracepointFields = generateFieldList(template)
  315. headerLines.append(tracepointFields)
  316. headerLines.append(")")
  317. headerLines.append("#define " + templateName + "T_TRACEPOINT_INSTANCE(name) \\")
  318. headerLines.append("TRACEPOINT_EVENT_INSTANCE(\\")
  319. headerLines.append(" " + providerName + ",\\")
  320. headerLines.append(" " + templateName + ",\\")
  321. headerLines.append(" name,\\")
  322. headerLines.append(" " + templateName + "_TRACEPOINT_ARGS \\")
  323. headerLines.append(")")
  324. headerLines.append("")
  325. headerLines.append("")
  326. headerLines.append("TRACEPOINT_EVENT_CLASS(")
  327. headerLines.append(" " + providerName + ",")
  328. headerLines.append(" emptyTemplate,")
  329. headerLines.append(" TP_ARGS(),")
  330. headerLines.append(" TP_FIELDS()")
  331. headerLines.append(")")
  332. headerLines.append("#define T_TRACEPOINT_INSTANCE(name) \\")
  333. headerLines.append("TRACEPOINT_EVENT_INSTANCE(\\")
  334. headerLines.append(" " + providerName + ",\\")
  335. headerLines.append(" emptyTemplate,\\")
  336. headerLines.append(" name,\\")
  337. headerLines.append(" TP_ARGS()\\")
  338. headerLines.append(")")
  339. headerLines.append("")
  340. for eventNode in events:
  341. eventName = eventNode.getAttribute('symbol')
  342. templateName = eventNode.getAttribute('template')
  343. if not eventName:
  344. raise Exception(eventNode + " event does not have a symbol")
  345. if not templateName:
  346. headerLines.append("T_TRACEPOINT_INSTANCE(" + eventName + ")")
  347. continue
  348. headerLines.append(templateName + "T_TRACEPOINT_INSTANCE(" + eventName + ")")
  349. headerLines.append("#endif /* LTTNG_CHAKRA_H" + providerName + " */")
  350. headerLines.append("#include <lttng/tracepoint-event.h>")
  351. return "\n".join(headerLines)
  352. def generateMethodBody(template, providerName, eventName):
  353. # Convert from ETW's windows types to LTTng compatiable types
  354. methodBody = [""]
  355. functionSignature = template.signature
  356. if not shouldPackTemplate(template):
  357. invocation = ["do_tracepoint(" + providerName, eventName]
  358. for paramName in functionSignature.paramList:
  359. functionParam = functionSignature.getParam(paramName)
  360. wintypeName = functionParam.winType
  361. winCount = functionParam.count
  362. ctf_type = None
  363. if functionParam.outType:
  364. ctf_type = ctfDataTypeMapping.get(functionParam.outType)
  365. else:
  366. ctf_Type = ctfDataTypeMapping.get(winCount)
  367. if not ctf_type:
  368. ctf_type = ctfDataTypeMapping[wintypeName]
  369. if ctf_type == "ctf_string" and wintypeName == "win:UnicodeString":
  370. # Convert wchar unicode string to utf8
  371. if functionParam.length:
  372. methodBody.append("utf8::WideToNarrow " + paramName + "_converter(" + paramName + ", " + functionParam.length + ");")
  373. else:
  374. methodBody.append("utf8::WideToNarrow " + paramName + "_converter(" + paramName + ");")
  375. invocation.append(paramName + "_converter")
  376. # elif ctf_type == "ctf_sequence" or wintypeName == "win:Pointer":
  377. elif wintypeName == "win:Pointer":
  378. invocation.append("(" + lttngDataTypeMapping[wintypeName] + lttngDataTypeMapping[winCount] + ")" + paramName)
  379. else:
  380. invocation.append(paramName)
  381. methodBody.append(",\n ".join(invocation) + ");")
  382. else:
  383. # Packing results into buffer
  384. methodBody.append("char stackBuffer[" + str(template.estimatedSize) + "];")
  385. methodBody.append("char *buffer = stackBuffer;")
  386. methodBody.append("int offset = 0;")
  387. methodBody.append("int size = " + str(template.estimatedSize) + ";")
  388. methodBody.append("bool fixedBuffer = true;")
  389. methodBody.append("bool success = true;")
  390. for paramName in functionSignature.paramList:
  391. functionParameter = functionSignature.getParam(paramName)
  392. if paramName in template.structCounts:
  393. size = "(unsigned int)" + paramName + "_ElementSize * (unsigned int)" + template.structCounts[paramName]
  394. methodBody.append("success &= WriteToBuffer((const char *)" + paramName + ", " + size + ", buffer, offset, size, fixedBuffer);")
  395. elif paramName in template.arrayCounts:
  396. size = "sizeof(" + lttngDataTypeMapping[functionParameter.winType] + ") * (unsigned int)" + template.arrayCounts[paramName]
  397. methodBody.append("success &= WriteToBuffer((const char *)" + paramName + ", " + size + ", buffer, offset, size, fixedBuffer);")
  398. elif functionParameter.winType == "win:GUID":
  399. methodBody.append("success &= WriteToBuffer(*" + paramName + ", buffer, offset, size, fixedBuffer);")
  400. else:
  401. methodBody.append("success &= WriteToBuffer(" + paramName + ", buffer, offset, size, fixedBuffer);")
  402. methodBody.append("if (!success)")
  403. methodBody.append("{")
  404. methodBody.append(" if (!fixedBuffer) delete[] buffer;")
  405. methodBody.append(" return ERROR_WRITE_FAULT;")
  406. methodBody.append("}")
  407. methodBody.append("do_tracepoint(" + providerName + ", " + eventName + ", offset, buffer);")
  408. methodBody.append("if (!fixedBuffer) delete[] buffer;")
  409. return "\n ".join(methodBody) + "\n"
  410. def generateMethodSignature(template):
  411. if not template:
  412. return ""
  413. functionSignature = template.signature
  414. lineFunctionPrototype = []
  415. for paramName in functionSignature.paramList:
  416. functionParameter = functionSignature.getParam(paramName)
  417. wintypeName = functionParameter.winType
  418. mappedType = palDataTypeMapping[wintypeName]
  419. winCount = functionParameter.count
  420. mappedCount = palDataTypeMapping[winCount]
  421. if paramName in template.structCounts:
  422. lineFunctionPrototype.append(" int " + paramName + "_ElementSize")
  423. # lineFunctionPrototype.append("// " + wintypeName + " " + str(functionParameter.length))
  424. lineFunctionPrototype.append(
  425. " " + mappedType
  426. + (mappedCount if mappedCount != " " else "*" if functionParameter.length and not wintypeName in ["win:UnicodeString", "win:AnsiString"] else "")
  427. + " "
  428. + functionParameter.name)
  429. return ",\n".join(lineFunctionPrototype)
  430. def generateLttngTracepointProvider(providerName, lttngHeader, templates, events):
  431. providerLines = [];
  432. providerLines.append("#define TRACEPOINT_DEFINE")
  433. providerLines.append("#ifndef CHAKRA_STATIC_LIBRARY")
  434. providerLines.append("#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE")
  435. providerLines.append("#endif")
  436. providerLines.append("#include \"stdlib.h\"")
  437. providerLines.append("#include \"Common.h\"")
  438. providerLines.append("#include \"Codex/Utf8Helper.h\"")
  439. providerLines.append("#include \"" + lttngHeader + "\"\n\n")
  440. providerLines.append("#ifndef tracepoint_enabled")
  441. providerLines.append("#define tracepoint_enabled(provider, name) 1")
  442. providerLines.append("#define do_tracepoint tracepoint")
  443. providerLines.append("#endif")
  444. providerLines.append("""
  445. bool ResizeBuffer(char *&buffer, int&size, int currentLength, int newSize, bool &fixedBuffer)
  446. {
  447. newSize *= 1.5;
  448. _ASSERTE(newSize > size); // Check for overflow
  449. if (newSize < 32)
  450. {
  451. newSize = 32;
  452. }
  453. char *newBuffer = new char[newSize];
  454. memcpy(newBuffer, buffer, currentLength);
  455. if (!fixedBuffer)
  456. {
  457. delete[] buffer;
  458. }
  459. buffer = newBuffer;
  460. size = newSize;
  461. fixedBuffer = false;
  462. return true;
  463. }
  464. bool WriteToBuffer(const char * src, int len, char *&buffer, int &offset, int &size, bool &fixedBuffer)
  465. {
  466. if (!src)
  467. {
  468. return true;
  469. }
  470. if (offset + len > size)
  471. {
  472. if (!ResizeBuffer(buffer, size, offset, size+len, fixedBuffer))
  473. {
  474. return false;
  475. }
  476. }
  477. memcpy(buffer + offset, src, len);
  478. offset += len;
  479. return true;
  480. }
  481. template <typename T>
  482. bool WriteToBuffer(const T &value, char *&buffer, int&offset, int&size, bool &fixedBuffer)
  483. {
  484. if (sizeof(T) + offset > size)
  485. {
  486. if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer))
  487. {
  488. return false;
  489. }
  490. }
  491. *(T *)(buffer + offset) = value;
  492. offset += sizeof(T);
  493. return true;
  494. }
  495. """)
  496. for eventNode in events:
  497. eventName = eventNode.getAttribute('symbol')
  498. templateName = eventNode.getAttribute('template')
  499. providerLines.append("extern \"C\" bool EventXplatEnabled%s(){ return tracepoint_enabled(%s, %s);}"
  500. % (eventName, providerName, eventName))
  501. providerLines.append("")
  502. template = None
  503. if templateName:
  504. template = templates[templateName]
  505. providerLines.append("extern \"C\" unsigned long FireEtXplat" + eventName + "(")
  506. providerLines.append(generateMethodSignature(template))
  507. providerLines.append(")")
  508. providerLines.append("{")
  509. providerLines.append(" if (!EventXplatEnabled" + eventName + "())")
  510. providerLines.append(" return ERROR_SUCCESS;")
  511. if template:
  512. providerLines.append(generateMethodBody(template, providerName, eventName))
  513. else:
  514. providerLines.append(" do_tracepoint(" + providerName + ", " + eventName +");")
  515. providerLines.append("")
  516. providerLines.append(" return ERROR_SUCCESS;")
  517. providerLines.append("}")
  518. providerLines.append("")
  519. return "\n".join(providerLines)
  520. def generateEtwHeader(templates, events):
  521. headerLines = []
  522. headerLines.append("#include \"pal.h\"")
  523. headerLines.append("")
  524. for event in events:
  525. eventName = event.getAttribute('symbol')
  526. templateName = event.getAttribute('template')
  527. template = None
  528. if templateName:
  529. template = templates[templateName]
  530. callArgs = []
  531. if template:
  532. functionSignature = template.signature
  533. for param in functionSignature.paramList:
  534. if param in template.structCounts:
  535. callArgs.append(param + "_ElementSize")
  536. callArgs.append(param)
  537. headerLines.append("extern \"C\" bool EventXplatEnabled" + eventName +"();")
  538. headerLines.append("inline bool EventEnabled" + eventName +"() { return EventXplatEnabled" + eventName + "();}")
  539. headerLines.append("")
  540. headerLines.append("extern \"C\" unsigned long FireEtXplat" + eventName +" (")
  541. headerLines.append(generateMethodSignature(template))
  542. headerLines.append(");")
  543. headerLines.append("inline unsigned long EventWrite" + eventName + "(")
  544. headerLines.append(generateMethodSignature(template))
  545. headerLines.append(")")
  546. headerLines.append("{")
  547. headerLines.append(" return FireEtXplat" + eventName + "(" + ", ".join(callArgs) + ");")
  548. headerLines.append("}")
  549. headerLines.append("")
  550. return "\n".join(headerLines)
  551. def generateCmakeFile(providerName):
  552. cmakeLines = []
  553. cmakeLines.append("project(Chakra.LTTng)")
  554. cmakeLines.append("")
  555. cmakeLines.append("add_compile_options(-fPIC)")
  556. cmakeLines.append("")
  557. cmakeLines.append("add_library (Chakra.LTTng OBJECT")
  558. cmakeLines.append(" eventprovider" + providerName + ".cpp")
  559. cmakeLines.append(" tracepointprovider" + providerName + ".cpp")
  560. cmakeLines.append(")")
  561. return "\n".join(cmakeLines)
  562. def generateLttngFiles(manifest, providerDirectory):
  563. import os
  564. tree = DOM.parse(manifest)
  565. if not os.path.exists(providerDirectory):
  566. os.makedirs(providerDirectory)
  567. if not os.path.exists(providerDirectory + "/lttng"):
  568. os.makedirs(providerDirectory + "/lttng")
  569. for providerNode in tree.getElementsByTagName("provider"):
  570. providerName = providerNode.getAttribute("name")
  571. providerName = providerName.replace("Microsoft-", "")
  572. providerNameFile = providerName.lower()
  573. lttngEventHeaderShortName = "tp" + providerNameFile + ".h"
  574. lttngEventHeaderPath = providerDirectory + "/lttng/" + lttngEventHeaderShortName
  575. lttngEventProvider = providerDirectory + "/lttng/eventprovider" + providerNameFile + ".cpp"
  576. lttngEventProviderTrace = providerDirectory + "/lttng/tracepointprovider" + providerNameFile + ".cpp"
  577. lttngEtwHeaderFile = providerDirectory + "/lttng/" + providerNameFile + "Etw.h"
  578. lttngCmakeFile = providerDirectory + "/lttng/CMakeLists.txt"
  579. lttngHeader = open(lttngEventHeaderPath, "w")
  580. lttngImplementation = open(lttngEventProvider, "w")
  581. lttngTraceImplementation = open(lttngEventProviderTrace, "w")
  582. lttngEtwHeader = open(lttngEtwHeaderFile, "w")
  583. lttngCmake = open(lttngCmakeFile, "w")
  584. # Create the lttng implementation
  585. lttngTraceImplementation.write("#define TRACEPOINT_CREATE_PROBES\n")
  586. lttngTraceImplementation.write("#include \"./"+lttngEventHeaderShortName+"\"\n")
  587. lttngTraceImplementation.close()
  588. # Create the lttng header
  589. templateNodes = providerNode.getElementsByTagName('template')
  590. eventNodes = providerNode.getElementsByTagName('event')
  591. allTemplates = parseTemplateNodes(templateNodes)
  592. lttngHeader.write(generateLttngHeader(providerName, lttngEventHeaderShortName, allTemplates, eventNodes))
  593. lttngHeader.close();
  594. lttngImplementation.write(generateLttngTracepointProvider(providerName, lttngEventHeaderShortName, allTemplates, eventNodes))
  595. lttngImplementation.close();
  596. lttngEtwHeader.write(generateEtwHeader(allTemplates, eventNodes))
  597. lttngEtwHeader.close()
  598. # Note: This in particular assumes that there is only one ETW provider
  599. lttngCmake.write(generateCmakeFile(providerNameFile))
  600. lttngCmake.close()
  601. if __name__ == '__main__':
  602. import argparse
  603. import sys
  604. parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng logging mechanism")
  605. required = parser.add_argument_group('required arguments')
  606. required.add_argument('--man', type=str, required=True,
  607. help='full path to manifest containig the description of events')
  608. required.add_argument('--intermediate', type=str, required=True,
  609. help='full path to eventprovider intermediate directory')
  610. args, unknown = parser.parse_known_args(sys.argv[1:])
  611. if unknown:
  612. print('Unknown argument(s): ', ', '.join(unknown))
  613. sys.exit(1)
  614. generateLttngFiles(args.man, args.intermediate)
  615. sys.exit(0)