1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

Bug 389945 - Only set breakpoints once for GDB >= 7.4

Make the IBreakpoinTargetDMC map to the GDB context for GDB >= 7.4.
This will allow to track breakpoints globally for GDB since that is
how GDB handles breakpoints from 7.4 and up.

Change-Id: I84bccf9bdc6e169624908fee106080f840843e28
Signed-off-by: Marc Khouzam <marc.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/22388
This commit is contained in:
Marc Khouzam 2014-04-04 15:30:40 -04:00
parent ede42e1820
commit 79dc0b8184
9 changed files with 152 additions and 43 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2013 Ericsson and others.
* Copyright (c) 2008, 2014 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
@ -11,6 +11,8 @@
* John Dallaway - GDB 7.x MI thread details field ignored (Bug 325556)
* Marc Khouzam (Ericsson) - Make each thread an IDisassemblyDMContext (bug 352748)
* Andy Jin (QNX) - Not output thread osId as a string when it is null (Bug 397039)
* Marc Khouzam (Ericsson) - Move IBreakpointsTargetDMContext from MIContainerDMC
* to GDBContainerDMC to ease inheritance (Bug 389945)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@ -183,8 +185,8 @@ public class GDBProcesses_7_0 extends AbstractDsfService
* Context representing a thread group of GDB/MI.
*/
@Immutable
private static class MIContainerDMC extends AbstractDMContext
implements IMIContainerDMContext, IBreakpointsTargetDMContext, IDisassemblyDMContext
static class MIContainerDMC extends AbstractDMContext
implements IMIContainerDMContext, IDisassemblyDMContext
{
/**
* String ID that is used to identify the thread group in the GDB/MI protocol.
@ -225,7 +227,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
}
private static class GDBContainerDMC extends MIContainerDMC
implements IMemoryDMContext
implements IMemoryDMContext, IBreakpointsTargetDMContext
{
public GDBContainerDMC(String sessionId, IProcessDMContext processDmc, String groupId) {
super(sessionId, processDmc, groupId);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2013 TUBITAK BILGEM-ITI and others.
* Copyright (c) 2010, 2014 TUBITAK BILGEM-ITI 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
@ -8,6 +8,7 @@
* Contributors:
* Onur Akdemir (TUBITAK BILGEM-ITI) - Multi-process debugging (Bug 237306)
* Marc Khouzam (Ericsson) - Workaround for Bug 352998
* Marc Khouzam (Ericsson) - Update breakpoint handling for GDB >= 7.4 (Bug 389945)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@ -558,11 +559,14 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
@Override
public void eventDispatched(IExitedDMEvent e) {
IDMContext dmc = e.getDMContext();
if (dmc instanceof IContainerDMContext) {
if (dmc instanceof IBreakpointsTargetDMContext) {
// A process has died, we should stop tracking its breakpoints, but only if it is not restarting
// We only do this when the process is a breakpointTargetDMC itself (GDB < 7.4);
// we don't want to stop tracking breakpoints when breakpoints are only set once
// for all processes (GDB >= 7.4)
if (!fProcRestarting.remove(dmc)) {
if (fBackend.getSessionType() != SessionType.CORE) {
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
IBreakpointsTargetDMContext bpTargetDmc = (IBreakpointsTargetDMContext)dmc;
MIBreakpointsManager bpmService = getServicesTracker().getService(MIBreakpointsManager.class);
if (bpmService != null) {
bpmService.stopTrackingBreakpoints(bpTargetDmc, new ImmediateRequestMonitor() {

View file

@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2014 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:
* Marc Khouzam (Ericsson) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
import org.eclipse.cdt.dsf.service.DsfSession;
/**
* Adapt to GDB 7.4 where breakpoints are for all inferiors at once.
*
* @since 4.4
*/
public class GDBProcesses_7_4 extends GDBProcesses_7_2_1 {
public GDBProcesses_7_4(DsfSession session) {
super(session);
}
/**
* A container context that is not an IBreakpointsTargetDMContext.
*/
private static class GDBContainerDMC_7_4 extends MIContainerDMC
implements IMemoryDMContext
{
public GDBContainerDMC_7_4(String sessionId, IProcessDMContext processDmc, String groupId) {
super(sessionId, processDmc, groupId);
}
}
@Override
public IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
String groupId) {
return new GDBContainerDMC_7_4(getSession().getId(), processDmc, groupId);
}
}

View file

@ -15,6 +15,7 @@
* Marc Khouzam (Ericsson) - Support for GDB 7.6 memory service
* Marc Khouzam (Ericsson) - Support for GDB 7.4 trace control service
* William Riley (Renesas) - Support for GDB 7.3 disassembly service (Bug 357270)
* Marc Khouzam (Ericsson) - Support for GDB 7.4 processes service (Bug 389945)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@ -200,6 +201,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
@Override
protected IProcesses createProcessesService(DsfSession session) {
if (GDB_7_4_VERSION.compareTo(fVersion) <= 0) {
return new GDBProcesses_7_4(session);
}
if (GDB_7_2_1_VERSION.compareTo(fVersion) <= 0) {
return new GDBProcesses_7_2_1(session);
}

View file

@ -16,6 +16,7 @@
* Mikhail Khodjaiants (Mentor Graphics) - Terminate should cancel the initialization sequence
* if it is still running (bug 373845)
* Marc Khouzam (Ericsson) - Terminate the session if we lose the connection to the remote target (bug 422586)
* Marc Khouzam (Ericsson) - Allow to override the creation of the ControlDMC (Bug 389945)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service.command;
@ -185,7 +186,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
}
}
private GDBControlDMContext fControlDmc;
private ICommandControlDMContext fControlDmc;
private IGDBBackend fMIBackend;
@ -250,9 +251,9 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
fMIBackend = getServicesTracker().getService(IGDBBackend.class);
// getId uses the MIBackend service, which is why we must wait until we
// have it, before we can create this context.
fControlDmc = new GDBControlDMContext(getSession().getId(), getId());
// getId, called to create this context, uses the MIBackend service,
// which is why we must wait until we have MIBackend, before we can create the below context.
fControlDmc = createComandControlContext();
getExecutor().execute(getStartupSequence(requestMonitor));
}
@ -273,9 +274,23 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
return fMIBackend.getId();
}
/**
* Create the commandControl context.
* This method can be overridden to provide a different context.
* @since 4.4
*/
protected ICommandControlDMContext createComandControlContext() {
return new GDBControlDMContext(getSession().getId(), getId());
}
@Deprecated
@Override
public MIControlDMContext getControlDMContext() {
return fControlDmc;
assert fControlDmc instanceof MIControlDMContext;
if (fControlDmc instanceof MIControlDMContext) {
return (MIControlDMContext)fControlDmc;
}
return null;
}
@Override
@ -325,7 +340,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
getGDBExitWaitTime(), TimeUnit.SECONDS);
queueCommand(
getCommandFactory().createMIGDBExit(fControlDmc),
getCommandFactory().createMIGDBExit(getContext()),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
public void handleCompleted() {
@ -437,7 +452,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
// Before GDB 7.0, we have to send the containerExited event ourselves
IGDBProcesses procService = getServicesTracker().getService(IGDBProcesses.class);
if (procService != null) {
IContainerDMContext processContainerDmc = procService.createContainerContextFromGroupId(fControlDmc, MIProcesses.UNIQUE_GROUP_ID);
IContainerDMContext processContainerDmc = procService.createContainerContextFromGroupId(getContext(), MIProcesses.UNIQUE_GROUP_ID);
getSession().dispatchEvent(
new ContainerExitedDMEvent(processContainerDmc), getProperties());
}
@ -447,7 +462,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
public void eventDispatched(BackendStateChangedEvent e) {
if (e.getState() == IMIBackend.State.TERMINATED && e.getBackendId().equals(fMIBackend.getId())) {
// Handle "GDB Exited" event, just relay to following event.
getSession().dispatchEvent(new GDBControlShutdownDMEvent(fControlDmc), getProperties());
getSession().dispatchEvent(new GDBControlShutdownDMEvent(getContext()), getProperties());
}
}
@ -518,8 +533,8 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
return;
}
fCLICommandProcessor = createCLIEventProcessor(GDBControl.this, fControlDmc);
fMIEventProcessor = createMIRunControlEventProcessor(GDBControl.this, fControlDmc);
fCLICommandProcessor = createCLIEventProcessor(GDBControl.this, getContext());
fMIEventProcessor = createMIRunControlEventProcessor(GDBControl.this, getContext());
fControlEventProcessor = createControlEventProcessor();
requestMonitor.done();
@ -575,7 +590,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
AbstractMIControl.class.getName(),
IGDBControl.class.getName() },
new Hashtable<String,String>());
getSession().dispatchEvent(new GDBControlInitializedDMEvent(fControlDmc), getProperties());
getSession().dispatchEvent(new GDBControlInitializedDMEvent(getContext()), getProperties());
requestMonitor.done();
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2012 Wind River Systems and others.
* Copyright (c) 2006, 2014 Wind River 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
@ -183,7 +183,7 @@ public class GDBControl_7_0 extends GDBControl {
private void listFeatures(final RequestMonitor requestMonitor) {
queueCommand(
getCommandFactory().createMIListFeatures(getControlDMContext()),
getCommandFactory().createMIListFeatures(getContext()),
new DataRequestMonitor<MIListFeaturesInfo>(getExecutor(), requestMonitor) {
@Override
public void handleSuccess() {
@ -235,7 +235,7 @@ public class GDBControl_7_0 extends GDBControl {
@Override
public void enablePrettyPrintingForMIVariableObjects(RequestMonitor rm) {
queueCommand(
getCommandFactory().createMIEnablePrettyPrinting(getControlDMContext()),
getCommandFactory().createMIEnablePrettyPrinting(getContext()),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
@ -248,7 +248,7 @@ public class GDBControl_7_0 extends GDBControl {
String subCommand = "set python print-stack " + (enabled ? "on" : "off"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
queueCommand(
getCommandFactory().createCLIMaintenance(getControlDMContext(), subCommand),
getCommandFactory().createCLIMaintenance(getContext(), subCommand),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Ericsson and others.
* Copyright (c) 2012, 2014 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
@ -7,11 +7,13 @@
*
* Contributors:
* Marc Khouzam (Ericsson) - initial API and implementation
* Marc Khouzam (Ericsson) - Update breakpoint handling for GDB >= 7.4 (Bug 389945)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service.command;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.service.DsfSession;
@ -20,12 +22,32 @@ import org.eclipse.debug.core.ILaunchConfiguration;
/**
* With GDB 7.4, the command 'maintenance set python print-stack' is not supported.
* The new command "set python print-stack none|full|message" has replaced it.
*
* With GDB 7.4, breakpoints are handled globally for all of GDB, so our
* IBreakpointsTargetDMContext becomes the GDBControlContext.
*
* @since 4.1
*/
public class GDBControl_7_4 extends GDBControl_7_2 implements IGDBControl {
/**
* A command control context that is also a IBreakpointsTargetDMContext
*/
private class GDBControlDMContext_7_4 extends GDBControlDMContext implements IBreakpointsTargetDMContext {
public GDBControlDMContext_7_4(String sessionId, String commandControlId) {
super(sessionId, commandControlId);
}
}
public GDBControl_7_4(DsfSession session, ILaunchConfiguration config, CommandFactory factory) {
super(session, config, factory);
}
/** @since 4.4 */
@Override
protected ICommandControlDMContext createComandControlContext() {
return new GDBControlDMContext_7_4(getSession().getId(), getId());
}
@Override
public void setPrintPythonErrors(boolean enabled, RequestMonitor rm) {

View file

@ -13,6 +13,7 @@
* Ericsson - Added Action support
* Marc Khouzam (Ericsson) - Fix support for thread filter (Bug 355833)
* Marc Khouzam (Ericsson) - Generalize thread filtering logic (Bug 431986)
* Marc Khouzam (Ericsson) - Accept multiple calls to startTrackingBreakpoints (Bug 389945)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@ -367,13 +368,14 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
return;
}
// Make sure a mapping for this execution context does not already exist
Map<ICBreakpoint,Map<String, Object>> platformBPs = fPlatformBPs.get(dmc);
Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
Map<IBreakpointDMContext, ICBreakpoint> targetIDs = fTargetBPs.get(dmc);
Map<ICBreakpoint, Set<String>> threadIDs = fBreakpointThreads.get(dmc);
if ((platformBPs != null) || (breakpointIDs != null) || (targetIDs != null) || (threadIDs != null)) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, CONTEXT_ALREADY_INITIALIZED, null));
// If the maps already contains this context we can simply ignore this request.
// This happens when we start or attach to another process with GDB >= 7.4
assert platformBPs != null && breakpointIDs != null && targetIDs != null && threadIDs != null;
rm.done();
return;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Mentor Graphics and others.
* Copyright (c) 2012, 2014 Mentor Graphics 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
@ -8,6 +8,7 @@
* Contributors:
* Mentor Graphics - Initial API and implementation
* Salvatore Culcasi (ST) - Bug 407163 - GDB Console: breakpoint not added with MinGW and gdb
* Marc Khouzam (Ericsson) - Update breakpoint handling for GDB >= 7.4 (Bug 389945)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@ -294,9 +295,6 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
if (breakpointsService == null || bm == null)
return;
final IBreakpointsTargetDMContext bpTargetDMC = breakpointsService.getBreakpointTargetContext(id);
final IContainerDMContext contDMC = DMContexts.getAncestorOfType(bpTargetDMC, IContainerDMContext.class);
if (contDMC == null)
return;
if (bpTargetDMC != null){
final MIBreakpointDMContext bpDMC =
new MIBreakpointDMContext(breakpointsService, new IDMContext[] { bpTargetDMC }, id);
@ -327,6 +325,17 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
IDsfBreakpointExtension bpExtension =
(IDsfBreakpointExtension)((ICBreakpoint)plBpt).getExtension(
MIBreakpointsManager.GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
if (processes == null) {
return;
}
IContainerDMContext contDMC = processes.createContainerContextFromThreadId(getCommandControl().getContext(), data.getThreadId());
if (contDMC == null) {
return;
}
IExecutionDMContext[] execDMCs = bpExtension.getThreadFilters(contDMC);
List<IExecutionDMContext> list = new ArrayList<IExecutionDMContext>(execDMCs.length);
for (IExecutionDMContext c : execDMCs) {
@ -453,7 +462,12 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
MIBreakpoint miBpt) {
try {
IContainerDMContext contDMC = DMContexts.getAncestorOfType(bpTargetDMC, IContainerDMContext.class);
IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
if (processes == null) {
return;
}
String threadId = miBpt.getThreadId();
IContainerDMContext contDMC = processes.createContainerContextFromThreadId(getCommandControl().getContext(), threadId);
if (contDMC == null) {
return;
}
@ -462,20 +476,16 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
if (procDmc == null) {
return;
}
IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
if (processes == null) {
return;
}
IDsfBreakpointExtension bpExtension = (IDsfBreakpointExtension)plBpt.getExtension(
MIBreakpointsManager.GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
IExecutionDMContext[] execDMCs = bpExtension.getThreadFilters(contDMC);
if (execDMCs == null) {
execDMCs = new IExecutionDMContext[0];
}
int threadId = Integer.parseInt(miBpt.getThreadId());
int threadNum = Integer.parseInt(threadId);
for (IExecutionDMContext execDMC : execDMCs) {
if (execDMC instanceof IMIExecutionDMContext
&& ((IMIExecutionDMContext)execDMC).getThreadId() == threadId) {
&& ((IMIExecutionDMContext)execDMC).getThreadId() == threadNum) {
// The platform breakpoint is already restricted to the given thread.
return;
}
@ -484,8 +494,8 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
System.arraycopy(execDMCs, 0, newExecDMCs, 0, execDMCs.length);
newExecDMCs[execDMCs.length] = processes.createExecutionContext(
contDMC,
processes.createThreadContext(procDmc, miBpt.getThreadId()),
miBpt.getThreadId());
processes.createThreadContext(procDmc, threadId),
threadId);
bpExtension.setThreadFilters(newExecDMCs);
}
catch(NumberFormatException e) {
@ -723,6 +733,9 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
if (processes == null) {
return null;
}
// For GDB < 7.4, each process is its own breakpointTargetDMC so we need to find a the proper process
// based on the threadId. For GDB >= 7.4, this does not matter as we'll always end up with the global bpTargetDMC
String threadId = (miBpt != null) ? miBpt.getThreadId() : null;
IContainerDMContext contContext = processes.createContainerContextFromThreadId(commandControl.getContext(), threadId);
if (contContext == null) {
@ -1231,10 +1244,11 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
@DsfServiceEventHandler
public void eventDispatched(IExitedDMEvent e) {
if (e.getDMContext() instanceof IContainerDMContext) {
IBreakpointsTargetDMContext bpTargetDMContext =
DMContexts.getAncestorOfType(e.getDMContext(), IBreakpointsTargetDMContext.class);
if (bpTargetDMContext != null) {
if (e.getDMContext() instanceof IBreakpointsTargetDMContext) {
// Remove breakpoint entries when a breakpoint target is removed.
// This will happen for GDB < 7.4 where the container is the breakpoint target.
// For GDB >= 7.4, GDB is the breakpoint target and will not be removed.
IBreakpointsTargetDMContext bpTargetDMContext = (IBreakpointsTargetDMContext)e.getDMContext();
Map<Integer, MIBreakpoint> createdBreakpoints = fCreatedTargetBreakpoints.remove(bpTargetDMContext);
if (createdBreakpoints != null)
createdBreakpoints.clear();
@ -1244,7 +1258,6 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI
Set<Integer> deletedBreakpoints = fDeletedTargetBreakpoints.remove(bpTargetDMContext);
if (deletedBreakpoints != null)
deletedBreakpoints.clear();
}
}
}