// Return values: // 0 - success // >= 100 - failure public static int Main(string[] args) { if (args.Length < 2) { return(Usage()); } string command = args[0].ToUpper(); string assemblyName = args[1]; int methodToPrep = -1; // For PREPONE, PREPALL. For PREPALL, this is the first method to prep. Visitor v = null; int dashIndex = command.IndexOf('-'); string rootCommand = dashIndex < 0 ? command : command.Substring(0, dashIndex); switch (rootCommand) { case "DRIVEALL": case "COUNT": if (args.Length < 2) { Console.WriteLine("ERROR: too few arguments"); return(Usage()); } else if (args.Length > 2) { Console.WriteLine("ERROR: too many arguments"); return(Usage()); } if (command == "DRIVEALL") { return(PMIDriver.PMIDriver.Drive(assemblyName)); } v = new Counter(); break; case "PREPALL": case "PREPONE": if (args.Length < 3) { methodToPrep = 0; } else if (args.Length > 3) { Console.WriteLine("ERROR: too many arguments"); return(Usage()); } else { try { methodToPrep = Convert.ToInt32(args[2]); } catch (System.FormatException) { Console.WriteLine("ERROR: illegal method number"); return(Usage()); } } bool all = command.IndexOf("ALL") > 0; bool verbose = !(command.IndexOf("QUIET") > 0); bool time = verbose || command.IndexOf("TIME") > 0; if (all) { v = new PrepareAll(methodToPrep, verbose, time); } else { v = new PrepareOne(methodToPrep, verbose, time); } break; default: Console.WriteLine("ERROR: Unknown command {0}", command); return(Usage()); } // We want to handle specifying a "load path" where assemblies can be found. // The environment variable PMIPATH is a semicolon-separated list of paths. If the // Assembly can't be found by the usual mechanisms, our Assembly ResolveEventHandler // will be called, and we'll probe on the PMIPATH list. AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandler); Worker w = new Worker(v); int result = 0; string msg = "a file"; #if NETCOREAPP2_1 msg += " or a directory"; if (Directory.Exists(assemblyName)) { EnumerationOptions options = new EnumerationOptions(); options.RecurseSubdirectories = true; IEnumerable <string> exeFiles = Directory.EnumerateFiles(assemblyName, "*.exe", options); IEnumerable <string> dllFiles = Directory.EnumerateFiles(assemblyName, "*.dll", options); IEnumerable <string> allFiles = exeFiles.Concat(dllFiles); result = w.Work(allFiles); } else #endif if (File.Exists(assemblyName)) { result = w.Work(assemblyName); } else { Console.WriteLine($"ERROR: {assemblyName} is not {msg}"); result = 101; } return(result); }
// Return values: // 0 - success // >= 100 - failure public static int Main(string[] args) { if (args.Length < 2) { return(Usage()); } // TlsOverPerCoreLockedStacksArrayPool.Return registers Gen2GcCallbackFunc on Gen2GcCallback. // Gen2GcCallbackFunc is then called from Gen2GcCallback finalizer after a gc. // For output determinism we force the registration of Gen2GcCallbackFunc and then force a gc // so that Gen2GcCallbackFunc is jitted. EnsureGen2GcCallbackFuncIsJitted(); string command = args[0].ToUpper(); string assemblyName = args[1]; int methodToPrep = -1; // For PREPONE, PREPALL. For PREPALL, this is the first method to prep. Visitor v = null; int dashIndex = command.IndexOf('-'); string rootCommand = dashIndex < 0 ? command : command.Substring(0, dashIndex); bool verbose = !(command.IndexOf("QUIET") > 0); switch (rootCommand) { case "DRIVEALL": case "COUNT": if (args.Length < 2) { Console.WriteLine("ERROR: too few arguments"); return(Usage()); } else if (args.Length > 2) { Console.WriteLine("ERROR: too many arguments"); return(Usage()); } if (rootCommand == "DRIVEALL") { string pmiEnv = Environment.GetEnvironmentVariable("PMIENV"); Dictionary <string, string> environment = new Dictionary <string, string>(); if ((pmiEnv != null) && (pmiEnv.Length != 0)) { Regex rx = new Regex(@"^(?:(?<name>[\w_]+)=(?<value>[^;]+);)*(?<lastname>[\w_]+)=(?<lastvalue>[^$]+)$"); MatchCollection matches = rx.Matches(pmiEnv); if (matches.Count != 1) { Console.WriteLine("ERROR: PMIENV format is incorrect"); return(Usage()); } Match match = matches[0]; GroupCollection groups = match.Groups; for (int i = 0; i < groups["name"].Captures.Count; ++i) { environment[groups["name"].Captures[i].Value] = groups["value"].Captures[i].Value; } environment[groups["lastname"].Captures[0].Value] = groups["lastvalue"].Captures[0].Value; } return(PMIDriver.PMIDriver.Drive(assemblyName, verbose, environment)); } v = new Counter(); break; case "PREPALL": case "PREPONE": if (args.Length < 3) { methodToPrep = 0; } else if (args.Length > 3) { Console.WriteLine("ERROR: too many arguments"); return(Usage()); } else { try { methodToPrep = Convert.ToInt32(args[2]); } catch (System.FormatException) { Console.WriteLine("ERROR: illegal method number"); return(Usage()); } } bool all = command.IndexOf("ALL") > 0; bool time = verbose || command.IndexOf("TIME") > 0; if (all) { v = new PrepareAll(methodToPrep, verbose, time); } else { v = new PrepareOne(methodToPrep, verbose, time); } break; default: Console.WriteLine("ERROR: Unknown command {0}", command); return(Usage()); } bool runCctors = command.IndexOf("CCTORS") > 0; bool logTailCallDecisions = command.IndexOf("TAILCALLS") > 0; bool logInliningDecisions = command.IndexOf("INLINES") > 0; if (logTailCallDecisions) { JITDecisionEventListener.s_enabledEvents.Add("MethodJitTailCallSucceeded"); JITDecisionEventListener.s_enabledEvents.Add("MethodJitTailCallFailed"); } if (logInliningDecisions) { JITDecisionEventListener.s_enabledEvents.Add("MethodJitInliningSucceeded"); JITDecisionEventListener.s_enabledEvents.Add("MethodJitInliningFailed"); } using var eventListener = logTailCallDecisions || logInliningDecisions ? new JITDecisionEventListener() : null; Worker w = new Worker(v, runCctors); int result = 0; string msg = "a file"; #if NETCOREAPP msg += " or a directory"; if (Directory.Exists(assemblyName)) { EnumerationOptions options = new EnumerationOptions(); options.RecurseSubdirectories = true; IEnumerable <string> exeFiles = Directory.EnumerateFiles(assemblyName, "*.exe", options); IEnumerable <string> dllFiles = Directory.EnumerateFiles(assemblyName, "*.dll", options); IEnumerable <string> allFiles = exeFiles.Concat(dllFiles); result = w.Work(allFiles); } else #endif if (File.Exists(assemblyName)) { result = w.Work(assemblyName); } else { Console.WriteLine($"ERROR: {assemblyName} is not {msg}"); result = 101; } return(result); }