public void TraceLineDiscovered(string sourceFile, CLogOutputInfo outputInfo, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { string priority = decodedTraceLine.GetConfigurationValue(ModuleName, "Priority"); inline.Append($"syslog({priority}, \"{decodedTraceLine.TraceString}\""); foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; if (!arg.TypeNode.IsEncodableArg) { continue; } CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; } inline.Append(", " + arg.MacroVariableName); } inline.Append(");\\\n"); }
public void FinishedProcessing(CLogOutputInfo outputInfo, StringBuilder header, StringBuilder sourceFile) { string dir = Path.GetDirectoryName(_lttngHeaderFileName); if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } File.WriteAllText(_lttngHeaderFileName, lttngFile.ToString()); if (_lttngDynamicTracepoint) { sourceFile.AppendLine("#ifdef BUILDING_TRACEPOINT_PROVIDER"); sourceFile.AppendLine("#define TRACEPOINT_CREATE_PROBES"); sourceFile.AppendLine("#else"); sourceFile.AppendLine("#define TRACEPOINT_DEFINE"); sourceFile.AppendLine("#endif"); } else { sourceFile.AppendLine("#define TRACEPOINT_CREATE_PROBES"); sourceFile.AppendLine("#define TRACEPOINT_DEFINE"); } sourceFile.AppendLine($"#include \"{Path.GetFileName(_clogFile)}\""); }
public void FinishedProcessing(CLogOutputInfo outputInfo, StringBuilder header, StringBuilder sourceFile) { }
public void TraceLineDiscovered(string sourceFile, CLogOutputInfo outputInfo, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { CLogFileProcessor.DecomposedString clean; CLogFileProcessor.CLogTypeContainer[] types = CLogFileProcessor.BuildTypes(decodedTraceLine.configFile, null, decodedTraceLine.TraceString, null, out clean); CLogExportModuleDefination moduleSettings = decodedTraceLine.GetMacroConfigurationProfile().FindExportModule(ModuleName); string printmacro; if (!moduleSettings.CustomSettings.TryGetValue("PrintMacro", out printmacro)) { printmacro = "printf"; } if (!emittedHeader) { string printHeader; if (!moduleSettings.CustomSettings.TryGetValue("PrintHeader", out printHeader)) { printHeader = "stdio.h"; } emittedHeader = true; } // // Only emit the function once; we may be called multiple times should someone emit an event multiple times in the same file // (usually error paths) // string argsString = string.Empty; string macroString = string.Empty; foreach (var arg in decodedTraceLine.splitArgs) { if (!arg.TypeNode.Synthesized && arg.TypeNode.EncodingType != CLogEncodingType.UniqueAndDurableIdentifier && arg.TypeNode.EncodingType != CLogEncodingType.UserEncodingString) { string seperatorA = ""; string seperatorB = ""; if (string.IsNullOrEmpty(argsString)) { seperatorA = ","; seperatorB = ""; } else { seperatorA = ""; seperatorB = ","; } // If the encided type is 'binary' (length and payload) - for DTrace we emit the payload // length with the variable name <suggestedName>_len if (CLogEncodingType.ByteArray == arg.TypeNode.EncodingType) { argsString += $"{seperatorB} unsigned int {arg.VariableInfo.SuggestedTelemetryName}_len{seperatorA}"; macroString += $"{seperatorB} {arg.MacroVariableName}_len{seperatorA}"; } argsString += $"{seperatorB} {arg.TypeNode.CType} {arg.MacroVariableName}"; macroString += $"{seperatorB} {arg.MacroVariableName}"; } } string printf = ""; foreach (var t in types) { printf += t.LeadingString; switch (t.TypeNode.EncodingType) { case CLogEncodingType.Int32: printf += "%d"; break; case CLogEncodingType.UInt32: printf += "%u"; break; case CLogEncodingType.Int64: printf += "%lld"; break; case CLogEncodingType.UInt64: printf += "%llu"; break; case CLogEncodingType.ANSI_String: printf += "%s"; break; case CLogEncodingType.UNICODE_String: printf += "%S"; break; case CLogEncodingType.Pointer: printf += "0x%llx"; break; case CLogEncodingType.GUID: printf += "%p"; break; case CLogEncodingType.Int16: printf += "%d"; break; case CLogEncodingType.UInt16: printf += "%d"; break; case CLogEncodingType.Int8: printf += "%d"; break; case CLogEncodingType.UInt8: printf += "%d"; break; case CLogEncodingType.ByteArray: printf += "[Not_Supported]"; break; } } // // Print the remainder of user text (the tail end); if there are no types at all then 'TraceString' is just a constant string // if (types.Length >= 1) { string tail = decodedTraceLine.TraceString.Substring(types[types.Length - 1].ArgStartingIndex + types[types.Length - 1].ArgLength); printf += tail; } else { printf += decodedTraceLine.TraceString; } printf += "\\n"; inline.Append($" {printmacro}(\"{printf}\""); foreach (var arg in decodedTraceLine.splitArgs) { if (arg.TypeNode.Synthesized || arg.TypeNode.EncodingType == CLogEncodingType.UniqueAndDurableIdentifier || arg.TypeNode.EncodingType == CLogEncodingType.UserEncodingString) { continue; } string cast = ""; switch (arg.TypeNode.EncodingType) { case CLogEncodingType.Int32: //cast = "(int)"; break; case CLogEncodingType.UInt32: //cast = "(unsigned int)"; break; case CLogEncodingType.Int64: //cast = "(__int64)"; break; case CLogEncodingType.UInt64: //cast = "(unsigned __int64)"; break; case CLogEncodingType.ANSI_String: break; case CLogEncodingType.UNICODE_String: break; case CLogEncodingType.Pointer: cast = "(unsigned long long int)"; break; case CLogEncodingType.GUID: cast = "(void*)"; break; case CLogEncodingType.Int16: //cast = "(__int16)"; break; case CLogEncodingType.UInt16: //cast = "(unsigned __int16)"; break; case CLogEncodingType.Int8: //cast = "(int)"; break; case CLogEncodingType.UInt8: //cast = "(int)"; break; case CLogEncodingType.ByteArray: //cast = "(void*)"; continue; } inline.Append($", {cast}(" + arg.MacroVariableName + ")"); } inline.Append(");"); }
public void TraceLineDiscovered(CLogDecodedTraceLine decodedTraceLine, CLogOutputInfo outputInfo, StringBuilder results) { Dictionary <int, string> map = new Dictionary <int, string>(); int idx = 1; if (skip) { results.Append(decodedTraceLine.match.MatchedRegExX.ToString()); return; } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, decodedTraceLine.match.MatchedRegExX.ToString()); int c = -1; try { for (; ;) { foreach (var m in decodedTraceLine.configFile.AllKnownMacros()) { map[idx] = m.MacroName; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"{idx}. {m.MacroName}"); ++idx; } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"{idx}. <skip the rest in this file and save>"); string choice = null; while (String.IsNullOrEmpty(choice)) { try { choice = Console.ReadLine(); c = Convert.ToInt32(choice); } catch (Exception) { Console.WriteLine("try again please"); } } if (c == idx) { skip = true; results.Append(decodedTraceLine.match.MatchedRegExX.ToString()); return; } break; } } catch (Exception) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "ERROR : invalid input"); } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "UNIQUE ID"); string id = Console.ReadLine().Trim().ToUpper(); while (takenIds.Contains(id)) { Console.WriteLine("ID is taken please use a unique ID"); id = Console.ReadLine().Trim().ToUpper(); } takenIds.Add(id); results.Append($"{map[c]}("); results.Append("" + id); results.Append($", \"{decodedTraceLine.TraceString}\""); for (int i = 2; i < decodedTraceLine.splitArgs.Length; ++i) { var arg = decodedTraceLine.splitArgs[i]; results.Append($", {arg.VariableInfo.UserSuppliedTrimmed}"); } results.Append(");"); }
public void TraceLineDiscovered(string sourceFile, CLogOutputInfo outputInfo, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { string hash = decodedTraceLine.UniqueId; CLogExportModuleDefination moduleSettings = decodedTraceLine.GetMacroConfigurationProfile().FindExportModule(_ModuleName); if (!_inited) { if (!moduleSettings.CustomSettings.ContainsKey("ETWManifestFile")) { throw new CLogEnterReadOnlyModeException("ETWManifestFileNotSpecified", CLogHandledException.ExceptionType.MustSpecifiyETWManifest, decodedTraceLine.match); } xmlFileName = moduleSettings.CustomSettings["ETWManifestFile"]; xmlFileName = Path.Combine(Path.GetDirectoryName(decodedTraceLine.macro.ConfigFileWithMacroDefination), xmlFileName); Init(); } if (!moduleSettings.CustomSettings.ContainsKey("ETW_Provider")) { Console.WriteLine($"The 'CustomSettings' dictionary for macro {decodedTraceLine.macro.MacroName} does not contain a GUID for the EtwProvider"); Console.WriteLine(" Please add an entry and rerun"); Console.WriteLine(""); Console.WriteLine($"Configuration File : {decodedTraceLine.configFile.FilePath}"); Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine(""); throw new CLogEnterReadOnlyModeException("ETW_Provider:NotSpecified", CLogHandledException.ExceptionType.MustSpecifyETWProvider, decodedTraceLine.match); } Guid providerId = new Guid(moduleSettings.CustomSettings["ETW_Provider"]); ManifestInformation manifest = FindProviderCache(providerId); string eventNamePrefix; if (!moduleSettings.CustomSettings.TryGetValue("EventNamePrefix", out eventNamePrefix)) { eventNamePrefix = string.Empty; } if (null == manifest) { Console.WriteLine($"Unable to locate ETW provider {providerId} in CLOG macro {decodedTraceLine.macro.MacroName}"); Console.WriteLine(" CLOG will not create this provider within the manifest; it will only add to an existing provider"); Console.WriteLine(" please consult the MSDN documentation for an ETW manifest for instructions"); Console.WriteLine(""); Console.WriteLine($"Macro: {providerId} is defined in {decodedTraceLine.configFile.FilePath}"); Console.WriteLine($"ETW Manifest : is set as {xmlFileName}"); Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine(""); throw new CLogEnterReadOnlyModeException("ManifestedETWProviderNotFoundInManifest", CLogHandledException.ExceptionType.ManifestedETWProviderNotFound, decodedTraceLine.match); } // // See if our event already exists - if it does we do not want to add it a second time // List <XmlElement> toRemove = new List <XmlElement>(); XmlElement newEvent = null; if (null == manifest.events) { throw new CLogEnterReadOnlyModeException("ManifestedETW does not contain 'events' node", CLogHandledException.ExceptionType.ManifestedETWFileDoesntContainEvents, decodedTraceLine.match); } foreach (var p in manifest.events.ChildNodes) { if (!(p is XmlElement)) { continue; } XmlElement pe = (XmlElement)p; if (pe.Name == "event") { if (!pe.HasAttribute("symbol")) { continue; } string symbol = pe.GetAttribute("symbol"); if (0 == symbol.CompareTo(eventNamePrefix + hash)) { toRemove.Add(pe); newEvent = pe; break; } } } // // Add the event if it doesnt already exist // if (null == newEvent) { newEvent = doc.CreateElement("event", manifest.events.NamespaceURI); manifest.events.AppendChild(newEvent); _dirty = true; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $"Adding event {eventNamePrefix + hash} to ETW manifest {xmlFileName}"); // // Set the string // bool setString = true; if (moduleSettings.CustomSettings.ContainsKey("EmitString") && moduleSettings.CustomSettings["EmitString"].Equals("0")) { setString = false; } if (setString) { string stringName = "CLOG." + hash; string manifestString = MapCLOGStringToManifestString(decodedTraceLine); var stringEntry = doc.CreateElement("string", manifest.stringTable.NamespaceURI); manifest.stringTable.AppendChild(stringEntry); _dirty = true; SetAttribute(stringEntry, "id", stringName); SetAttribute(stringEntry, "value", manifestString); SetAttribute(newEvent, "message", "$(string." + stringName + ")"); } } int hashUInt; string eventAsString; decodedTraceLine.macro.DecodeUniqueId(decodedTraceLine.match, hash, out eventAsString, out hashUInt); uint eventId; if (!newEvent.HasAttribute("value")) { eventId = FindUnusedEventId(providerId, decodedTraceLine.match); SetAttribute(newEvent, "value", eventId.ToString()); } else { eventId = Convert.ToUInt32(newEvent.GetAttribute("value")); } // // Store the eventID for future decode as well as every configuration setting attached to this module // decodedTraceLine.AddConfigFileProperty(ModuleName, "EventID", eventId.ToString()); foreach (var setting in moduleSettings.CustomSettings) { decodedTraceLine.AddConfigFileProperty(ModuleName, setting.Key, setting.Value); } SetAttribute(newEvent, "symbol", eventNamePrefix + hash); string oldTemplate = null; if (newEvent.HasAttribute("template")) { oldTemplate = newEvent.GetAttribute("template"); } string templateId = DiscoverOrCreateTemplate(decodedTraceLine, sidecar, providerId, oldTemplate, eventId); SetAttribute(newEvent, "template", templateId); if (moduleSettings.CustomSettings.ContainsKey("Level")) { SetAttribute(newEvent, "level", moduleSettings.CustomSettings["Level"]); } else { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, $"Manifested ETW Level not specified; if you desire a Level, add 'Level' to CustomSettings in {decodedTraceLine.configFile.FilePath}"); } if (moduleSettings.CustomSettings.ContainsKey("Keywords")) { SetAttribute(newEvent, "keywords", moduleSettings.CustomSettings["Keywords"]); } else { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, $"Manifested ETW Keywords not specified; if you desire a Keyword, add 'Keywords' to CustomSettings in {decodedTraceLine.configFile.FilePath}"); } // // Construct the function signature // string traceLine = $"EventWrite{eventNamePrefix + hash}("; bool haveMultipleArgs = false; foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; if (!arg.TypeNode.IsEncodableArg) { continue; } CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; } if (haveMultipleArgs) { traceLine += ", "; } haveMultipleArgs = true; switch (node.EncodingType) { case CLogEncodingType.ByteArray: traceLine += $"{arg.MacroVariableName}_len, {arg.MacroVariableName}"; continue; default: traceLine += $"{arg.MacroVariableName}"; break; } } traceLine += "); \\"; inline.AppendLine(traceLine); Save(decodedTraceLine.match); }
public void TraceLineDiscovered(string sourceFile, CLogOutputInfo outputInfo, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { // // Generate a function name that is unique; this is where you'll attach a DTrace probe. // // ScopePrefix is passed in during compliation, it is a unique name that indicates the library // string uid = "DTRACE_" + decodedTraceLine.configFile.ScopePrefix + "_" + Path.GetFileName(sourceFile).Replace(".", "_") + "_" + decodedTraceLine.UniqueId; uid = uid.Replace("{", ""); uid = uid.Replace("}", ""); uid = uid.Replace("-", ""); string argsString = string.Empty; string macroString = string.Empty; foreach (var arg in decodedTraceLine.splitArgs) { CLogEncodingCLogTypeSearch v = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); if (!v.Synthesized) { string seperatorA = ""; string seperatorB = ""; if (string.IsNullOrEmpty(argsString)) { seperatorA = ","; seperatorB = ""; } else { seperatorA = ""; seperatorB = ","; } // If the encided type is 'binary' (length and payload) - for DTrace we emit the payload // length with the variable name <suggestedName>_len if (CLogEncodingType.ByteArray == v.EncodingType) { argsString += $"{seperatorB} unsigned int {arg.VariableInfo.SuggestedTelemetryName}_len{seperatorA}"; macroString += $"{seperatorB} {arg.MacroVariableName}_len{seperatorA}"; } argsString += $"{seperatorB} {v.CType} {arg.MacroVariableName}"; macroString += $"{seperatorB} {arg.MacroVariableName}"; } } // // Emit into the CLOG macro (this is the actual code that goes into the product) // macroPrefix.AppendLine("void " + uid + "(" + argsString + ");\r\n"); // // Emit our foward delcaration and implementation into the .c file that CLOG generates // if (!alreadyEmitted.Contains(uid)) { inline.AppendLine($"{uid}({macroString});\\"); function.AppendLine($"void {uid}({argsString})" + "{}\r\n\r\n"); alreadyEmitted.Add(uid); } }
public void TraceLineDiscovered(string sourceFile, CLogOutputInfo outputInfo, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { int hashUInt; string hash; decodedTraceLine.macro.DecodeUniqueId(decodedTraceLine.match, decodedTraceLine.UniqueId, out hash, out hashUInt); int usedArguments = 0; foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; if (!arg.TypeNode.IsEncodableArg) { continue; } CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.ByteArray: usedArguments += 2; break; default: ++usedArguments; break; } } if (usedArguments >= 11) { throw new ReadOnlyException($"Too Many arguments in {hash}, LTTNG accepts a max of 10"); } lttngFile.AppendLine(""); lttngFile.AppendLine(""); lttngFile.AppendLine(""); lttngFile.AppendLine("/*----------------------------------------------------------"); lttngFile.AppendLine($"// Decoder Ring for {decodedTraceLine.UniqueId}"); lttngFile.AppendLine($"// {decodedTraceLine.TraceString}"); lttngFile.AppendLine($"// {decodedTraceLine.match.MatchedRegExX}"); foreach (var arg in decodedTraceLine.splitArgs) { if (!arg.TypeNode.IsEncodableArg) { continue; } lttngFile.AppendLine($"// {arg.MacroVariableName} = {arg.VariableInfo.SuggestedTelemetryName} = {arg.VariableInfo.UserSuppliedTrimmed} = {arg.VariableInfo.IndexBasedName}"); } lttngFile.AppendLine("----------------------------------------------------------*/"); lttngFile.AppendLine($"TRACEPOINT_EVENT({_lttngProviderName}, {hash},"); int argNum = 0; lttngFile.AppendLine(" TP_ARGS("); foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; if (!arg.TypeNode.IsEncodableArg) { continue; } CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; case CLogEncodingType.UNICODE_String: continue; } if (0 != argNum) { if (CLogEncodingType.ByteArray == node.EncodingType) { lttngFile.Append(","); lttngFile.AppendLine(""); lttngFile.Append($" unsigned int, {arg.VariableInfo.SuggestedTelemetryName}_len"); } lttngFile.Append(","); lttngFile.AppendLine(""); lttngFile.Append($" {ConvertToClogType(node)}, {arg.VariableInfo.SuggestedTelemetryName}"); } else { if (CLogEncodingType.ByteArray == node.EncodingType) { lttngFile.Append($" unsigned int, {arg.VariableInfo.SuggestedTelemetryName}_len"); lttngFile.Append(","); lttngFile.AppendLine(""); } lttngFile.Append($" {ConvertToClogType(node)}, {arg.VariableInfo.SuggestedTelemetryName}"); } ++argNum; } lttngFile.Append("), "); lttngFile.AppendLine(""); lttngFile.AppendLine(" TP_FIELDS("); foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; if (!arg.TypeNode.IsEncodableArg) { continue; } CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; case CLogEncodingType.UNICODE_String: continue; case CLogEncodingType.ByteArray: lttngFile.AppendLine( $" ctf_integer(unsigned int, {arg.VariableInfo.SuggestedTelemetryName}_len, {arg.VariableInfo.SuggestedTelemetryName}_len)"); lttngFile.AppendLine( $" ctf_sequence(char, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName}, unsigned int, {arg.VariableInfo.SuggestedTelemetryName}_len)"); break; case CLogEncodingType.Int8: lttngFile.AppendLine( $" ctf_integer(char, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.UInt8: lttngFile.AppendLine( $" ctf_integer(unsigned char, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.Int16: lttngFile.AppendLine( $" ctf_integer(short, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.UInt16: lttngFile.AppendLine( $" ctf_integer(unsigned short, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.Int32: lttngFile.AppendLine( $" ctf_integer(int, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.UInt32: lttngFile.AppendLine( $" ctf_integer(unsigned int, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.Int64: lttngFile.AppendLine( $" ctf_integer(int64_t, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.UInt64: lttngFile.AppendLine( $" ctf_integer(uint64_t, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.Pointer: lttngFile.AppendLine( $" ctf_integer_hex(uint64_t, {arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; case CLogEncodingType.ANSI_String: lttngFile.AppendLine( $" ctf_string({arg.VariableInfo.SuggestedTelemetryName}, {arg.VariableInfo.SuggestedTelemetryName})"); break; default: throw new CLogEnterReadOnlyModeException("LTTNG:UnknownType:" + node.EncodingType, CLogHandledException.ExceptionType.EncoderIncompatibleWithType, decodedTraceLine.match); } ++argNum; } lttngFile.AppendLine(" )"); //TRACEPONT_ARGS lttngFile.AppendLine(")"); //TRACEPOINT_EVENT string traceLine = $"tracepoint({_lttngProviderName}, {hash} "; foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; if (!arg.TypeNode.IsEncodableArg) { continue; } CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); if (string.IsNullOrEmpty(node.CType)) { throw new ReadOnlyException($"Missing CType Field : {node.DefinationEncoding}"); } switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; case CLogEncodingType.UNICODE_String: continue; } if (node.EncodingType == CLogEncodingType.ByteArray) { traceLine += $", {arg.MacroVariableName}_len"; } traceLine += $", {arg.MacroVariableName}"; } traceLine += ");\\"; inline.AppendLine(traceLine); }
private static int Main(string[] args) { ParserResult <CommandLineArguments> o = Parser.Default.ParseArguments <CommandLineArguments>(args); return(o.MapResult( options => { string currentFile = null; try { // // The CommandLineArguments library validates most input arguments for us, there are few ones that are complicated // this secondary check looks for those and errors out if present // if (!options.IsValid()) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Invalid args"); return -1; } CLogConfigurationFile configFile = CLogConfigurationFile.FromFile(options.ConfigurationFile); configFile.ProfileName = options.ConfigurationProfile; if (options.ReadOnly && !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_FORCE_WRITABLE"))) { options.ReadOnly = false; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, "WARNING: CLOG was instructed via --readOnly not to emit changes however this was overridden with CLOG_FORCE_WRITABLE environment variable"); } if (options.OverwriteHashCollisions || !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_OVERWRITE_COLLISIONS"))) { options.OverwriteHashCollisions = true; options.ReadOnly = false; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "***********************************************"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Overwriting of sidecare collisions is set by environment variable CLOG_OVERWRITE_COLLISIONS. This setting is only to be used while making large refactors and should not be included in build environments or standard development environments"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "***********************************************"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); } if (options.Devmode || !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_DEVELOPMENT_MODE"))) { options.ReadOnly = false; options.OverwriteHashCollisions = true; configFile.DeveloperMode = true; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, "WARNING: CLOG was instructed to enter a developer mode"); } if (options.LintConfig) { if (!configFile.MarkPhase) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Lint operation only works on config files placed into the 'MarkPhase'. This can be a destricutive action, please read the docs for more information"); return -10; } configFile.Lint(); configFile.Save(false); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "Lint operation complete"); return 0; } if (options.UpgradeConfigFile) { configFile.UpdateVersion(); configFile.Save(false); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "Config upgrade complete"); return 0; } CLogSidecar sidecar; if (!Directory.Exists(Path.GetDirectoryName(options.SidecarFile))) { Directory.CreateDirectory(Path.GetDirectoryName(options.SidecarFile)); } if (!File.Exists(options.SidecarFile)) { sidecar = new CLogSidecar(); } else { string json = File.ReadAllText(options.SidecarFile); sidecar = CLogSidecar.FromJson(json); if (null == sidecar) { sidecar = new CLogSidecar(); } } sidecar.SetConfigFile(configFile); if (options.RefreshCustomTypeProcessor) { configFile.ForceDecoderCompile(); sidecar.Save(options.SidecarFile); return 0; } // // BUGBUG: refactoring needed for handling batches of input files, expecially // now that managed languages are coming along. Leaving this unaddressed // for now while the best way is still elusive // List <ICLogBatchingModule> batchingModules = new List <ICLogBatchingModule>(); Console.WriteLine("Number of files : " + (new List <string>(options.InputFiles)).Count); foreach (string inputFile in options.InputFiles) { Console.WriteLine("Processing: " + inputFile); currentFile = inputFile; string outputFile = options.GetOutputFileName(inputFile); string outputCFile = Path.Combine(Path.GetDirectoryName(outputFile), options.ScopePrefix + "_" + Path.GetFileName(outputFile)) + ".c"; configFile.ScopePrefix = options.ScopePrefix; configFile.FilePath = Path.GetFullPath(options.ConfigurationFile); configFile.OverwriteHashCollisions = options.OverwriteHashCollisions; //Delete the output file; we want to encourage build breaks if something goes wrong if (File.Exists(outputFile)) { File.Delete(outputFile); } if (File.Exists(outputCFile)) { File.Delete(outputCFile); } CLogFileProcessor processor = new CLogFileProcessor(configFile); CLogFullyDecodedMacroEmitter fullyDecodedMacroEmitter = new CLogFullyDecodedMacroEmitter(inputFile, sidecar); fullyDecodedMacroEmitter.AddClogModule(sidecar); CLogTraceLoggingOutputModule traceLoggingEmitter = new CLogTraceLoggingOutputModule(); fullyDecodedMacroEmitter.AddClogModule(traceLoggingEmitter); CLogDTraceOutputModule dtrace = new CLogDTraceOutputModule(); fullyDecodedMacroEmitter.AddClogModule(dtrace); CLogSysLogModule syslog = new CLogSysLogModule(); fullyDecodedMacroEmitter.AddClogModule(syslog); CLogSTDOUT stdout = new CLogSTDOUT(); fullyDecodedMacroEmitter.AddClogModule(stdout); CLogManifestedETWOutputModule manifestedEtwOutput = new CLogManifestedETWOutputModule(options.ReadOnly); fullyDecodedMacroEmitter.AddClogModule(manifestedEtwOutput); CLogLTTNGOutputModule lttngOutput = new CLogLTTNGOutputModule(inputFile, outputFile, outputFile + ".lttng.h", options.DynamicTracepointProvider); fullyDecodedMacroEmitter.AddClogModule(lttngOutput); if (!File.Exists(inputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"Invalid Input File (file doesnt exist) : {inputFile}"); throw new CLogEnterReadOnlyModeException("InvalidInputFile", CLogHandledException.ExceptionType.InvalidInputFile, null); } CLogOutputInfo outputInfo = new CLogOutputInfo(); outputInfo.OutputDirectory = options.OutputDirectory; outputInfo.OutputFileName = outputFile; outputInfo.InputFileName = inputFile; string content = File.ReadAllText(inputFile); string output = processor.ConvertFile(configFile, outputInfo, fullyDecodedMacroEmitter, content, inputFile, false); // TODO: BUGBUG - Java won't ever do this //if (!content.Contains(Path.GetFileName(outputFile))) //{ // CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"You must #include the clog output file {Path.GetFileName(outputFile)}"); // throw new CLogEnterReadOnlyModeException("MustIncludeCLogHeader", CLogHandledException.ExceptionType.SourceMustIncludeCLOGHeader, null); //} fullyDecodedMacroEmitter.FinishedProcessing(outputInfo); StringBuilder clogFile = new StringBuilder(); clogFile.AppendLine($"#ifndef CLOG_DO_NOT_INCLUDE_HEADER"); clogFile.AppendLine("#include <clog.h>"); clogFile.AppendLine($"#endif"); clogFile.Append(fullyDecodedMacroEmitter.HeaderInit); foreach (var macro in processor.MacrosInUse) { clogFile.AppendLine($"#ifndef _clog_MACRO_{macro.MacroName}"); clogFile.AppendLine($"#define _clog_MACRO_{macro.MacroName} 1"); clogFile.AppendLine( $"#define {macro.MacroName}(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))"); clogFile.AppendLine("#endif"); } clogFile.AppendLine("#ifdef __cplusplus"); clogFile.AppendLine("extern \"C\" {"); clogFile.AppendLine("#endif"); clogFile.Append(fullyDecodedMacroEmitter.HeaderFile); clogFile.AppendLine("#ifdef __cplusplus"); clogFile.AppendLine("}"); clogFile.AppendLine("#endif"); clogFile.AppendLine("#ifdef CLOG_INLINE_IMPLEMENTATION"); clogFile.AppendLine("#include \"" + Path.GetFileName(outputCFile) + "\""); clogFile.AppendLine("#endif"); // // BUGBUG : the intent in saving needs to be // 1. delete any output files early - before we start, getting us into a safe state (build breaks) // 2. save sidecars and other items that make assumptions about the emitted code // 3. save emitted code // // the goal of these orderings is to be safe in the event of failure/crash // if (!Directory.Exists(Path.GetDirectoryName(outputFile))) { Console.WriteLine("Creating Directory for Output : " + Path.GetDirectoryName(outputFile)); Directory.CreateDirectory(Path.GetDirectoryName(outputFile)); } if (sidecar.AreDirty || configFile.AreWeDirty()) { if (options.ReadOnly) { if (sidecar.AreDirty) { Console.WriteLine("Sidecar is dirty"); } if (configFile.AreWeDirty()) { Console.WriteLine("ConfigFile is dirty"); } sidecar.PrintDirtyReasons(); throw new CLogEnterReadOnlyModeException("WontWriteWhileInReadonlyMode:SideCar", CLogHandledException.ExceptionType.WontWriteInReadOnlyMode, null); } configFile.ForceDecoderCompile(); sidecar.Save(options.SidecarFile); } if (configFile.AreWeDirty() || configFile.AreWeInMarkPhase()) { if (options.ReadOnly) { throw new CLogEnterReadOnlyModeException("WontWriteWhileInReadonlyMode:ConfigFile", CLogHandledException.ExceptionType.WontWriteInReadOnlyMode, null); } Console.WriteLine("Configuration file was updated, saving..."); Console.WriteLine($" {configFile.FilePath}"); configFile.Save(false); } File.WriteAllText(outputFile, clogFile.ToString()); File.WriteAllText(outputCFile, fullyDecodedMacroEmitter.SourceFile); } currentFile = null; // // Enumerate batching modules, allowing them to save // foreach (var m in batchingModules) { CLogOutputInfo outputInfo = new CLogOutputInfo(); outputInfo.OutputDirectory = options.OutputDirectory; m.FinishedBatch(outputInfo); } } catch (CLogHandledException e) { if (null != currentFile) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"Failure in file : {currentFile}"); } e.PrintDiagnostics(options.VerboseErrors); return -2; } catch (Exception e) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"---------------------------------------------------------------------------"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"CLOG has crashed processing : {currentFile}."); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" if you're reading this, we consider seeing this message a bug. Even if the message"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" you're about to read is sufficient to diagnose, we'd like to improve the user experience"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" please consider filing a bug, with repro files and --verboseErrors"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"Exception:"); if (!options.VerboseErrors) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, " " + e.Message); return -1; } else { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, e.ToString()); } } return 0; }, err => { Console.WriteLine("Bad Args : " + err); return -1; })); }
public void TraceLineDiscovered(string sourceFile, CLogOutputInfo outputInfo, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { int hashUInt; string hash; CLogExportModuleDefination moduleSettings = decodedTraceLine.GetMacroConfigurationProfile().FindExportModule(ModuleName); decodedTraceLine.macro.DecodeUniqueId(decodedTraceLine.match, decodedTraceLine.UniqueId, out hash, out hashUInt); inline.AppendLine( $"__annotation(L\"Debug\", L\"CLOG\", L\"{hash}\"); \\"); //, msg, id, \"{sourceFile}\");"); string traceloggingLine = "TraceLoggingWrite(clog_hTrace, \"" + decodedTraceLine.UniqueId + "\""; foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; if (!arg.TypeNode.IsEncodableArg) { continue; } CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; } // // Documentation for each of the TraceLogging macros // https://docs.microsoft.com/en-gb/windows/win32/tracelogging/tracelogging-wrapper-macros // switch (node.EncodingType) { case CLogEncodingType.Int8: traceloggingLine += ",\\\n TraceLoggingInt8" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt8: traceloggingLine += ",\\\n TraceLoggingUInt8" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Int16: traceloggingLine += ",\\\n TraceLoggingInt16" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt16: traceloggingLine += ",\\\n TraceLoggingUInt16" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Int32: traceloggingLine += ",\\\n TraceLoggingInt32" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt32: traceloggingLine += ",\\\n TraceLoggingUInt32" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Int64: traceloggingLine += ",\\\n TraceLoggingInt64" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt64: traceloggingLine += ",\\\n TraceLoggingUInt64" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Pointer: traceloggingLine += ",\\\n TraceLoggingPointer" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.ByteArray: traceloggingLine += ",\\\n TraceLoggingUInt8Array" + $"({arg.MacroVariableName}, {arg.MacroVariableName}_len, \"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.ANSI_String: traceloggingLine += ",\\\n TraceLoggingString" + $"((const char *)({arg.MacroVariableName}),\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UNICODE_String: traceloggingLine += ",\\\n TraceLoggingWideString" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; } } // Emit keywords (if supplied by the user) if (moduleSettings.CustomSettings.ContainsKey("Keyword")) { traceloggingLine += ",\\\n TraceLoggingKeyword" + $"({moduleSettings.CustomSettings["Keyword"]})"; } if (moduleSettings.CustomSettings.ContainsKey("Level")) { traceloggingLine += ",\\\n TraceLoggingLevel" + $"({moduleSettings.CustomSettings["Level"]})"; } traceloggingLine += "); \\"; inline.AppendLine(traceloggingLine); }