@Override protected String evaluateExpression(String expression) { IFrameDMContext frame = getFrame(); if (frame == null) { return null; } String sessionId = frame.getSessionId(); DsfServicesTracker dsfServicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), sessionId); try { GetExpressionValueQuery query = new GetExpressionValueQuery(frame, expression, dsfServicesTracker); DsfSession session = DsfSession.getSession(sessionId); if (session != null) { session.getExecutor().execute(query); try { FormattedValueDMData data = query.get(); if (data != null) return data.getFormattedValue(); } catch (Exception e) { } } } finally { dsfServicesTracker.dispose(); } return null; }
/** * Initialize the members of the StartOrRestartProcessSequence_7_0 class. This step is mandatory * for the rest of the sequence to complete. */ @Execute public void stepInitializeBaseSequence(RequestMonitor rm) { fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fContainerDmc.getSessionId()); fCommandControl = fTracker.getService(IGDBControl.class); fCommandFactory = fTracker.getService(IMICommandControl.class).getCommandFactory(); fProcService = fTracker.getService(IGDBProcesses.class); fBackend = fTracker.getService(IGDBBackend.class); if (fCommandControl == null || fCommandFactory == null || fProcService == null) { rm.setStatus( new Status( IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot obtain service", null)); //$NON-NLS-1$ rm.done(); return; } fReverseService = fTracker.getService(IReverseRunControl.class); if (fReverseService != null) { // Although the option to use reverse debugging could be on, we only check // it if we actually have a reverse debugging service. There is no point // in trying to handle reverse debugging if it is not available. fReverseEnabled = CDebugUtils.getAttribute( fAttributes, IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT); } rm.done(); }
/** * Initialize the members of the DebugNewProcessSequence class. This step is mandatory for the * rest of the sequence to complete. */ @Execute public void stepInitializeBaseSequence(RequestMonitor rm) { fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fContext.getSessionId()); fBackend = fTracker.getService(IGDBBackend.class); fCommandControl = fTracker.getService(IGDBControl.class); fCommandFactory = fTracker.getService(IMICommandControl.class).getCommandFactory(); fProcService = fTracker.getService(IGDBProcesses.class); if (fBackend == null || fCommandControl == null || fCommandFactory == null || fProcService == null) { rm.setStatus( new Status( IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot obtain service", null)); //$NON-NLS-1$ rm.done(); return; } // When we are starting to debug a new process, the container is the default process used by // GDB. // We don't have a pid yet, so we can simply create the container with the UNIQUE_GROUP_ID setContainerContext( fProcService.createContainerContextFromGroupId( fCommandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID)); rm.done(); }
@Override protected void execute(final DataRequestMonitor<FormattedValueDMData> rm) { DsfSession session = DsfSession.getSession(frame.getSessionId()); IExpressions expressions = dsfServicesTracker.getService(IExpressions.class); if (expressions == null) { rm.setStatus( DsfUIPlugin.newErrorStatus( IDsfStatusConstants.REQUEST_FAILED, "No expression service", null)); // $NON-NLS-1$ rm.done(); return; } IExpressionDMContext expressionDMC = expressions.createExpression(frame, expression); FormattedValueDMContext formattedValueContext = expressions.getFormattedValueContext(expressionDMC, getHoverFormat()); expressions.getFormattedExpressionValue( formattedValueContext, new DataRequestMonitor<FormattedValueDMData>(session.getExecutor(), rm) { @Override protected void handleSuccess() { rm.setData(getData()); rm.done(); } @Override protected void handleFailure() { rm.done(); } }); }
private void startNewProcess( ICommandControlDMContext controlDmc, String binaryPath, RequestMonitor rm) { IGDBProcesses procService = fTracker.getService(IGDBProcesses.class); procService.debugNewProcess( controlDmc, binaryPath, new HashMap<String, Object>(), new DataRequestMonitor<IDMContext>(fExecutor, rm)); }
/** * In case of a restart, we must mark reverse debugging as disabled because GDB has turned it off. * We may have to turn it back on after. */ @Execute public void stepSetReverseOff(RequestMonitor rm) { if (fRestart) { GDBRunControl_7_0 reverseService = fTracker.getService(GDBRunControl_7_0.class); if (reverseService != null) { reverseService.setReverseModeEnabled(false); } } rm.done(); }
/** * Start tracking the breakpoints. Note that for remote debugging we should first connect to the * target. */ @Execute public void stepStartTrackingBreakpoints(RequestMonitor rm) { if (fBackend.getSessionType() != SessionType.CORE) { MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class); IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(getContainerContext(), IBreakpointsTargetDMContext.class); bpmService.startTrackingBreakpoints(bpTargetDmc, rm); } else { rm.done(); } }
/** * This method indicates if we should use the -exec-continue command instead of the -exec-run * command. This method can be overridden to allow for customization. */ protected boolean useContinueCommand() { // Note that restart does not apply to remote sessions IGDBBackend backend = fTracker.getService(IGDBBackend.class); if (backend == null) { return false; } // When doing remote non-attach debugging, we use -exec-continue instead of -exec-run // For remote attach, if we get here it is that we are starting a new process // (multi-process), so we want to use -exec-run return backend.getSessionType() == SessionType.REMOTE && !backend.getIsAttachSession(); }
@Override @After public void doAfterTest() throws Exception { Runnable runnable = new Runnable() { @Override public void run() { fSession.removeServiceEventListener(GDBConsoleBreakpointsTest.this); } }; fSession.getExecutor().submit(runnable).get(); fBreakpointEvents.clear(); fServicesTracker.dispose(); fServicesTracker = null; super.doAfterTest(); deleteAllPlatformBreakpoints(); }
@Override @After public void doAfterTest() throws Exception { if (fSession != null) { fSession .getExecutor() .submit(() -> fSession.removeServiceEventListener(GDBConsoleBreakpointsTest.this)) .get(); } fBreakpointEvents.clear(); if (fServicesTracker != null) { fServicesTracker.dispose(); fServicesTracker = null; } super.doAfterTest(); deleteAllPlatformBreakpoints(); }
@Override public void doAfterTest() throws Exception { super.doAfterTest(); if (fServicesTracker != null) fServicesTracker.dispose(); }
private void attachToProcesses( final ICommandControlDMContext controlDmc, IProcessExtendedInfo[] processes, final RequestMonitor rm) { // For a local attach, GDB can figure out the binary automatically, // so we don't need to prompt for it. final IGDBProcesses procService = fTracker.getService(IGDBProcesses.class); final IGDBBackend backend = fTracker.getService(IGDBBackend.class); if (procService != null && backend != null) { // Attach to each process in a sequential fashion. We must do this // to be able to check if we are allowed to attach to the next process. // Attaching to all of them in parallel would assume that all attach are supported. // Create a list of all our processes so we can attach to one at a time. // We need to create a new list so that we can remove elements from it. final List<IProcessExtendedInfo> procList = new ArrayList<IProcessExtendedInfo>(Arrays.asList(processes)); class AttachToProcessRequestMonitor extends ImmediateDataRequestMonitor<IDMContext> { public AttachToProcessRequestMonitor() { super(); } @Override protected void handleCompleted() { if (!isSuccess()) { // Failed to attach to a process. Just ignore it and move on. } // Check that we have a process to attach to if (procList.size() > 0) { // Check that we can actually attach to the process. // This is because some backends may not support multi-process. // If the backend does not support multi-process, we only attach to the first process. procService.isDebuggerAttachSupported( controlDmc, new ImmediateDataRequestMonitor<Boolean>() { @Override protected void handleCompleted() { if (isSuccess() && getData()) { // Can attach to process // Remove process from list and attach to it. IProcessExtendedInfo process = procList.remove(0); String pidStr = Integer.toString(process.getPid()); if (backend.getSessionType() == SessionType.REMOTE) { // For remote attach, we must set the binary first so we need to prompt the // user. // If this is the very first attach of a remote session, check if the user // specified the binary in the launch. If so, let's add it to our map to // avoid having to prompt the user for that binary. // This would be particularly annoying since we didn't use to have // to do that before we supported multi-process. // Must do this here to be in the executor // Bug 350365 if (fProcessNameToBinaryMap.isEmpty()) { IPath binaryPath = backend.getProgramPath(); if (binaryPath != null && !binaryPath.isEmpty()) { fProcessNameToBinaryMap.put( binaryPath.lastSegment(), binaryPath.toOSString()); } } // Because the prompt is a very long operation, we need to run outside the // executor, so we don't lock it. // Bug 344892 IPath processPath = new Path(process.getName()); String processShortName = processPath.lastSegment(); new PromptAndAttachToProcessJob( pidStr, LaunchUIMessages.getString("ProcessPrompterDialog.TitlePrefix") + process.getName(), // $NON-NLS-1$ processShortName, new AttachToProcessRequestMonitor()) .schedule(); } else { // For a local attach, we can attach directly without looking for the binary // since GDB will figure it out by itself IProcessDMContext procDmc = procService.createProcessContext(controlDmc, pidStr); procService.attachDebuggerToProcess( procDmc, null, new AttachToProcessRequestMonitor()); } } else { // Not allowed to attach to another process. Just stop. rm.done(); } } }); } else { // No other process to attach to rm.done(); } } }; // Trigger the first attach. new AttachToProcessRequestMonitor().done(); } else { rm.done( new Status( IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot find service", null)); //$NON-NLS-1$ } }
public void dispose() { fTracker.dispose(); }
/** Before running the program, we must create its console for IO. */ @Execute public void stepCreateConsole(final RequestMonitor rm) { Process inferiorProcess; if (fPty == null) { inferiorProcess = new MIInferiorProcess(fContainerDmc, fBackend.getMIOutputStream()); } else { inferiorProcess = new MIInferiorProcess(fContainerDmc, fPty); } final Process inferior = inferiorProcess; final ILaunch launch = (ILaunch) getContainerContext().getAdapter(ILaunch.class); // This is the groupId of the new process that will be started, even in the // case of a restart. final String groupId = ((IMIContainerDMContext) getContainerContext()).getGroupId(); // For multi-process, we cannot simply use the name given by the backend service // because we may not be starting that process, but another one. // Instead, we can look in the attributes for the binary name, which we stored // there for this case, specifically. // Bug 342351 IGDBBackend backend = fTracker.getService(IGDBBackend.class); String defaultPathName = backend.getProgramPath().lastSegment(); if (defaultPathName == null) { defaultPathName = ""; // $NON-NLS-1$ } String progPathName = CDebugUtils.getAttribute( fAttributes, ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, defaultPathName); final String pathLabel = new Path(progPathName).lastSegment(); // Add the inferior to the launch. // This cannot be done on the executor or things deadlock. DebugPlugin.getDefault() .asyncExec( new Runnable() { @Override public void run() { String label = pathLabel; if (fRestart) { // For a restart, remove the old inferior IProcess[] launchProcesses = launch.getProcesses(); for (IProcess process : launchProcesses) { if (process instanceof InferiorRuntimeProcess) { String groupAttribute = process.getAttribute(IGdbDebugConstants.INFERIOR_GROUPID_ATTR); // if the groupAttribute is not set in the process we know we are dealing // with single process debugging so the one process is the one we want. // If the groupAttribute is set, then we must make sure it is the proper // inferior if (groupAttribute == null || groupAttribute.equals(MIProcesses.UNIQUE_GROUP_ID) || groupAttribute.equals(groupId)) { launch.removeProcess(process); // Use the exact same label as before label = process.getLabel(); break; } } } } // Add the inferior InferiorRuntimeProcess runtimeInferior = new InferiorRuntimeProcess(launch, inferior, label, null); runtimeInferior.setAttribute(IGdbDebugConstants.INFERIOR_GROUPID_ATTR, groupId); launch.addProcess(runtimeInferior); rm.done(); } }); }
/** * Cleanup now that the sequence has been run. * * @since 4.0 */ @Execute public void stepCleanupBaseSequence(RequestMonitor rm) { fTracker.dispose(); fTracker = null; rm.done(); }
@After public void tearDown() { fServicesTracker.dispose(); fRegService = null; }
/** * If we are dealing with a postmortem session, connect to the core/trace file. * * @since 4.0 */ @Execute public void stepSpecifyCoreFile(final RequestMonitor rm) { // If we are dealing with a postmortem session, it is now time to connect // to the core/trace file. We have to do this step after // we have specified the executable, so we have to do it here. // It is safe to do it here because a postmortem session does not support // multi-process so this step will not be executed more than once. // Bug 338730 if (fBackend.getSessionType() == SessionType.CORE) { String coreFile = CDebugUtils.getAttribute( fAttributes, ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); // $NON-NLS-1$ final String coreType = CDebugUtils.getAttribute( fAttributes, IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE, IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT); if (coreFile.length() == 0) { new PromptForCoreJob( "Prompt for post mortem file", //$NON-NLS-1$ new DataRequestMonitor<String>(getExecutor(), rm) { @Override protected void handleCancel() { rm.cancel(); rm.done(); } @Override protected void handleSuccess() { String newCoreFile = getData(); if (newCoreFile == null || newCoreFile.length() == 0) { rm.setStatus( new Status( IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", null)); //$NON-NLS-1$ rm.done(); } else { if (coreType.equals( IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) { fCommandControl.queueCommand( fCommandFactory.createMITargetSelectCore( fCommandControl.getContext(), newCoreFile), new DataRequestMonitor<MIInfo>(getExecutor(), rm)); } else if (coreType.equals( IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) { IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); if (traceControl != null) { ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType( fCommandControl.getContext(), ITraceTargetDMContext.class); traceControl.loadTraceData(targetDmc, newCoreFile, rm); } else { rm.setStatus( new Status( IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null)); rm.done(); } } else { rm.setStatus( new Status( IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null)); rm.done(); } } } }) .schedule(); } else { if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) { fCommandControl.queueCommand( fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile), new DataRequestMonitor<MIInfo>(getExecutor(), rm)); } else if (coreType.equals( IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) { IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); if (traceControl != null) { ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType( fCommandControl.getContext(), ITraceTargetDMContext.class); traceControl.loadTraceData(targetDmc, coreFile, rm); } else { rm.setStatus( new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null)); rm.done(); } } else { rm.setStatus( new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null)); rm.done(); } } } else { rm.done(); } }
/** * Rollback method for {@link #stepInitializeBaseSequence()} * * @since 4.0 */ @RollBack("stepInitializeBaseSequence") public void rollBackInitializeBaseSequence(RequestMonitor rm) { if (fTracker != null) fTracker.dispose(); fTracker = null; rm.done(); }