internal override ICorDebug.IMetadataImport GetMetadataImport() { if (Revision != _runtime.Revision) { ClrDiagnosticsException.ThrowRevisionError(Revision, _runtime.Revision); } if (_metadata != null) { return(_metadata); } _metadata = _runtime.GetMetadataImport(_address); return(_metadata); }
internal override ICorDebug.IMetadataImport GetMetadataImport() { if (Revision != _runtime.Revision) { ClrDiagnosticsException.ThrowRevisionError(Revision, _runtime.Revision); } if (_metadata != null) { return(_metadata); } ulong module = GetDomainModule(null); if (module == 0) { return(null); } _metadata = _runtime.GetMetadataImport(module); return(_metadata); }
private static int MainWorker(string[] args) { string outputFile = null; int exceptionExitCode = 1; try { float decayToZeroHours = 0; bool forceGC = false; bool processDump = false; string inputSpec = null; int minSecForTrigger = -1; var dumper = new GCHeapDumper(Console.Out); for (int curArgIdx = 0; curArgIdx < args.Length; curArgIdx++) { var arg = args[curArgIdx].Trim(); if (string.IsNullOrWhiteSpace(arg)) { continue; } if (arg.StartsWith("/")) { // This is not for external use. On 64 bit systems we need to do the GetProcess in a 64 bit process. if (string.Compare(arg, "/GetProcessesWithGCHeaps", StringComparison.OrdinalIgnoreCase) == 0) { foreach (var processInfo in GCHeapDump.GetProcessesWithGCHeaps().Values) { Console.WriteLine("{0}{1} {2}", processInfo.UsesDotNet ? 'N' : ' ', processInfo.UsesJavaScript ? 'J' : ' ', processInfo.ID); } return(0); } else if (string.Compare(arg, "/dumpData", StringComparison.OrdinalIgnoreCase) == 0) { dumper.DumpData = true; } else if (string.Compare(arg, "/processDump", StringComparison.OrdinalIgnoreCase) == 0) { processDump = true; } else if (string.Compare(arg, "/forceGC", StringComparison.OrdinalIgnoreCase) == 0) { forceGC = true; } else if (string.Compare(arg, "/freeze", StringComparison.OrdinalIgnoreCase) == 0) { dumper.Freeze = true; } else if (string.Compare(arg, 0, "/MaxDumpCountK=", 0, 15, StringComparison.OrdinalIgnoreCase) == 0) { string value = arg.Substring(15); if (!int.TryParse(value, out dumper.MaxDumpCountK)) { Console.WriteLine("Could not parse MaxDumpCount argument: {0}", value); goto Usage; } } else if (string.Compare(arg, 0, "/MaxNodeCountK=", 0, 15, StringComparison.OrdinalIgnoreCase) == 0) { string value = arg.Substring(15); if (!int.TryParse(value, out dumper.MaxNodeCountK)) { Console.WriteLine("Could not parse MaxNodeCount argument: {0}", value); goto Usage; } } else if (string.Compare(arg, "/SaveETL", StringComparison.OrdinalIgnoreCase) == 0) { dumper.SaveETL = true; } else if (string.Compare(arg, "/UseETW", StringComparison.OrdinalIgnoreCase) == 0) { dumper.UseETW = true; } else if (arg.StartsWith("/DecayToZeroHours:", StringComparison.OrdinalIgnoreCase)) { decayToZeroHours = float.Parse(arg.Substring(18)); } else if (arg.StartsWith("/StopOnPerfCounter:", StringComparison.OrdinalIgnoreCase)) { string spec = arg.Substring(19); bool done = false; using (var trigger = new PerformanceCounterTrigger(spec, decayToZeroHours, Console.Out, delegate(PerformanceCounterTrigger t) { done = true; }) { MinSecForTrigger = minSecForTrigger }) { for (int i = 0; !done; i++) { if (i % 10 == 2) { Console.WriteLine("[{0}]", trigger.Status); Console.Out.Flush(); } Thread.Sleep(1000); } } Console.WriteLine("[PerfCounter Triggered: {0}]", spec); return(0); } else if (arg.StartsWith("/MinSecForTrigger:", StringComparison.OrdinalIgnoreCase)) { minSecForTrigger = int.Parse(arg.Substring(18)); } else if (arg.StartsWith("/PromotedBytesThreshold:", StringComparison.OrdinalIgnoreCase)) { dumper.CrossGeneration = true; string spec = arg.Substring(24); dumper.PromotedBytesThreshold = Convert.ToUInt64(spec); Console.WriteLine("Promoted Bytes Threshold: " + dumper.PromotedBytesThreshold); } else if (arg.StartsWith("/GenerationToTrigger:", StringComparison.OrdinalIgnoreCase)) { string spec = arg.Substring(21); dumper.GenerationToTrigger = Convert.ToInt32(spec); if (dumper.GenerationToTrigger < 0 || dumper.GenerationToTrigger > 2) { Console.WriteLine("Invalid value for /GenerationToTrigger. Value must be between 0 and 2 inclusively."); goto Usage; } Console.WriteLine("Generation To Trigger: " + dumper.GenerationToTrigger); } else { Console.WriteLine("Unknown qualifier: {0}", arg); goto Usage; } } else { if (inputSpec == null) { inputSpec = arg; } else if (outputFile == null) { outputFile = arg; } else { Console.WriteLine("Extra parameter: {0}", arg); return(-1); } } } if (inputSpec == null) { goto Usage; } if (dumper.DumpData) { Console.WriteLine("WARNING: Currently DumpData is not supported"); } if (!forceGC) { if (outputFile == null) { outputFile = Path.ChangeExtension(inputSpec, ".gcDump"); } // This avoids file sharing issues, and also ensures that old files are not left behind. if (File.Exists(outputFile)) { File.Delete(outputFile); } } if (processDump) { Console.WriteLine("Creating heap dump {0} from process dump {1}.", outputFile, inputSpec); dumper.DumpHeapFromProcessDump(inputSpec, outputFile); // TODO FIX NOW REMOVE GCHeap.DumpHeapFromProcessDump(inputSpec, outputFile, Console.Out); } else { var processID = GetProcessID(inputSpec); if (processID < 0) { Console.WriteLine("Error: Could not find process {0}", inputSpec); return(4); } if (PointerSizeForProcess(processID) != Marshal.SizeOf(typeof(IntPtr))) { throw new ApplicationException("The debuggee process has a different bitness (32-64) than the debugger."); } if (forceGC) { dumper.ForceGC(processID); return(0); } Console.WriteLine("Dumping process {0} with id {1}.", inputSpec, processID); dumper.DumpLiveHeap(processID, outputFile); } if (!File.Exists(outputFile)) { Console.WriteLine("No output file {0} created.", outputFile); return(2); } return(0); Usage: Console.WriteLine("Usage: HeapDump [/MaxDumpCountK=n /Freeze] ProcessIdOrName OutputHeapDumpFile"); Console.WriteLine("Usage: HeapDump [/MaxDumpCountK=n] /processDump DumpFile OutputHeapDumpFile"); Console.WriteLine("Usage: HeapDump /forceGC ProcessIdOrName"); return(1); } catch (Exception e) { ClrDiagnosticsException diagException = e as ClrDiagnosticsException; if ((diagException != null) && ((uint)diagException.HResult == 0x80070057)) { exceptionExitCode = 3; Console.WriteLine("HeapDump Error: Unable to open process dump. HeapDump only supports converting Windows process dumps."); } if (e is ApplicationException) { Console.WriteLine("HeapDump Error: {0}", e.Message); } else { Console.WriteLine("HeapDump Error ({0}): {1}", e.HResult, e.ToString()); } if (outputFile != null) { try { File.Delete(outputFile); } catch (Exception) { } } } return(exceptionExitCode); }