mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 360735: Add support for multi-process for "Show Breakpoints
Supported by Selected Target" Change-Id: I8b64d5f7d8d87b6c6bce0737249207e9077a1d78 Reviewed-on: https://git.eclipse.org/r/7923 Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com> IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com> Tested-by: Marc Khouzam <marc.khouzam@ericsson.com>
This commit is contained in:
parent
f6ce109425
commit
1709e1b676
7 changed files with 381 additions and 38 deletions
|
@ -13,6 +13,7 @@
|
|||
package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.breakpoints;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -24,16 +25,19 @@ import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
|||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints.BreakpointVMProvider;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||
|
@ -103,16 +107,16 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
|
|||
@Override
|
||||
protected void calcFileteredBreakpoints( final DataRequestMonitor<IBreakpoint[]> rm ) {
|
||||
if ( Boolean.TRUE.equals( getPresentationContext().getProperty( IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION ) ) ) {
|
||||
if (fUseAggressiveBpFilter) {
|
||||
if ( fUseAggressiveBpFilter ) {
|
||||
// Aggressive filtering of breakpoints. Only return bps that are installed on the target.
|
||||
IBreakpointsTargetDMContext bpContext = null;
|
||||
IMIExecutionDMContext threadContext = null;
|
||||
IExecutionDMContext execContext = null;
|
||||
ISelection debugContext = getDebugContext();
|
||||
if ( debugContext instanceof IStructuredSelection ) {
|
||||
Object element = ((IStructuredSelection)debugContext).getFirstElement();
|
||||
Object element = ( (IStructuredSelection)debugContext ).getFirstElement();
|
||||
if ( element instanceof IDMVMContext ) {
|
||||
bpContext = DMContexts.getAncestorOfType( ((IDMVMContext)element).getDMContext(), IBreakpointsTargetDMContext.class );
|
||||
threadContext = DMContexts.getAncestorOfType( ((IDMVMContext)element).getDMContext(), IMIExecutionDMContext.class );
|
||||
execContext = DMContexts.getAncestorOfType( ((IDMVMContext)element).getDMContext(), IExecutionDMContext.class );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,17 +131,17 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
|
|||
return;
|
||||
}
|
||||
|
||||
getInstalledBreakpoints( bpContext, threadContext, rm );
|
||||
getInstalledBreakpoints( bpContext, execContext, rm );
|
||||
} else {
|
||||
// Original behavior of bp filtering. Return all bp of type ICBreakpoint
|
||||
IBreakpoint[] allBreakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints();
|
||||
List<IBreakpoint> filteredBPs = new ArrayList<IBreakpoint>(allBreakpoints.length);
|
||||
List<IBreakpoint> filteredBPs = new ArrayList<IBreakpoint>( allBreakpoints.length );
|
||||
for (IBreakpoint bp : allBreakpoints) {
|
||||
if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(CDebugCorePlugin.PLUGIN_ID)) {
|
||||
filteredBPs.add(bp);
|
||||
if ( bp instanceof ICBreakpoint && bp.getModelIdentifier().equals( CDebugCorePlugin.PLUGIN_ID ) ) {
|
||||
filteredBPs.add( bp );
|
||||
}
|
||||
}
|
||||
rm.done( filteredBPs.toArray(new IBreakpoint[filteredBPs.size()]) );
|
||||
rm.done( filteredBPs.toArray( new IBreakpoint[filteredBPs.size()]) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -221,7 +225,7 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
|
|||
return StructuredSelection.EMPTY;
|
||||
}
|
||||
|
||||
void getInstalledBreakpoints( final IBreakpointsTargetDMContext targetContext, final IMIExecutionDMContext threadContext, final DataRequestMonitor<IBreakpoint[]> rm ) {
|
||||
private void getInstalledBreakpoints( final IBreakpointsTargetDMContext targetContext, final IExecutionDMContext execContext, final DataRequestMonitor<IBreakpoint[]> rm ) {
|
||||
|
||||
try {
|
||||
fSession.getExecutor().execute( new DsfRunnable() {
|
||||
|
@ -237,7 +241,7 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
|
|||
rm.done();
|
||||
return;
|
||||
}
|
||||
bpService.getBreakpoints( targetContext, new DataRequestMonitor<IBreakpoints.IBreakpointDMContext[]>( fSession.getExecutor(), rm ) {
|
||||
bpService.getBreakpoints( targetContext, new DataRequestMonitor<IBreakpointDMContext[]>( fSession.getExecutor(), rm ) {
|
||||
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -267,7 +271,7 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
|
|||
for ( final IBreakpointDMContext bpCtx : getData() ) {
|
||||
bpService.getBreakpointDMData(
|
||||
bpCtx,
|
||||
new DataRequestMonitor<IBreakpoints.IBreakpointDMData>( ImmediateExecutor.getInstance(), crm ) {
|
||||
new DataRequestMonitor<IBreakpointDMData>( ImmediateExecutor.getInstance(), crm ) {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.dsf.concurrent.RequestMonitor#handleSuccess()
|
||||
|
@ -276,10 +280,19 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
|
|||
protected void handleSuccess() {
|
||||
if ( getData() instanceof MIBreakpointDMData ) {
|
||||
MIBreakpointDMData data = (MIBreakpointDMData)getData();
|
||||
if ( !data.isPending() && isThreadBreakpoint( threadContext, data )) {
|
||||
IBreakpoint bp = bpManager.findPlatformBreakpoint( bpCtx );
|
||||
if ( bp != null )
|
||||
bps.add( bp );
|
||||
if ( !data.isPending() ) {
|
||||
bpBelongsToContext( execContext, data, new ImmediateDataRequestMonitor<Boolean>(crm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (getData()) {
|
||||
IBreakpoint bp = bpManager.findPlatformBreakpoint( bpCtx );
|
||||
if ( bp != null )
|
||||
bps.add( bp );
|
||||
}
|
||||
crm.done();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
crm.done();
|
||||
|
@ -306,25 +319,55 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isThreadBreakpoint( IMIExecutionDMContext threadContext, MIBreakpointDMData data ) {
|
||||
if ( threadContext == null || data.getThreadId() == null || data.getThreadId().length() == 0 ) {
|
||||
// Ignore threads
|
||||
return true;
|
||||
private void bpBelongsToContext( IExecutionDMContext execContext, final MIBreakpointDMData data, final DataRequestMonitor<Boolean> rm ) {
|
||||
if ( execContext == null ) {
|
||||
// No execution context so accept all breakpoints
|
||||
rm.done( true );
|
||||
return;
|
||||
}
|
||||
|
||||
int threadId = threadContext.getThreadId();
|
||||
try {
|
||||
int bpThreadId = Integer.parseInt( data.getThreadId() );
|
||||
if ( bpThreadId == 0 )
|
||||
return true;
|
||||
return ( threadId == bpThreadId );
|
||||
|
||||
// First check if a thread is selected as the context. In that case, we only want to show breakpoints that
|
||||
// are applicable to that thread.
|
||||
IMIExecutionDMContext threadContext = DMContexts.getAncestorOfType( execContext, IMIExecutionDMContext.class );
|
||||
if ( threadContext != null ) {
|
||||
// A thread is selected. Now make sure this breakpoint is assigned to this thread.
|
||||
if ( data.getThreadId() != null && data.getThreadId().length() > 0 ) {
|
||||
try {
|
||||
int bpThreadId = Integer.parseInt( data.getThreadId() );
|
||||
// A threadId of 0 means all threads of this process. We therefore will have to check
|
||||
// if this breakpoint applies to the process that is selected. But if the threadId is not 0
|
||||
// we simply make sure we have the right thread selected.
|
||||
if ( bpThreadId != 0 ) {
|
||||
rm.done( threadContext.getThreadId() == bpThreadId );
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch( NumberFormatException e ) {
|
||||
assert false;
|
||||
GdbUIPlugin.getDefault().getLog().log( new Status(
|
||||
IStatus.ERROR,
|
||||
GdbUIPlugin.getUniqueIdentifier(),
|
||||
"Invalid breakpoint thread id" ) ); //$NON-NLS-1$
|
||||
rm.done( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here it is that the breakpoint is not assigned to a single thread.
|
||||
// We therefore make sure the breakpoint is applicable to the selected process.
|
||||
final IMIContainerDMContext containerContext = DMContexts.getAncestorOfType( execContext, IMIContainerDMContext.class );
|
||||
if ( containerContext != null ) {
|
||||
if ( data.getGroupIds() != null ) {
|
||||
List<String> groupIds = Arrays.asList( data.getGroupIds() );
|
||||
rm.done( groupIds.contains( containerContext.getGroupId() ) );
|
||||
} else {
|
||||
// This happens if we are debugging a single process, so all breakpoints apply.
|
||||
rm.done( true );
|
||||
}
|
||||
} else {
|
||||
// Accept breakpoint
|
||||
rm.done( true );
|
||||
}
|
||||
catch( NumberFormatException e ) {
|
||||
GdbUIPlugin.getDefault().getLog().log( new Status(
|
||||
IStatus.ERROR,
|
||||
GdbUIPlugin.getUniqueIdentifier(),
|
||||
"Invalid breakpoint thread id" ) ); //$NON-NLS-1$
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
* Contributors:
|
||||
* Ericsson - Initial API and implementation
|
||||
* Marc Khouzam (Ericsson) - Support for fast tracepoints (Bug 346320)
|
||||
* Marc Khouzam (Ericsson) - Fetch groupIds when getting breakpoints (Bug 360735)
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -27,7 +29,10 @@ 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.CLIInfoBreakInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
|
@ -89,6 +94,73 @@ public class GDBBreakpoints_7_2 extends GDBBreakpoints_7_0
|
|||
super.shutdown(requestMonitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Starting with GDB 7.2, also provides information about which process each breakpoint applies to.
|
||||
*/
|
||||
@Override
|
||||
public void getBreakpoints(final IBreakpointsTargetDMContext context, final DataRequestMonitor<IBreakpointDMContext[]> drm)
|
||||
{
|
||||
// Validate the context
|
||||
if (context == null) {
|
||||
drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT, null));
|
||||
drm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Select the breakpoints context map
|
||||
// If it doesn't exist then no breakpoint was ever inserted for this breakpoint space.
|
||||
// In that case, return an empty list.
|
||||
final Map<Integer, MIBreakpointDMData> breakpointContext = getBreakpointMap(context);
|
||||
if (breakpointContext == null) {
|
||||
drm.setData(new IBreakpointDMContext[0]);
|
||||
drm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the command
|
||||
fConnection.queueCommand(fConnection.getCommandFactory().createMIBreakList(context),
|
||||
new DataRequestMonitor<MIBreakListInfo>(getExecutor(), drm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
final MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
||||
|
||||
// Also fetch the information about which breakpoint belongs to which
|
||||
// process. We currently can only obtain this information from the CLI
|
||||
// command. This information is needed for breakpoint filtering.
|
||||
// Bug 360735
|
||||
fConnection.queueCommand(fConnection.getCommandFactory().createCLIInfoBreak(context),
|
||||
new ImmediateDataRequestMonitor<CLIInfoBreakInfo>(drm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
Map<Integer, String[]> groupIdMap = getData().getBreakpointToGroupMap();
|
||||
|
||||
// Refresh the breakpoints map and format the result
|
||||
breakpointContext.clear();
|
||||
IBreakpointDMContext[] result = new IBreakpointDMContext[breakpoints.length];
|
||||
for (int i = 0; i < breakpoints.length; i++) {
|
||||
MIBreakpointDMData breakpointData = new MIBreakpointDMData(breakpoints[i]);
|
||||
|
||||
// Now fill in the thread-group information into the breakpoint data
|
||||
// It is ok to get null. For example, pending breakpoints are not
|
||||
// associated to a thread-group; also, when debugging a single process,
|
||||
// the thread-group list is empty.
|
||||
int reference = breakpointData.getReference();
|
||||
String[] groupIds = groupIdMap.get(reference);
|
||||
breakpointData.setGroupIds(groupIds);
|
||||
|
||||
result[i] = new MIBreakpointDMContext(GDBBreakpoints_7_2.this, new IDMContext[] { context }, reference);
|
||||
breakpointContext.put(reference, breakpointData);
|
||||
}
|
||||
drm.setData(result);
|
||||
drm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setTracepointMode() {
|
||||
ILaunch launch = (ILaunch)getSession().getModelAdapter(ILaunch.class);
|
||||
String tpMode = IGDBLaunchConfigurationConstants.DEBUGGER_TRACEPOINT_MODE_DEFAULT;
|
||||
|
|
|
@ -269,6 +269,10 @@ public class MIBreakpointDMData implements IBreakpointDMData {
|
|||
return fBreakpoint.isEnabled();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MIBreakpointDMData
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
|
@ -283,10 +287,6 @@ public class MIBreakpointDMData implements IBreakpointDMData {
|
|||
return fBreakpoint.getCommands();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MIBreakpointDMData
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public int getNumber() {
|
||||
return fBreakpoint.getNumber();
|
||||
}
|
||||
|
@ -295,6 +295,16 @@ public class MIBreakpointDMData implements IBreakpointDMData {
|
|||
return fBreakpoint.getThreadId();
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
public String[] getGroupIds() {
|
||||
return fBreakpoint.getGroupIds();
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
public void setGroupIds(String[] groups) {
|
||||
fBreakpoint.setGroupIds(groups);
|
||||
}
|
||||
|
||||
public boolean isTemporary() {
|
||||
return fBreakpoint.isTemporary();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAttach;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIDetach;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIExecAbort;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoBreak;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoProgram;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoSharedLibrary;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoThreads;
|
||||
|
@ -167,6 +168,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowAttributes;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowFormat;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarUpdate;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoProgramInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoSharedLibraryInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoThreadsInfo;
|
||||
|
@ -241,6 +243,16 @@ public class CommandFactory {
|
|||
return new CLIExecAbort(ctx);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
public ICommand<CLIInfoBreakInfo> createCLIInfoBreak(IDMContext ctx) {
|
||||
return new CLIInfoBreak(ctx);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
public ICommand<CLIInfoBreakInfo> createCLIInfoBreak(IDMContext ctx, int bpRef) {
|
||||
return new CLIInfoBreak(ctx, bpRef);
|
||||
}
|
||||
|
||||
public ICommand<CLIInfoProgramInfo> createCLIInfoProgram(IContainerDMContext ctx) {
|
||||
return new CLIInfoProgram(ctx);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012 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.mi.service.command.commands;
|
||||
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
|
||||
|
||||
/**
|
||||
* 'info break [BP_REFERENCE]
|
||||
*
|
||||
* will return information about the specified breakpoint. If no breakpoint is
|
||||
* specified, it will return information about all breakpoints.
|
||||
* We use it to find out to which inferior a breakpoint is applicable.
|
||||
* This information is not available from -break-list or -break-info until GDB 7.6.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class CLIInfoBreak extends CLICommand<CLIInfoBreakInfo> {
|
||||
|
||||
private static final String INFO_BREAK = "info break"; //$NON-NLS-1$
|
||||
|
||||
public CLIInfoBreak(IDMContext ctx) {
|
||||
super(ctx, INFO_BREAK);
|
||||
};
|
||||
|
||||
public CLIInfoBreak(IDMContext ctx, int bpReference) {
|
||||
super(ctx, INFO_BREAK + Integer.toString(bpReference));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLIInfoBreakInfo getResult(MIOutput MIresult) {
|
||||
return new CLIInfoBreakInfo(MIresult);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012 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.mi.service.command.output;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 'info break [BP_REFERENCE] will return information about
|
||||
* the specified breakpoint. We use it to find out to which
|
||||
* inferiors a breakpoint is applicable.
|
||||
*
|
||||
* sample output:
|
||||
*
|
||||
* (gdb) info break
|
||||
* Num Type Disp Enb Address What
|
||||
* 1 breakpoint keep y <MULTIPLE>
|
||||
* 1.1 y 0x08048533 in main() at loopfirst.cc:8 inf 2
|
||||
* 1.2 y 0x08048533 in main() at loopfirst.cc:8 inf 1
|
||||
* 2 breakpoint keep y <MULTIPLE>
|
||||
* 2.1 y 0x08048553 in main() at loopfirst.cc:9 inf 2
|
||||
* 2.2 y 0x08048553 in main() at loopfirst.cc:9 inf 1
|
||||
*
|
||||
* If only one inferior is being debugged there is not mention of the inferior:
|
||||
* (gdb) info break
|
||||
* Num Type Disp Enb Address What
|
||||
* 1 breakpoint keep y 0x08048533 in main() at loopfirst.cc:8
|
||||
* 2 breakpoint keep y 0x08048553 in main() at loopfirst.cc:9
|
||||
*
|
||||
* Note that the below output is theoretically possible looking at GDB's code but
|
||||
* I haven't figured out a way to trigger it. Still, we should be prepared for it:
|
||||
* (gdb) info break
|
||||
* Num Type Disp Enb Address What
|
||||
* 1 breakpoint keep y <MULTIPLE>
|
||||
* 1.1 y 0x08048533 in main() at loopfirst.cc:8 inf 3, 2
|
||||
* 1.2 y 0x08048533 in main() at loopfirst.cc:8 inf 2, 1
|
||||
* 2 breakpoint keep y <MULTIPLE>
|
||||
* 2.1 y 0x08048553 in main() at loopfirst.cc:9 inf 2, 1
|
||||
* 2.2 y 0x08048553 in main() at loopfirst.cc:9 inf 3, 2, 1
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class CLIInfoBreakInfo extends MIInfo {
|
||||
|
||||
private Map<Integer, String[]> fBreakpointToGroupMap = new HashMap<Integer, String[]>();
|
||||
|
||||
public CLIInfoBreakInfo(MIOutput out) {
|
||||
super(out);
|
||||
parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map of breakpoint to groupId array indicating to which thread-group
|
||||
* each breakpoint applies. If there is only a single thread-group being debugged, an
|
||||
* empty map will be returned.
|
||||
*/
|
||||
public Map<Integer, String[]> getBreakpointToGroupMap() {
|
||||
return fBreakpointToGroupMap;
|
||||
}
|
||||
|
||||
protected void parse() {
|
||||
final String INFERIOR_PREFIX = " inf "; //$NON-NLS-1$
|
||||
if (isDone()) {
|
||||
MIOutput out = getMIOutput();
|
||||
for (MIOOBRecord oob : out.getMIOOBRecords()) {
|
||||
if (oob instanceof MIConsoleStreamOutput) {
|
||||
String line = ((MIConsoleStreamOutput)oob).getString().trim();
|
||||
int loc = line.indexOf(INFERIOR_PREFIX);
|
||||
if (loc >= 0) {
|
||||
// Get the breakpoint id by extracting the first element before a white space
|
||||
// or before a period. We can set a limit of 2 since we only need the first element
|
||||
String bpIdStr = line.split("[\\s\\.]", 2)[0]; //$NON-NLS-1$
|
||||
int bpId = 0;
|
||||
try {
|
||||
bpId = Integer.parseInt(bpIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
assert false;
|
||||
}
|
||||
|
||||
String[] groups = fBreakpointToGroupMap.get(bpId);
|
||||
Set<String> groupIdList = new HashSet<String>();
|
||||
if (groups != null) {
|
||||
// Since we already know about this breakpoint id we must retain the list
|
||||
// we have been building
|
||||
groupIdList.addAll(Arrays.asList(groups));
|
||||
}
|
||||
|
||||
// Get the comma-separated list of inferiors
|
||||
// Split the list into individual ids
|
||||
String inferiorIdStr = line.substring(loc + INFERIOR_PREFIX.length()).trim();
|
||||
for (String id : inferiorIdStr.split(",")) { //$NON-NLS-1$
|
||||
// Add the 'i' prefix as GDB does for MI commands
|
||||
groupIdList.add("i" + id.trim()); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
fBreakpointToGroupMap.put(bpId, groupIdList.toArray(new String[groupIdList.size()]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,10 +11,14 @@
|
|||
* Ericsson - Modified for the breakpoint service
|
||||
* Ericsson - Added Tracepoint support (284286)
|
||||
* Abeer Bagul (Tensilica) - Differentiate between hw breakpoint and watchpoint
|
||||
* Marc Khouzam (Ericsson) - Add 'thread-group' field (bug 360735)
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.mi.service.command.output;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.TracepointActionManager;
|
||||
|
@ -105,6 +109,13 @@ public class MIBreakpoint {
|
|||
*/
|
||||
private boolean pending;
|
||||
|
||||
/**
|
||||
* The list of groupIds to which this breakpoint applies.
|
||||
* This field is only reported by MI starting with GDB 7.6.
|
||||
* null will be returned if this field is not present.
|
||||
*/
|
||||
private String[] groupIds;
|
||||
|
||||
public MIBreakpoint() {
|
||||
}
|
||||
|
||||
|
@ -134,6 +145,9 @@ public class MIBreakpoint {
|
|||
isCatchpoint = other.isCatchpoint;
|
||||
catchpointType = other.catchpointType;
|
||||
pending = other.pending;
|
||||
if (other.groupIds != null) {
|
||||
groupIds = Arrays.copyOf(other.groupIds, other.groupIds.length);
|
||||
}
|
||||
}
|
||||
|
||||
public MIBreakpoint(MITuple tuple) {
|
||||
|
@ -409,6 +423,25 @@ public class MIBreakpoint {
|
|||
return pending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread-groups to which this breakpoint applies.
|
||||
* Returns null if the data is not known.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public String[] getGroupIds() {
|
||||
return groupIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of thread-groups to which this breakpoint applies.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public void setGroupIds(String[] groups) {
|
||||
groupIds = groups;
|
||||
}
|
||||
|
||||
// Parse the result string
|
||||
void parse(MITuple tuple) {
|
||||
MIResult[] results = tuple.getMIResults();
|
||||
|
@ -504,6 +537,10 @@ public class MIBreakpoint {
|
|||
if (value instanceof MITuple) {
|
||||
parseCommands((MITuple)value);
|
||||
}
|
||||
} else if (var.equals("thread-group")) { //$NON-NLS-1$
|
||||
if (value instanceof MIList) {
|
||||
parseGroups((MIList)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -524,4 +561,17 @@ public class MIBreakpoint {
|
|||
setCommands(cmds.toString());
|
||||
|
||||
}
|
||||
|
||||
private void parseGroups(MIList list) {
|
||||
List<String> groups = new ArrayList<String>();
|
||||
|
||||
MIValue[] values = list.getMIValues();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (values[i] instanceof MIConst) {
|
||||
groups.add(((MIConst)values[i]).getCString());
|
||||
}
|
||||
}
|
||||
|
||||
groupIds = groups.toArray(new String[groups.size()]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue