Beispiel #1
0
        /// <summary>
        /// Returns information about the PE file.
        /// </summary>
        /// <param name="isVirtual">the memory layout of the module</param>
        /// <param name="address">module base address</param>
        /// <param name="size">module size</param>
        /// <param name="pdbFileInfo">the pdb record or null</param>
        /// <param name="flags">module flags</param>
        ///
        /// <returns>PEImage instance or null</returns>
        private PEImage GetPEInfo(bool isVirtual, ulong address, ulong size, ref PdbFileInfo pdbFileInfo, ref Module.Flags flags)
        {
            Stream stream = MemoryService.CreateMemoryStream(address, size);

            try
            {
                stream.Position = 0;
                var peImage = new PEImage(stream, leaveOpen: false, isVirtual);
                if (peImage.IsValid)
                {
                    flags      |= Module.Flags.IsPEImage;
                    flags      |= peImage.IsManaged ? Module.Flags.IsManaged : Module.Flags.None;
                    pdbFileInfo = peImage.DefaultPdb?.ToPdbFileInfo();
                    flags      &= ~(Module.Flags.IsLoadedLayout | Module.Flags.IsFileLayout);
                    flags      |= isVirtual ? Module.Flags.IsLoadedLayout : Module.Flags.IsFileLayout;
                    return(peImage);
                }
                else
                {
                    Trace.TraceError($"GetPEInfo: PE invalid {address:X16} isVirtual {isVirtual}");
                }
            }
            catch (Exception ex) when(ex is BadImageFormatException || ex is EndOfStreamException || ex is IOException)
            {
                Trace.TraceError($"GetPEInfo: {address:X16} isVirtual {isVirtual} exception {ex.Message}");
            }
            return(null);
        }
Beispiel #2
0
        public static void BuildCodeAuthor(CodeAuthorInfo codeAuthor, PdbFileInfo pdbFile, List <GitFileInfo> gitFileInfos)
        {
            var gitFiles = gitFileInfos.Where(q => q.File == pdbFile.File && q.Line >= pdbFile.LineStart && q.Line <= pdbFile.LineEnd);

            foreach (var file in gitFiles)
            {
                codeAuthor.AddAuthor(pdbFile.Namespace, pdbFile.Class, pdbFile.Method, file.Author, file.CommitTime);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Returns the PE file's PDB info from the debug directory
        /// </summary>
        /// <param name="address">module base address</param>
        /// <param name="size">module size</param>
        /// <param name="pdbFileInfo">the pdb record or null</param>
        /// <param name="flags">module flags</param>
        /// <returns>PEImage instance or null</returns>
        internal PEImage GetPEInfo(ulong address, ulong size, ref PdbFileInfo pdbFileInfo, ref Module.Flags flags)
        {
            PEImage peImage = null;

            // None of the modules that lldb (on either Linux/MacOS) provides are PEs
            if (Target.Host.HostType != HostType.Lldb)
            {
                // First try getting the PE info as load layout (native Windows DLLs and most managed PEs on Linux/MacOS).
                peImage = GetPEInfo(isVirtual: true, address: address, size: size, pdbFileInfo: ref pdbFileInfo, flags: ref flags);
                if (peImage == null)
                {
                    if (Target.OperatingSystem != OSPlatform.Windows)
                    {
                        // Then try getting the PE info as file layout (some managed PEs on Linux/MacOS).
                        peImage = GetPEInfo(isVirtual: false, address: address, size: size, pdbFileInfo: ref pdbFileInfo, flags: ref flags);
                    }
                }
            }
            return(peImage);
        }
Beispiel #4
0
        public void FormatLog(CreateLogItemRequest logRequest)
        {
            _traceLogger.Verbose("Received a log request to format.");

            var handled = false;

            var fullMessageBuilder = Config.GetValue("Extensions:SourceBack:WithMarkdownPrefix", false) ? new StringBuilder("!!!MARKDOWN_MODE!!!") : new StringBuilder();

            if (logRequest.Level == LogLevel.Error || logRequest.Level == LogLevel.Fatal)
            {
                _traceLogger.Info($"Parsing exception stacktrace in log message with {logRequest.Level} level...");

                foreach (var line in logRequest.Text.Split(new string[] { Environment.NewLine, "\n" }, StringSplitOptions.None))
                {
                    _traceLogger.Verbose("Parsing line as stacktrace frame:" + Environment.NewLine + line);

                    var lineWithoutMarkdown = line.Replace("`", @"\`").Replace("__", @"\__");

                    var match = Regex.Match(line, @"\s+\w+\s.*\s\w+\s(.*):\w+\s(\d+)");

                    if (match.Success)
                    {
                        var sourcePath = match.Groups[1].Value;
                        var lineIndex  = int.Parse(match.Groups[2].Value) - 1;

                        _traceLogger.Info($"It matches stacktrace. SourcePath: {sourcePath} - LineIndex: {lineIndex}");

                        var sectionBuilder = new StringBuilder();

                        try
                        {
                            lock (_pdbsLock)
                            {
                                if (_pdbs == null)
                                {
                                    _pdbs = new List <PdbFileInfo>();

                                    var currentDirectory = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).FullName;

                                    _traceLogger.Verbose($"Exploring {currentDirectory} directory for PDB files");

                                    var pdbFilePaths = DirectoryScanner.FindPdbPaths(currentDirectory);

                                    foreach (var pdbFilePath in pdbFilePaths)
                                    {
                                        var pdbFileInfo = new PdbFileInfo(pdbFilePath);

                                        try
                                        {
                                            pdbFileInfo.LoadSourceLinks();
                                        }
                                        catch (NotSupportedException exp)
                                        {
                                            _traceLogger.Warn($"{pdbFilePath} format is not supported. Try to change it to 'portable' or 'embedded'. {Environment.NewLine}{exp}");
                                        }

                                        _pdbs.Add(pdbFileInfo);
                                    }
                                }
                            }

                            var pdb = _pdbs.FirstOrDefault(p => p.SourceLinks.ContainsKey(sourcePath));

                            // if defined
                            if (pdb != null)
                            {
                                var content = pdb.GetSourceLinkContent(sourcePath);

                                // if available
                                if (content != null)
                                {
                                    var contentLines = content.Replace("\r\n", "\n").Split(new string[] { "\n" }, StringSplitOptions.None);

                                    // up
                                    var offsetUp             = Config.GetValue("Extensions:SourceBack:OffsetUp", 4);
                                    var takeFromIndex        = lineIndex - offsetUp;
                                    var missingTopLinesCount = 0;
                                    if (takeFromIndex < 0)
                                    {
                                        missingTopLinesCount = Math.Abs(takeFromIndex);
                                        takeFromIndex        = 0;
                                    }

                                    // down
                                    var offsetDown  = Config.GetValue("Extensions:SourceBack:OffsetDown", 2);
                                    var takeToIndex = lineIndex + offsetDown;
                                    if (takeToIndex > contentLines.Length - 1)
                                    {
                                        takeToIndex = contentLines.Length - 1;
                                    }

                                    // and add whitespace to replace it with ►
                                    var frameContentLines = contentLines.Skip(takeFromIndex + 1).Take(takeToIndex - takeFromIndex).Select(l => " " + l).ToList();

                                    var hightlightFrameLineIndex = offsetUp - missingTopLinesCount - 1;
                                    frameContentLines[hightlightFrameLineIndex] = "►" + frameContentLines[hightlightFrameLineIndex].Remove(0, 1);
                                    var frameContent = string.Join(Environment.NewLine, frameContentLines);

                                    sectionBuilder.AppendLine($"```{Environment.NewLine}{frameContent}{Environment.NewLine}```");
                                }
                            }
                        }
                        catch (Exception exp)
                        {
                            sectionBuilder.AppendLine($"```{Environment.NewLine}SourceBack error: {exp}{Environment.NewLine}```");
                        }

                        handled = true;

                        if (!string.IsNullOrEmpty(sectionBuilder.ToString()))
                        {
                            var sourceFileName   = Path.GetFileName(sourcePath);
                            var lineWithEditLink = lineWithoutMarkdown.Replace("\\" + sourceFileName, $"\\\\**{sourceFileName}**");
                            lineWithEditLink = lineWithEditLink.Remove(lineWithEditLink.Length - match.Groups[2].Value.Length);

                            var openWith = Config.GetValue("Extensions:SourceBack:OpenWith", "vscode");
                            switch (openWith.ToLowerInvariant())
                            {
                            case "vscode":
                                lineWithEditLink += $"[{match.Groups[2].Value}](vscode://file/{sourcePath.Replace("\\", "/")}:{lineIndex + 1})";
                                break;
                            }

                            fullMessageBuilder.AppendLine($"{lineWithEditLink}{Environment.NewLine}{sectionBuilder}");
                        }
                        else
                        {
                            fullMessageBuilder.AppendLine(lineWithoutMarkdown);
                        }
                    }
                    else
                    {
                        fullMessageBuilder.AppendLine(lineWithoutMarkdown);
                    }
                }
            }

            if (handled)
            {
                logRequest.Text = fullMessageBuilder.ToString();
            }
        }
        private static void GetPdbInfo(List <PdbFileInfo> infos, string xml)
        {
            XmlDocument xmlDocument = new System.Xml.XmlDocument();

            xmlDocument.LoadXml(xml.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", ""));

            var fileNodes = xmlDocument.SelectNodes("/symbols/files/file");
            Dictionary <string, string> srcFiles = new Dictionary <string, string>();

            foreach (XmlNode node in fileNodes)
            {
                var key   = node.Attributes["id"].Value;
                var value = node.Attributes["name"].Value;
                srcFiles[key] = value;
            }
            var methodNodes = xmlDocument.SelectNodes("/symbols/methods/method");

            foreach (XmlNode node in methodNodes)
            {
                var cname      = node.Attributes["containingType"].Value;
                var @namespace = cname.Substring(0, cname.LastIndexOf('.'));
                var className  = cname.Substring(cname.LastIndexOf('.') + 1);
                var mname      = node.Attributes["name"].Value;

                var entrys    = node.SelectNodes("sequencePoints/entry");
                int startLine = int.MaxValue;
                int endLine   = 0;
                var file      = "";
                foreach (XmlNode entry in entrys)
                {
                    bool isHidden = false;
                    int  sl = 0, el = 0;
                    foreach (XmlAttribute att in entry.Attributes)
                    {
                        if (att.Name == "hidden")
                        {
                            isHidden = true;
                        }
                        else if (att.Name == "startLine")
                        {
                            sl = int.Parse(att.Value);
                        }
                        else if (att.Name == "endLine")
                        {
                            el = int.Parse(att.Value);
                        }
                        else if (att.Name == "document")
                        {
                            var fileId = entry.Attributes["document"].Value;
                            file = srcFiles[fileId];
                        }
                    }
                    if (isHidden)
                    {
                        continue;
                    }
                    if (startLine > sl)
                    {
                        startLine = sl;
                    }
                    if (endLine < el)
                    {
                        endLine = el;
                    }
                }
                if (endLine > 0)
                {
                    var info = new PdbFileInfo()
                    {
                        Namespace = @namespace,
                        Class     = className,
                        Method    = mname,
                        File      = file,
                        LineStart = startLine,
                        LineEnd   = endLine
                    };
                    infos.Add(info);
                }
            }
        }