diff --git a/src/MICore/JsonLaunchOptions.cs b/src/MICore/JsonLaunchOptions.cs index 064ede7c9..2033c1ff3 100644 --- a/src/MICore/JsonLaunchOptions.cs +++ b/src/MICore/JsonLaunchOptions.cs @@ -299,6 +299,12 @@ public partial class LaunchOptions : BaseOptions [JsonProperty("externalConsole", DefaultValueHandling = DefaultValueHandling.Ignore)] public bool? ExternalConsole { get; set; } + /// + /// If true, disables debuggee console redirection that is required for Integrated Terminal support. + /// + [JsonProperty("avoidWindowsConsoleRedirection", DefaultValueHandling = DefaultValueHandling.Ignore)] + public bool? AvoidWindowsConsoleRedirection { get; set; } + #endregion #region Constructors diff --git a/src/MICore/LaunchOptions.cs b/src/MICore/LaunchOptions.cs index be4f71d81..9bd5e690b 100644 --- a/src/MICore/LaunchOptions.cs +++ b/src/MICore/LaunchOptions.cs @@ -1805,10 +1805,83 @@ protected void InitializeCommonOptions(Xml.LaunchOptions.BaseLaunchOptions sourc this.Environment = new ReadOnlyCollection(GetEnvironmentEntries(source.Environment)); } + private static List TryAddWindowsDebuggeeConsoleRedirection(List arguments) + { + if (PlatformUtilities.IsWindows()) // Only do this on Windows + { + bool stdInRedirected = false; + bool stdOutRedirected = false; + bool stdErrRedirected = false; + + if (arguments != null) + { + foreach (string rawArgument in arguments) + { + string argument = rawArgument.TrimStart(); + if (argument.TrimStart().StartsWith("2>", StringComparison.Ordinal)) + { + stdErrRedirected = true; + } + if (argument.TrimStart().StartsWith("1>", StringComparison.Ordinal) || argument.TrimStart().StartsWith(">", StringComparison.Ordinal)) + { + stdOutRedirected = true; + } + if (argument.TrimStart().StartsWith("0>", StringComparison.Ordinal) || argument.TrimStart().StartsWith("<", StringComparison.Ordinal)) + { + stdInRedirected = true; + } + } + } + + // If one (or more) are not redirected, then add redirection + if (!stdInRedirected || !stdOutRedirected || !stdErrRedirected) + { + int argLength = arguments.Count; + List argList = new List(argLength + 3); + if (arguments != null) + { + argList.AddRange(arguments); + } + + if (!stdErrRedirected) + { + argList.Add("2>CON"); + } + + if (!stdOutRedirected) + { + argList.Add("1>CON"); + } + + if (!stdInRedirected) + { + argList.Add(" args = launch.Args; + + if (Host.GetHostUIIdentifier() == HostUIIdentifier.VSCode && + HostRunInTerminal.IsRunInTerminalAvailable() && + !launch.ExternalConsole.GetValueOrDefault(false) && + string.IsNullOrEmpty(launch.CoreDumpPath) && + !launch.AvoidWindowsConsoleRedirection.GetValueOrDefault(false) && + !(this is PipeLaunchOptions)) // Make sure we are not doing a PipeLaunch + { + args = TryAddWindowsDebuggeeConsoleRedirection(args); + } + + this.ExeArguments = ParseArguments(args); this.WorkingDirectory = launch.Cwd ?? String.Empty; this.CoreDumpPath = launch.CoreDumpPath; @@ -2046,7 +2119,8 @@ protected static string ParseArguments(IEnumerable arguments, bool quote return String.Empty; } - private static char[] s_ARGUMENT_SEPARATORS = new char[] { ' ', '\t' }; + // gdb does not like parenthesis without being quoted + private static char[] s_ARGUMENT_SEPARATORS = { ' ', '\t', '(', ')' }; protected static string QuoteArgument(string arg) { // If its not quoted and it has an argument separater, then quote it. diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index c4fbcfa98..bff95bdef 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -2226,9 +2226,18 @@ public bool MapCompileTimeSrcToCurrentSrc(string compilerSrc, out string current if (hostOSCompilerSrc.StartsWith(e.CompileTimePath, comp)) { var file = hostOSCompilerSrc.Substring(e.CompileTimePath.Length); - if (string.IsNullOrEmpty(file)) // matched the whole directory string + if (string.IsNullOrEmpty(file)) // matched the whole string { - break; // use default + if (hostOSCompilerSrc.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) || hostOSCompilerSrc.EndsWith(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal)) + { + break; // directory matched, use default. + } + else + { + // Is a file + currentName = e.EditorPath; // return the matches compile time path + return true; + } } // must do the path break at a directory boundry, i.e. at a '\' or '/' char char firstFilechar = file[0]; diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 32381d9c0..6be6f1aa3 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -53,7 +53,6 @@ internal class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEven private int m_firstStoppingEvent; private uint m_breakCounter = 0; private bool m_isAttach; - private bool m_isCoreDump; private bool m_isStopped = false; private bool m_isStepping = false; @@ -174,7 +173,7 @@ private bool ValidateProgramPath(ref string program) return true; } - private void SetCommonDebugSettings(Dictionary args, out int sourceFileMappings) + private void SetCommonDebugSettings(Dictionary args) { // Save the Just My Code setting. We will set it once the engine is created. m_sessionConfig.JustMyCode = args.GetValueAsBool("justMyCode").GetValueOrDefault(m_sessionConfig.JustMyCode); @@ -210,26 +209,26 @@ private void SetCommonDebugSettings(Dictionary args, out int sou m_logger.SetLoggingConfiguration(LoggingCategory.AdapterResponse, traceResponse.Value); } } + } + + private void SetCommonMISettings(Dictionary args) + { + string miMode = args.GetValueAsString("MIMode"); - sourceFileMappings = 0; - Dictionary sourceFileMap = null; + // If MIMode is not provided, set default to GDB. + if (string.IsNullOrEmpty(miMode)) + { + args["MIMode"] = "gdb"; + } + else { - dynamic sourceFileMapProperty = args.GetValueAsObject("sourceFileMap"); - if (sourceFileMapProperty != null) + // If lldb and there is no miDebuggerPath, set it. + bool hasMiDebuggerPath = args.ContainsKey("miDebuggerPath"); + if (miMode == "lldb" && !hasMiDebuggerPath) { - try - { - sourceFileMap = sourceFileMapProperty.ToObject>(); - sourceFileMappings = sourceFileMap.Count; - } - catch (Exception e) - { - SendMessageEvent(MessagePrefix.Error, "Configuration for 'sourceFileMap' has a format error and will be ignored.\nException: " + e.Message); - sourceFileMap = null; - } + args["miDebuggerPath"] = MILaunchOptions.GetLLDBMIPath(); } } - m_pathConverter.m_pathMapper = new PathMapper(sourceFileMap); } private ProtocolException VerifyLocalProcessId(string processId, string telemetryEventName, out int pid) @@ -310,14 +309,11 @@ private static long FileTimeToPosix(FILETIME ft) public void BeforeContinue() { - if (!m_isCoreDump) - { - m_isStepping = false; - m_isStopped = false; - m_variableManager.Reset(); - m_frameHandles.Reset(); - m_threadFrameEnumInfos.Clear(); - } + m_isStepping = false; + m_isStopped = false; + m_variableManager.Reset(); + m_frameHandles.Reset(); + m_threadFrameEnumInfos.Clear(); } public void Stopped(IDebugThread2 thread) @@ -774,8 +770,7 @@ protected override void HandleLaunchRequestAsync(IRequestResponder(StringComparer.Ordinal); - properties.Add(DebuggerTelemetry.TelemetryIsCoreDump, m_isCoreDump); - if (debugServerUsed) - { - properties.Add(DebuggerTelemetry.TelemetryUsesDebugServer, isOpenOCD ? "openocd" : "other"); - } if (flags.HasFlag(enum_LAUNCH_FLAGS.LAUNCH_NODEBUG)) { properties.Add(DebuggerTelemetry.TelemetryIsNoDebug, true); } - properties.Add(DebuggerTelemetry.TelemetryVisualizerFileUsed, visualizerFileUsed); - properties.Add(DebuggerTelemetry.TelemetrySourceFileMappings, sourceFileMappings); properties.Add(DebuggerTelemetry.TelemetryMIMode, mimode); DebuggerTelemetry.ReportTimedEvent(telemetryEventName, DateTime.Now - launchStartTime, properties); @@ -930,8 +907,6 @@ protected override void HandleAttachRequestAsync(IRequestResponder(StringComparer.Ordinal); properties.Add(DebuggerTelemetry.TelemetryMIMode, mimode); - properties.Add(DebuggerTelemetry.TelemetryVisualizerFileUsed, visualizerFileUsed); - properties.Add(DebuggerTelemetry.TelemetrySourceFileMappings, sourceFileMappings); DebuggerTelemetry.ReportTimedEvent(telemetryEventName, DateTime.Now - attachStartTime, properties); success = true; @@ -1252,10 +1200,7 @@ protected override void HandleStepInRequestAsync(IRequestResponderGenerates launch options for launching the mi engine. internal static class MILaunchOptions { - private const string DebuggerCommandMacro = "${debuggerCommand}"; - private enum RequestType - { - Launch, - Attach - } - - private enum LaunchOptionType - { - Local, - Pipe, - Tcp, - } - - [JsonObject] - private class JsonCommand - { - [JsonProperty] - public bool IgnoreFailures { get; set; } - - [JsonProperty] - public string Description { get; set; } - - [JsonProperty] - public string Text { get; set; } - } - - - [JsonObject] - private class JsonBaseLaunchOptions - { - [JsonProperty] - [JsonRequired] - public string Name { get; set; } - - [JsonProperty] - [JsonRequired] - public string Type { get; set; } - - [JsonProperty] - public JsonCommand[] SetupCommands { get; set; } - - [JsonProperty] - public JsonCommand[] CustomLaunchSetupCommands { get; set; } - - [JsonProperty] - public string LaunchCompleteCommand { get; set; } - - [JsonProperty] - [JsonRequired] - [JsonConverter(typeof(StringEnumConverter))] - public RequestType Request { get; set; } - - [JsonProperty] - public string[] Args { get; set; } - - [JsonProperty] - public string Cwd { get; set; } - - [JsonProperty] - public string VisualizerFile { get; set; } - - [JsonProperty] - public bool ShowDisplayString { get; set; } - - [JsonProperty] - public bool StopAtEntry { get; set; } - - [JsonProperty] - public string TargetArchitecture { get; set; } - - [JsonProperty] - public string AdditionalSOLibSearchPath { get; set; } - - [JsonProperty] - public string MIMode { get; set; } - - [JsonProperty] - public string CoreDumpPath { get; set; } - - [JsonProperty] - public SymbolLoadInfo SymbolLoadInfo { get; set; } - } - - [JsonObject] - private class EnvironmentEntry - { - [JsonProperty] - [JsonRequired] - public string Name { get; set; } - - [JsonProperty] - [JsonRequired] - public string Value { get; set; } - } - - - [JsonObject] - private class JsonLocalLaunchOptions : JsonBaseLaunchOptions - { - [JsonProperty] - public string MIDebuggerPath { get; set; } - - [JsonProperty] - public string MIDebuggerArgs { get; set; } - - [JsonProperty] - public string MIDebuggerServerAddress { get; set; } - - [JsonProperty] - public int ProcessId { get; set; } - - [JsonProperty] - public EnvironmentEntry[] Environment { get; set; } - - [JsonProperty] - public Dictionary Env { get; } = new Dictionary(); - - [JsonProperty] - public string DebugServerPath { get; set; } - - [JsonProperty] - public string DebugServerArgs { get; set; } - - [JsonProperty] - public string ServerStarted { get; set; } - - [JsonProperty] - public bool FilterStdout { get; set; } - - [JsonProperty] - public bool FilterStderr { get; set; } - - [JsonProperty] - public int ServerLaunchTimeout { get; set; } - - [JsonProperty] - public bool ExternalConsole { get; set; } - - [JsonProperty] - public bool AvoidWindowsConsoleRedirection { get; set; } - } - - [JsonObject] - private class SymbolLoadInfo - { - [JsonProperty] - public bool? LoadAll { get; set; } - - [JsonProperty] - public string ExceptionList { get; set; } - } - - [JsonObject] - private class JsonPipeLaunchOptions : JsonBaseLaunchOptions - { - [JsonProperty] - [JsonRequired] - public JsonPipeTransport PipeTransport { get; set; } - - [JsonProperty] - public string ProcessId { get; set; } - } - - [JsonObject] - private class JsonPipeTransportOptions - { - [JsonProperty] - [JsonRequired] - public string PipeCwd { get; set; } - - [JsonProperty] - [JsonRequired] - public string PipeProgram { get; set; } - - [JsonProperty] - [JsonRequired] - public string[] PipeArgs { get; set; } - - [JsonProperty] - public string DebuggerPath { get; set; } - - [JsonProperty] - public Dictionary PipeEnv { get; set; } - - [JsonProperty("quoteArgs", DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool? QuoteArgs { get; set; } - } - - [JsonObject] - private class JsonPipeTransport : JsonPipeTransportOptions - { - [JsonProperty] - public JsonPipeTransportOptions Windows { get; set; } - - [JsonProperty] - public JsonPipeTransportOptions Linux { get; set; } - - [JsonProperty] - public JsonPipeTransportOptions OSX { get; set; } - } - - [JsonObject] - private class JsonTcpLaunchOptions : JsonBaseLaunchOptions - { - [JsonProperty] - [JsonRequired] - public string HostName { get; set; } - - [JsonProperty] - [JsonRequired] - public string Port { get; set; } - - [JsonProperty()] - [JsonRequired] - public bool Secure { get; set; } - } - - private static string FormatCommand(JsonCommand command) - { - return String.Concat( - " ", - command.Text, - "\n" - ); - } - - private static void AddBaseLaunchOptionsAttributes( - StringBuilder xmlLaunchOptions, - JsonBaseLaunchOptions jsonLaunchOptions, - string program, - string workingDirectory) - { - xmlLaunchOptions.Append(String.Concat(" ExePath='", XmlSingleQuotedAttributeEncode(program), "'\n")); - - if (!String.IsNullOrEmpty(workingDirectory)) - { - xmlLaunchOptions.Append(String.Concat(" WorkingDirectory='", XmlSingleQuotedAttributeEncode(workingDirectory), "'\n")); - } - - if (jsonLaunchOptions.TargetArchitecture != null) - { - xmlLaunchOptions.Append(String.Concat(" TargetArchitecture='", jsonLaunchOptions.TargetArchitecture, "'\n")); - } - - if (jsonLaunchOptions.VisualizerFile != null) - { - xmlLaunchOptions.Append(String.Concat(" VisualizerFile='", jsonLaunchOptions.VisualizerFile, "'\n")); - } - - if (jsonLaunchOptions.ShowDisplayString) - { - xmlLaunchOptions.Append(" ShowDisplayString='true'\n"); - } - - if (jsonLaunchOptions.AdditionalSOLibSearchPath != null) - { - xmlLaunchOptions.Append(String.Concat(" AdditionalSOLibSearchPath='", jsonLaunchOptions.AdditionalSOLibSearchPath, "'\n")); - } - - if (!String.IsNullOrWhiteSpace(jsonLaunchOptions.CoreDumpPath)) - { - xmlLaunchOptions.Append(String.Concat(" CoreDumpPath='", jsonLaunchOptions.CoreDumpPath, "'\n")); - } - - string[] exeArgsArray = jsonLaunchOptions.Args; - - // Check to see if we need to redirect app stdin/out/err in Windows case for IntegratedTerminalSupport. - if (Utilities.IsWindows() - && HostRunInTerminal.IsRunInTerminalAvailable() - && jsonLaunchOptions is JsonLocalLaunchOptions - && String.IsNullOrWhiteSpace(jsonLaunchOptions.CoreDumpPath)) - { - var localLaunchOptions = (JsonLocalLaunchOptions)jsonLaunchOptions; - - if (localLaunchOptions.ProcessId == 0 && // Only when launching the debuggee - !localLaunchOptions.ExternalConsole - && !localLaunchOptions.AvoidWindowsConsoleRedirection) - { - exeArgsArray = TryAddWindowsDebuggeeConsoleRedirection(exeArgsArray); - } - } - - // ExeArguments - // Build the exe's argument list as a string - StringBuilder exeArguments = new StringBuilder(); - exeArguments.Append(CreateArgumentList(exeArgsArray)); - XmlSingleQuotedAttributeEncode(exeArguments); - xmlLaunchOptions.Append(String.Concat(" ExeArguments='", exeArguments, "'\n")); - - if (jsonLaunchOptions.MIMode != null) - { - xmlLaunchOptions.Append(String.Concat(" MIMode='", jsonLaunchOptions.MIMode, "'\n")); - } - } - - /// - /// To support Windows RunInTerminal's IntegratedTerminal, we will check each argument to see if it is a redirection of stdin, stderr, stdout and then will add - /// the redirection for the ones the user did not specify to go to Console. - /// - private static string[] TryAddWindowsDebuggeeConsoleRedirection(string[] arguments) - { - if (Utilities.IsWindows()) // Only do this on Windows - { - bool stdInRedirected = false; - bool stdOutRedirected = false; - bool stdErrRedirected = false; - - if (arguments != null) - { - foreach (string rawArgument in arguments) - { - string argument = rawArgument.TrimStart(); - if (argument.TrimStart().StartsWith("2>", StringComparison.Ordinal)) - { - stdErrRedirected = true; - } - if (argument.TrimStart().StartsWith("1>", StringComparison.Ordinal) || argument.TrimStart().StartsWith(">", StringComparison.Ordinal)) - { - stdOutRedirected = true; - } - if (argument.TrimStart().StartsWith("0>", StringComparison.Ordinal) || argument.TrimStart().StartsWith("<", StringComparison.Ordinal)) - { - stdInRedirected = true; - } - } - } - - // If one (or more) are not redirected, then add redirection - if (!stdInRedirected || !stdOutRedirected || !stdErrRedirected) - { - int argLength = arguments?.Length ?? 0; - List argList = new List(argLength + 3); - if (arguments != null) - { - argList.AddRange(arguments); - } - - if (!stdErrRedirected) - { - argList.Add("2>CON"); - } - - if (!stdOutRedirected) - { - argList.Add("1>CON"); - } - - if (!stdInRedirected) - { - argList.Add("(); - } - } - - return arguments; - } - - /// - /// Converts a list of strings arguments to a string representation. - /// - /// The list of arguments to convert into a string. - /// Only used for PipeTransports. Setting this to false disables quote handling if the user requests it. - /// - private static string CreateArgumentList(IEnumerable args, bool quoteArgs = true) - { - StringBuilder stringBuilder = new StringBuilder(); - if (args != null) - { - foreach (string arg in args) - { - if (stringBuilder.Length != 0) - stringBuilder.Append(' '); - - stringBuilder.Append(quoteArgs ? QuoteArgument(arg) : arg); - } - } - return stringBuilder.ToString(); - } - - // gdb does not like parenthesis without being quoted - private static char[] s_CHARS_TO_QUOTE = { ' ', '\t', '(', ')' }; - private static string QuoteArgument(string argument) - { - // If user wants an empty or whitespace argument, make sure we quote it - if (string.IsNullOrWhiteSpace(argument)) - { - return '"' + argument + '"'; - } - else - { - // ensure all quotes already in the string are escaped. If use has already escaped it too, undo our escaping - argument = argument.Replace("\"", "\\\"").Replace("\\\\\"", "\\\""); - if (argument.IndexOfAny(s_CHARS_TO_QUOTE) >= 0) - { - return '"' + argument + '"'; - } - } - return argument; - } - - private static void AddBaseLaunchOptionsElements(StringBuilder xmlLaunchOptions, JsonBaseLaunchOptions jsonLaunchOptions) - { - if (jsonLaunchOptions.SetupCommands != null) - { - xmlLaunchOptions.Append(" \n"); - foreach (JsonCommand command in jsonLaunchOptions.SetupCommands) - { - xmlLaunchOptions.Append(FormatCommand(command)); - } - xmlLaunchOptions.Append(" \n"); - } - - if (jsonLaunchOptions.CustomLaunchSetupCommands != null) - { - xmlLaunchOptions.Append(" \n"); - foreach (JsonCommand command in jsonLaunchOptions.CustomLaunchSetupCommands) - { - xmlLaunchOptions.Append(FormatCommand(command)); - } - xmlLaunchOptions.Append(" \n"); - } - - if (!String.IsNullOrEmpty(jsonLaunchOptions.LaunchCompleteCommand)) - { - // The xml schema will validate the allowable values. - xmlLaunchOptions.Append(String.Format(CultureInfo.InvariantCulture, " {0}\n", jsonLaunchOptions.LaunchCompleteCommand)); - } - } - /// /// Returns the path to lldb-mi which is installed when the extension is installed /// /// Path to lldb-mi or null if it doesn't exist - private static string GetLLDBMIPath() + internal static string GetLLDBMIPath() { string exePath = null; string directory = EngineConfiguration.GetAdapterDirectory(); @@ -487,327 +51,5 @@ private static string GetLLDBMIPath() return exePath; } - - internal static string CreateLaunchOptions( - string program, - string workingDirectory, - string args, - bool isPipeLaunch, - out bool stopAtEntry, - out bool isCoreDump, - out bool debugServerUsed, - out bool isOpenOCD, - out bool visualizerFileUsed) - { - stopAtEntry = false; - isCoreDump = false; - debugServerUsed = false; - isOpenOCD = false; - visualizerFileUsed = false; - - LaunchOptionType launchType = isPipeLaunch ? LaunchOptionType.Pipe : LaunchOptionType.Local; - - if (launchType == LaunchOptionType.Local) - { - JsonLocalLaunchOptions jsonLaunchOptions = JsonConvert.DeserializeObject(args); - StringBuilder xmlLaunchOptions = new StringBuilder(); - xmlLaunchOptions.Append("\n"); - - AddBaseLaunchOptionsElements(xmlLaunchOptions, jsonLaunchOptions); - - bool environmentDefined = jsonLaunchOptions.Environment?.Length > 0; - if (environmentDefined) - { - xmlLaunchOptions.Append(" \n"); - foreach (EnvironmentEntry envEntry in jsonLaunchOptions.Environment) - { - AddEnvironmentVariable(xmlLaunchOptions, envEntry.Name, envEntry.Value); - } - xmlLaunchOptions.Append(" \n"); - } - - if (jsonLaunchOptions.Env.Count > 0) - { - if (environmentDefined) - { - throw new ArgumentException(AD7Resources.Error_ConflictingEnvProps); - } - - xmlLaunchOptions.Append(" \n"); - foreach (KeyValuePair pair in jsonLaunchOptions.Env) - { - AddEnvironmentVariable(xmlLaunchOptions, pair.Key, pair.Value); - } - xmlLaunchOptions.Append(" \n"); - } - - if (jsonLaunchOptions.SymbolLoadInfo != null) - { - xmlLaunchOptions.Append(" \n"); - } - - xmlLaunchOptions.Append(""); - - visualizerFileUsed = jsonLaunchOptions.VisualizerFile != null; - - return xmlLaunchOptions.ToString(); - } - else if (launchType == LaunchOptionType.Pipe) - { - JsonPipeLaunchOptions jsonLaunchOptions = JsonConvert.DeserializeObject(args.ToString()); - - stopAtEntry = jsonLaunchOptions.StopAtEntry; - - StringBuilder xmlLaunchOptions = new StringBuilder(); - xmlLaunchOptions.Append(" pipeEnv = jsonLaunchOptions.PipeTransport.PipeEnv; - - JsonPipeTransportOptions platformSpecificTransportOptions = null; - if (Utilities.IsOSX() && jsonLaunchOptions.PipeTransport.OSX != null) - { - platformSpecificTransportOptions = jsonLaunchOptions.PipeTransport.OSX; - } - else if (Utilities.IsLinux() && jsonLaunchOptions.PipeTransport.Linux != null) - { - platformSpecificTransportOptions = jsonLaunchOptions.PipeTransport.Linux; - } - else if (Utilities.IsWindows() && jsonLaunchOptions.PipeTransport.Windows != null) - { - platformSpecificTransportOptions = jsonLaunchOptions.PipeTransport.Windows; - } - - if (platformSpecificTransportOptions != null) - { - pipeProgram = platformSpecificTransportOptions.PipeProgram ?? pipeProgram; - pipeArgs = platformSpecificTransportOptions.PipeArgs ?? pipeArgs; - pipeCwd = platformSpecificTransportOptions.PipeCwd ?? pipeCwd; - pipeEnv = platformSpecificTransportOptions.PipeEnv ?? pipeEnv; - quoteArgs = platformSpecificTransportOptions.QuoteArgs ?? quoteArgs; - } - - if (string.IsNullOrWhiteSpace(pipeProgram)) - { - throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Invalid pipeProgram option. pipeProgram should not be null or empty. Args: {0}", args)); - } - - xmlLaunchOptions.Append(String.Concat(" PipePath='", pipeProgram, "'\n")); - - if (pipeArgs != null) - { - // This code should be kept similar to MICode.LaunchOptions.cs EnsurePipeArguments() - string pipeCommandArgs = CreateArgumentList(pipeArgs, quoteArgs); - IEnumerable allPipeArguments = pipeArgs; - string debuggerPath = jsonLaunchOptions.PipeTransport.DebuggerPath ?? ""; - if (!string.IsNullOrEmpty(debuggerPath)) - { - string fullDebuggerCommandline = string.Format(CultureInfo.InvariantCulture, "{0} --interpreter=mi", debuggerPath); - if (allPipeArguments.Any(x => x.Contains(DebuggerCommandMacro))) - { - allPipeArguments = allPipeArguments.Select(x => x.Replace(DebuggerCommandMacro, fullDebuggerCommandline)); - } - else - { - allPipeArguments = allPipeArguments.Concat(new string[] { fullDebuggerCommandline }); - } - } - - string allArguments = CreateArgumentList(allPipeArguments, quoteArgs); - xmlLaunchOptions.Append(String.Concat(" PipeArguments='", MILaunchOptions.XmlSingleQuotedAttributeEncode(allArguments), "'\n")); - - // debuggerPath has to be specified. if it isn't then the debugger is specified in PipeArg which means we can't use the same arguments for pipeCommandArgs - if (!string.IsNullOrEmpty(debuggerPath)) - { - xmlLaunchOptions.Append(String.Concat(" PipeCommandArguments='", MILaunchOptions.XmlSingleQuotedAttributeEncode(pipeCommandArgs), "'\n")); - } - } - - if (pipeCwd != null) - { - xmlLaunchOptions.Append(String.Concat(" PipeCwd='", MILaunchOptions.XmlSingleQuotedAttributeEncode(pipeCwd), "'\n")); - } - - if (!String.IsNullOrEmpty(processId)) - { - xmlLaunchOptions.Append(String.Concat(" ProcessId='", processId, "'\n")); - } - - xmlLaunchOptions.Append(">\n"); - - AddBaseLaunchOptionsElements(xmlLaunchOptions, jsonLaunchOptions); - - if (pipeEnv != null && pipeEnv.Count > 0) - { - xmlLaunchOptions.Append(" \n"); - foreach (KeyValuePair pair in pipeEnv) - { - AddEnvironmentVariable(xmlLaunchOptions, pair.Key, pair.Value); - } - xmlLaunchOptions.Append(" \n"); - } - - xmlLaunchOptions.Append(""); - - return xmlLaunchOptions.ToString(); - } - // Commented out for now as we aren't supporting these options. - //else if (args.transport == "Tcp") - //{ - // JsonTcpLaunchOptions jsonLaunchOptions = JsonConvert.DeserializeObject(args.ToString()); - - // StringBuilder xmlLaunchOptions = new StringBuilder(); - // xmlLaunchOptions.Append("\n"); - - // AddBaseLaunchOptionsElements(xmlLaunchOptions, jsonLaunchOptions); - - // xmlLaunchOptions.Append(""); - - // return xmlLaunchOptions.ToString(); - //} - - Debug.Fail("We should not get here. All the launch types should be handled above."); - throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, AD7Resources.Error_Internal_Launch, launchType, args)); - } - - private static void AddEnvironmentVariable(StringBuilder xmlLaunchOptions, string name, string value) - { - xmlLaunchOptions.AppendFormat(CultureInfo.InvariantCulture, " \n", name, XmlSingleQuotedAttributeEncode(value)); - } - - internal static string XmlSingleQuotedAttributeEncode(string value) - { - if (string.IsNullOrWhiteSpace(value) || value.IndexOfAny(s_specialXmlSingleQuotedAttributeChars) < 0) - { - return value; - } - else - { - StringBuilder sb = new StringBuilder(value); - XmlSingleQuotedAttributeEncode(sb); - return sb.ToString(); - } - } - - /// - /// Escape a string that will be used as an XML attribute enclosed using single quotes ('). - /// - /// StringBuilder to update - private static void XmlSingleQuotedAttributeEncode(StringBuilder stringBuilder) - { - stringBuilder.Replace("&", "&"); - stringBuilder.Replace("<", "<"); - stringBuilder.Replace(">", ">"); - stringBuilder.Replace("'", "'"); - } - - private static char[] s_specialXmlSingleQuotedAttributeChars = { '&', '<', '>', '\'' }; } } diff --git a/src/OpenDebugAD7/OpenDebugAD7.csproj b/src/OpenDebugAD7/OpenDebugAD7.csproj index 51a43a730..b17497c36 100644 --- a/src/OpenDebugAD7/OpenDebugAD7.csproj +++ b/src/OpenDebugAD7/OpenDebugAD7.csproj @@ -68,8 +68,6 @@ prompt 4 false - - pdbonly @@ -139,7 +137,6 @@ - diff --git a/src/OpenDebugAD7/PathConverter.cs b/src/OpenDebugAD7/PathConverter.cs index 9c9253ffa..34207a6c4 100644 --- a/src/OpenDebugAD7/PathConverter.cs +++ b/src/OpenDebugAD7/PathConverter.cs @@ -9,7 +9,6 @@ namespace OpenDebugAD7 { internal class PathConverter { - internal PathMapper m_pathMapper { get; set; } internal bool DebuggerLinesStartAt1 { get; set; } internal bool ClientLinesStartAt1 { get; set; } internal bool DebuggerPathsAreURI { get; set; } @@ -53,8 +52,6 @@ internal int ConvertDebuggerColumnToClient(int column) internal string ConvertDebuggerPathToClient(string path) { - path = m_pathMapper.ResolveSymbolPath(path); - if (Path.DirectorySeparatorChar == '/') { path = path.Replace('\\', '/'); diff --git a/src/OpenDebugAD7/PathMapper.cs b/src/OpenDebugAD7/PathMapper.cs deleted file mode 100644 index 99b88f4f6..000000000 --- a/src/OpenDebugAD7/PathMapper.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace OpenDebugAD7 -{ - internal class PathMapper - { - // List of entries from PDB path -> local path - private readonly List> _entries = new List>(); - - public PathMapper(IReadOnlyDictionary entries) - { - if (entries != null) - { - foreach (KeyValuePair pair in entries) - { - ValidatePath(pair.Key); - ValidatePath(pair.Value); - string symbolPath = EncodeKey(pair.Key); - string localPath = ExpandPath(pair.Value); - - _entries.Add(new KeyValuePair(symbolPath, localPath)); - } - } - } - - /// - /// Looks to see if we have a rule redirecting the specified symbol path, and if so return the mapped path. Otherwise return the original. - /// - /// The incoming path from the engine - /// The path to return to the UI - public string ResolveSymbolPath(string symbolPath) - { - string encodedSymbolPath = EncodeKey(symbolPath); - - foreach (KeyValuePair entry in _entries) - { - if (encodedSymbolPath.StartsWith(entry.Key, StringComparison.OrdinalIgnoreCase)) - { - if (entry.Key.Length == encodedSymbolPath.Length) // Full file name match - return entry.Value; - - string remainder = symbolPath.Substring(entry.Key.Length); - - // Partial match, ensure the match doesn't have partial directory name (i.e. c:\\foo doesn't match c:\\foo-jam entry) - if (entry.Key.EndsWith("\\", StringComparison.OrdinalIgnoreCase) || - remainder.StartsWith("\\", StringComparison.OrdinalIgnoreCase) || - remainder.StartsWith("/", StringComparison.OrdinalIgnoreCase)) - { - return Path.Combine(entry.Value, remainder.TrimStart('\\', '/')); - } - } - } - - return symbolPath; - } - - private string ExpandPath(string path) - { - // Handle home directory - if (path.StartsWith("~", StringComparison.OrdinalIgnoreCase)) - { - string homeDirectory = Environment.GetEnvironmentVariable("HOME"); - - if (!string.IsNullOrEmpty(homeDirectory)) - { - path = homeDirectory + path.Substring(1); - } - } - - return path; - } - - private string EncodeKey(string key) - { - // To ensure consistent mappings even if we get the slashes changed to back slashes by the engine, we will swap all the slashes to back slashes - return key.Replace('/', '\\'); - } - - private void ValidatePath(string symbolPath) - { - if (string.IsNullOrEmpty(symbolPath)) - throw new AD7Exception(AD7Resources.Error_SourceFileMapEntryNull); - - if (symbolPath.IndexOf('/') < 0 && symbolPath.IndexOf('\\') < 0 && symbolPath != "~") - { - throw new AD7Exception(string.Format(CultureInfo.CurrentCulture, AD7Resources.Error_SourceFileMapEntryInvalid, symbolPath)); - } - } - } -}