Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
    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);
    }