public void TestAttachToGameFail_CannotGetTracer() { var launcherFactory = CreateLauncherFactory(false); var launcher = launcherFactory.Create(_debugEngine, LaunchOption.AttachToGame, "", _gameBinary, _gameBinary, _gameLaunch); _debuggerFactory.SetTargetAttachError("Operation not permitted"); _platformFactory.AddCommandOutput($"cat /proc/{_pid}/status", null); AttachException e = Assert.ThrowsAsync <AttachException>(async() => await LaunchAsync(launcher)); Assert.That(e.Message, Is.EqualTo( ErrorStrings.FailedToAttachToProcess("Operation not permitted"))); CheckLldbListenerStops(); }
public void TestAttachToGameFail_NoTracer() { string parentPid = "1234"; string tracerPid = "0"; var launcherFactory = CreateLauncherFactory(false); var launcher = launcherFactory.Create(_debugEngine, LaunchOption.AttachToGame, "", _gameBinary, _gameBinary, _gameLaunch); _debuggerFactory.SetTargetAttachError("Operation not permitted"); _platformFactory.AddCommandOutput($"cat /proc/{_pid}/status", "Name:\tgame\n" + $"Pid:\t{_pid}\n" + $"PPid:\t{parentPid}\n" + $"TracerPid:\t{tracerPid}\n" + "FDSize:\t256\n"); AttachException e = Assert.ThrowsAsync <AttachException>(async() => await LaunchAsync(launcher)); Assert.That(e.Message, Is.EqualTo( ErrorStrings.FailedToAttachToProcess("Operation not permitted"))); CheckLldbListenerStops(); }
/// <summary> /// Get a more detailed error message if attaching to the remote process failed. /// /// At the moment, we handle specially only the case when another tracer is attached. /// In that case, we detect and show which process is the tracer. /// </summary> /// <param name="lldbError">Error object from Lldb attach.</param> /// <param name="platform">Lldb platform, used to run shell commands.</param> /// <param name="processId">Process Id of the debuggee.</param> /// <returns>Returns the error string.</returns> string GetLldbAttachErrorDetails(SbError lldbError, SbPlatform platform, uint processId) { string lldbMessageWhenAlreadyTraced = "Operation not permitted"; // Compute the fallback error message. string errorString = ErrorStrings.FailedToAttachToProcess(lldbError.GetCString()); // If the error does not need special handling, just return the default message. if (platform == null || lldbError.GetCString() != lldbMessageWhenAlreadyTraced) { return(errorString); } // Let us detect if there is a debugger already attached and provide a better error // message there. string output = RunShellCommand($"cat /proc/{processId}/status", platform); if (string.IsNullOrEmpty(output)) { return(errorString); } Regex tracerRE = new Regex("[\\r\\n]TracerPid:\\W*([0-9]+)[\\r\\n]"); Regex parentRE = new Regex("[\\r\\n]PPid:\\W*([0-9]+)[\\r\\n]"); Regex firstLineRE = new Regex("^([^\\r\\n]*)([\\r\\n]|$)"); // Find the line with tracer pid in the proc-status file. Match tracerMatch = tracerRE.Match(output); Match parentMatch = parentRE.Match(output); if (!tracerMatch.Success || !parentMatch.Success) { return(errorString); } string parentPid = parentMatch.Groups[1].Value; string tracerPid = tracerMatch.Groups[1].Value; // If there was no tracer, just show the default message. if (tracerPid == "0") { return(errorString); } // If the tracer is the parent process, then the debuggee is tracing itself. if (tracerPid == parentPid) { return(ErrorStrings.FailedToAttachToProcessSelfTrace); } // Try to find the tracer in the list of processes and report it in the error message. string commOutput = RunShellCommand($"cat /proc/{tracerPid}/comm", platform); if (string.IsNullOrEmpty(output)) { return(errorString); } // Get the first line as the process name. Match commMatch = firstLineRE.Match(commOutput); string tracerName = commMatch.Success ? commMatch.Groups[1].Value : "<unkown>"; return(ErrorStrings.FailedToAttachToProcessOtherTracer(tracerName, tracerPid)); }