From e2f7dbf915bcb13d3295229435ed4a0ce1cdb76e Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Mon, 27 Jun 2011 15:02:37 -0400 Subject: [PATCH] Bug 347196: Use MI to create tracepoint starting with GDB 7.2, which allows to set a tracepoint on the right process when using multi-process --- .../META-INF/MANIFEST.MF | 2 +- .../dsf/gdb/service/GDBBreakpoints_7_2.java | 153 ++++++++++++++++++ .../gdb/service/GdbDebugServicesFactory.java | 5 +- .../command/commands/MIBreakInsert.java | 4 +- 4 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBreakpoints_7_2.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF index 8edbcd618da..c64fd1f27f5 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb;singleton:=true -Bundle-Version: 4.0.0.qualifier +Bundle-Version: 4.1.0.qualifier Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.GdbPlugin Bundle-Localization: plugin Require-Bundle: org.eclipse.core.runtime, diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBreakpoints_7_2.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBreakpoints_7_2.java new file mode 100644 index 00000000000..add70750871 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBreakpoints_7_2.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2011 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.service; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints; +import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.mi.service.IMICommandControl; +import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData; +import org.eclipse.cdt.dsf.mi.service.MIBreakpoints; +import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Breakpoint service for GDB 7.2. + * It support MI for tracepoints. + * + * @since 4.1 + */ +public class GDBBreakpoints_7_2 extends GDBBreakpoints_7_0 +{ + private IMICommandControl fConnection; + + public GDBBreakpoints_7_2(DsfSession session) { + super(session); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.dsf.service.AbstractDsfService#initialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor) + */ + @Override + public void initialize(final RequestMonitor rm) { + super.initialize(new RequestMonitor(ImmediateExecutor.getInstance(), rm) { + @Override + protected void handleSuccess() { + doInitialize(rm); + } + }); + } + + private void doInitialize(final RequestMonitor rm) { + // Get the services references + fConnection = getServicesTracker().getService(IMICommandControl.class); + + // Register this service + register(new String[] { IBreakpoints.class.getName(), + IBreakpointsExtension.class.getName(), + MIBreakpoints.class.getName(), + GDBBreakpoints_7_0.class.getName(), + GDBBreakpoints_7_2.class.getName() }, + new Hashtable()); + + rm.done(); + } + + @Override + public void shutdown(RequestMonitor requestMonitor) { + unregister(); + super.shutdown(requestMonitor); + } + + /** + * Add a tracepoint using MI + */ + @Override + protected void addTracepoint(final IBreakpointsTargetDMContext context, final Map attributes, final DataRequestMonitor drm) + { + // Select the context breakpoints map + final Map contextBreakpoints = getBreakpointMap(context); + if (contextBreakpoints == null) { + drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null)); + drm.done(); + return; + } + + // Extract the relevant parameters (providing default values to avoid potential NPEs) + final String location = formatLocation(attributes); + if (location.equals(NULL_STRING)) { + drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null)); + drm.done(); + return; + } + + + final Boolean enabled = (Boolean) getProperty(attributes, MIBreakpoints.IS_ENABLED, true); + final Boolean isHardware = (Boolean) getProperty(attributes, MIBreakpointDMData.IS_HARDWARE, false); + final String condition = (String) getProperty(attributes, MIBreakpoints.CONDITION, NULL_STRING); + + fConnection.queueCommand( + fConnection.getCommandFactory().createMIBreakInsert(context, false, isHardware, condition, 0, location, 0, !enabled, true), + new DataRequestMonitor(getExecutor(), drm) { + @Override + protected void handleSuccess() { + // With MI, an invalid location won't generate an error + if (getData().getMIBreakpoints().length == 0) { + drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, BREAKPOINT_INSERTION_FAILURE, null)); + drm.done(); + return; + } + + // Create a breakpoint object and store it in the map + final MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(getData().getMIBreakpoints()[0]); + int reference = newBreakpoint.getNumber(); + if (reference == -1) { + drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, BREAKPOINT_INSERTION_FAILURE, null)); + drm.done(); + return; + } + contextBreakpoints.put(reference, newBreakpoint); + + // Format the return value + MIBreakpointDMContext dmc = new MIBreakpointDMContext(GDBBreakpoints_7_2.this, new IDMContext[] { context }, reference); + drm.setData(dmc); + + // Flag the event + getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); + + // Tracepoints are created with no passcount (passcount are not + // the same thing as ignore-count, which is not supported by + // tracepoints). We have to set the passcount manually now. + // Same for commands. + Map delta = new HashMap(); + delta.put(MIBreakpoints.PASS_COUNT, getProperty(attributes, MIBreakpoints.PASS_COUNT, 0)); + delta.put(MIBreakpoints.COMMANDS, getProperty(attributes, MIBreakpoints.COMMANDS, "")); //$NON-NLS-1$ + modifyBreakpoint(dmc, delta, drm, false); + } + + @Override + protected void handleError() { + drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, BREAKPOINT_INSERTION_FAILURE, null)); + drm.done(); + } + }); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java index b013aae8dd3..0964d762527 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 Ericsson and others. + * Copyright (c) 2008, 2011 Ericsson and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -98,6 +98,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { @Override protected IBreakpoints createBreakpointService(DsfSession session) { + if (GDB_7_2_VERSION.compareTo(fVersion) <= 0) { + return new GDBBreakpoints_7_2(session); + } if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) { return new GDBBreakpoints_7_0(session); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java index 49a22d77c62..f653ead1443 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 QNX Software Systems and others. + * Copyright (c) 2000, 2011 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -57,7 +57,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; * * '-a' * Insert a tracepoint instead of a breakpoint - * Only available starting GDB 7.1 + * Only available starting GDB 7.2 * * '-p THREAD' * THREAD on which to apply the breakpoint