Example #1
0
        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");
        }
Example #2
0
        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)}\"");
        }
Example #3
0
 public void FinishedProcessing(CLogOutputInfo outputInfo, StringBuilder header, StringBuilder sourceFile)
 {
 }
Example #4
0
        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(");");
        }
Example #5
0
        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(");");
        }
Example #6
0
        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);
        }
Example #7
0
        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);
            }
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }