/// <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); }
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); } }
/// <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); }
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); } } }