/*******************************************************************************
* Copyright (c) 2012, 2016 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
* http://www.eclipse.org/legal/epl-v10.html
*
* 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)
* Marc Khouzam (Ericsson) - Support for dynamic printf (Bug 400628)
* Jonah Graham (Kichwa Coders) - Bug 317173 - cleanup warnings
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.breakpointactions.BreakpointActionManager;
import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpointExtension;
import org.eclipse.cdt.debug.core.model.ICBreakpointType;
import org.eclipse.cdt.debug.core.model.ICDynamicPrintf;
import org.eclipse.cdt.debug.core.model.ICFunctionBreakpoint;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
import org.eclipse.cdt.debug.core.model.ICTracepoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
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.IDsfBreakpointExtension;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.CollectAction;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.EvaluateAction;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.ITracepointAction;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.TracepointActionManager;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.WhileSteppingAction;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager.IMIBreakpointsTrackingListener;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
import org.osgi.framework.BundleContext;
/**
* Provides synchronization between breakpoints set from outside of the Eclipse breakpoint
* framework (GDB console, trace files, etc.) and the Breakpoints view.
* @since 4.2
*/
public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMIBreakpointsTrackingListener {
// Catchpoint expressions
private static final String CE_EXCEPTION_CATCH = "exception catch"; //$NON-NLS-1$
private static final String CE_EXCEPTION_THROW = "exception throw"; //$NON-NLS-1$
// GDB tracepoint commands
private static final String TC_COLLECT = "collect "; //$NON-NLS-1$
private static final String TC_TEVAL = "teval "; //$NON-NLS-1$
private static final String TC_WHILE_STEPPING = "while-stepping "; //$NON-NLS-1$
private static final String TC_END = "end"; //$NON-NLS-1$
private IMICommandControl fConnection;
private MIBreakpoints fBreakpointsService;
private MIBreakpointsManager fBreakpointsManager;
/**
* Collection of the target contexts that are being tracked.
*/
private Set<IBreakpointsTargetDMContext> fTrackedTargets;
/**
* Collection of breakpoints created from the GDB console or outside of Eclipse
*/
private Map<IBreakpointsTargetDMContext, Map<String, MIBreakpoint>> fCreatedTargetBreakpoints;
/**
* Collection of breakpoints deleted from the GDB console or outside of Eclipse
*/
private Map<IBreakpointsTargetDMContext, Set<String>> fDeletedTargetBreakpoints;
/**
* Collection of pending breakpoint modifications
*/
private Map<IBreakpointsTargetDMContext, Map<String, MIBreakpoint>> fPendingModifications;
public MIBreakpointsSynchronizer(DsfSession session) {
super(session);
fTrackedTargets = new HashSet<IBreakpointsTargetDMContext>();
fCreatedTargetBreakpoints = new HashMap<IBreakpointsTargetDMContext, Map<String, MIBreakpoint>>();
fDeletedTargetBreakpoints = new HashMap<IBreakpointsTargetDMContext, Set<String>>();
fPendingModifications = new HashMap<IBreakpointsTargetDMContext, Map<String, MIBreakpoint>>();
}
@Override
protected BundleContext getBundleContext() {
return GdbPlugin.getBundleContext();
}
@Override
public void initialize(final RequestMonitor rm) {
super.initialize(new ImmediateRequestMonitor(rm) {
@Override
protected void handleSuccess() {
doInitialize(rm);
}
});
}
private void doInitialize(final RequestMonitor rm) {
fConnection = getServicesTracker().getService(IMICommandControl.class);
fBreakpointsService = getServicesTracker().getService(MIBreakpoints.class);
fBreakpointsManager = getServicesTracker().getService(MIBreakpointsManager.class);
if (fConnection == null || fBreakpointsService == null && fBreakpointsManager == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Service is not available")); //$NON-NLS-1$
rm.done();
return;
}
fBreakpointsManager.addBreakpointsTrackingListener(this);
getSession().addServiceEventListener(this, null);
// Register this service
register(new String[] {
MIBreakpointsSynchronizer.class.getName()
},
new Hashtable<String, String>());
rm.done();
}
@Override
public void shutdown(RequestMonitor rm) {
fTrackedTargets.clear();
fCreatedTargetBreakpoints.clear();
fDeletedTargetBreakpoints.clear();
fPendingModifications.clear();
getSession().removeServiceEventListener(this);
MIBreakpointsManager bm = getBreakpointsManager();
if (bm != null) {
bm.removeBreakpointsTrackingListener(this);
}
unregister();
super.shutdown( rm );
}
@Override
public void breakpointTrackingStarted(IBreakpointsTargetDMContext bpTargetDMC) {
fTrackedTargets.add(bpTargetDMC);
}
@Override
public void breakpointTrackingStopped(IBreakpointsTargetDMContext bpTargetDMC) {
fTrackedTargets.remove(bpTargetDMC);
}
private IMICommandControl getCommandControl() {
return fConnection;
}
private MIBreakpoints getBreakpointsService() {
return fBreakpointsService;
}
private MIBreakpointsManager getBreakpointsManager() {
return fBreakpointsManager;
}
public void targetBreakpointCreated(final MIBreakpoint miBpt) {
if (isCatchpoint(miBpt)) {
return;
}
ICommandControlService commandControl = getCommandControl();
MIBreakpoints breakpointsService = getBreakpointsService();
final MIBreakpointsManager bm = getBreakpointsManager();
if (commandControl == null || breakpointsService == null || bm == null) {
return;
}
final IBreakpointsTargetDMContext bpTargetDMC = getBreakpointsTargetContext(commandControl, miBpt);
if (bpTargetDMC == null) {
return;
}
// Store the target breakpoint data
Map<String, MIBreakpointDMData> contextBreakpoints = breakpointsService.getBreakpointMap(bpTargetDMC);
if (contextBreakpoints == null) {
contextBreakpoints = breakpointsService.createNewBreakpointMap(bpTargetDMC);
}
contextBreakpoints.put(miBpt.getNumber(), new MIBreakpointDMData(miBpt));
// Store the created target breakpoint to prevent setting it again on the target
// when addBreakpoint() is called.
Map<String, MIBreakpoint> targetMap = fCreatedTargetBreakpoints.get(bpTargetDMC);
if (targetMap == null) {
targetMap = new HashMap<String, MIBreakpoint>();
fCreatedTargetBreakpoints.put(bpTargetDMC, targetMap);
}
targetMap.put(miBpt.getNumber(), miBpt);
// Convert the debug info file path into the file path in the local file system
String debuggerPath = getFileName(miBpt);
getSource(
bpTargetDMC,
debuggerPath,
new DataRequestMonitor<String>(getExecutor(), null) {
@Override
@ConfinedToDsfExecutor( "fExecutor" )
protected void handleSuccess() {
String fileName = getData();
if (fileName == null) {
fileName = getFileName(miBpt);
}
// Try to find matching platform breakpoint
ICBreakpoint plBpt = getPlatformBreakpoint(miBpt, fileName);
String threadId = miBpt.getThreadId();
boolean isThreadSpecific = threadId != null && !threadId.isEmpty() && !"0".equals(threadId); //$NON-NLS-1$
try {
if (plBpt == null) {
// If matching platform breakpoint doesn't exist create a new one
plBpt = createPlatformBreakpoint(fileName, miBpt);
// If the target breakpoint is thread specific, update thread filters
if (isThreadSpecific) {
setThreadSpecificBreakpoint(plBpt, miBpt);
}
}
else {
// The corresponding platform breakpoint already exists.
// If the breakpoint tracking has already started we need
// to notify MIBreakpointsManager which will increment its
// install count.
// Otherwise the breakpoint will be processed as an initial
// breakpoint when the breakpoint tracking starts.
if (isBreakpointTargetTracked(bpTargetDMC)) {
// If the target breakpoint is thread specific, update thread filters
if (isThreadSpecific) {
setThreadSpecificBreakpoint(plBpt, miBpt);
}
bm.breakpointAdded(plBpt);
}
}
// Make sure the platform breakpoint's parameters are synchronized
// with the target breakpoint.
Map<String, MIBreakpoint> map = fPendingModifications.get(bpTargetDMC);
if (map != null) {
MIBreakpoint mod = map.remove(miBpt.getNumber());
if (mod != null) {
targetBreakpointModified(bpTargetDMC, plBpt, mod);
}
}
else {
targetBreakpointModified(bpTargetDMC, plBpt, miBpt);
}
}
catch(CoreException e) {
GdbPlugin.log(getStatus());
}
super.handleSuccess();
}
});
}
/**
* @since 5.0
*/
public void targetBreakpointDeleted(final String id) {
MIBreakpoints breakpointsService = getBreakpointsService();
final MIBreakpointsManager bm = getBreakpointsManager();
if (breakpointsService == null || bm == null) {
return;
}
final IBreakpointsTargetDMContext bpTargetDMC = breakpointsService.getBreakpointTargetContext(id);
if (bpTargetDMC != null){
final MIBreakpointDMContext bpDMC =
new MIBreakpointDMContext(breakpointsService, new IDMContext[] { bpTargetDMC }, id);
breakpointsService.getBreakpointDMData(
bpDMC,
new DataRequestMonitor<IBreakpointDMData>(getExecutor(), null) {
@Override
@ConfinedToDsfExecutor( "fExecutor" )
protected void handleSuccess() {
if (!(getData() instanceof MIBreakpointDMData)) {
return;
}
MIBreakpointDMData data = (MIBreakpointDMData)getData();
if (MIBreakpoints.CATCHPOINT.equals(data.getBreakpointType())) {
return;
}
IBreakpoint plBpt = bm.findPlatformBreakpoint(bpDMC);
if (plBpt instanceof ICBreakpoint) {
Set<String> set = fDeletedTargetBreakpoints.get(bpTargetDMC);
if (set == null) {
set = new HashSet<String>();
fDeletedTargetBreakpoints.put(bpTargetDMC, set);
}
set.add(id);
try {
String threadId = data.getThreadId();
if (!threadId.equals("0")) { //$NON-NLS-1$
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) {
if (c instanceof IMIExecutionDMContext
&& !((IMIExecutionDMContext)c).getThreadId().equals(threadId)) {
list.add(c);
}
}
if (!list.isEmpty()) {
bpExtension.setThreadFilters(list.toArray(new IExecutionDMContext[list.size()]));
}
else {
bm.uninstallBreakpoint(bpTargetDMC, (ICBreakpoint)plBpt, new RequestMonitor(getExecutor(), null));
}
}
else {
bm.uninstallBreakpoint(bpTargetDMC, (ICBreakpoint)plBpt, new RequestMonitor(getExecutor(), null));
}
}
catch(CoreException e) {
GdbPlugin.log(e.getStatus());
}
}
}
});
}
}
public void targetBreakpointModified(final MIBreakpoint miBpt) {
if (isCatchpoint(miBpt)) {
return;
}
ICommandControlService commandControl = getCommandControl();
MIBreakpoints breakpointsService = getBreakpointsService();
final MIBreakpointsManager bm = getBreakpointsManager();
if (commandControl != null && breakpointsService != null && bm != null) {
final IBreakpointsTargetDMContext bpTargetDMC = getBreakpointsTargetContext(commandControl, miBpt);
if (bpTargetDMC == null) {
return;
}
final Map<String, MIBreakpointDMData> contextBreakpoints = breakpointsService.getBreakpointMap(bpTargetDMC);
if (contextBreakpoints == null) {
return;
}
IBreakpoint b = bm.findPlatformBreakpoint(
new MIBreakpointDMContext(breakpointsService, new IDMContext[] { bpTargetDMC }, miBpt.getNumber()));
if (!(b instanceof ICBreakpoint)) {
// Platform breakpoint hasn't been created yet. Store the latest
// modification data, it will be picked up later.
Map<String, MIBreakpoint> map = fPendingModifications.get(bpTargetDMC);
if (map == null) {
map = new HashMap<String, MIBreakpoint>();
fPendingModifications.put(bpTargetDMC, map);
}
map.put(miBpt.getNumber(), miBpt);
}
else {
ICBreakpoint plBpt = (ICBreakpoint)b;
targetBreakpointModified(bpTargetDMC, plBpt, miBpt);
}
}
}
private void targetBreakpointModified(
IBreakpointsTargetDMContext bpTargetDMC,
ICBreakpoint plBpt,
MIBreakpoint miBpt) {
Map<String, MIBreakpointDMData> contextBreakpoints = getBreakpointsService().getBreakpointMap(bpTargetDMC);
MIBreakpointDMData oldData = contextBreakpoints.get(miBpt.getNumber());
contextBreakpoints.put(miBpt.getNumber(), new MIBreakpointDMData(miBpt));
try {
if (plBpt.isEnabled() != miBpt.isEnabled()) {
plBpt.setEnabled(miBpt.isEnabled());
}
if (!plBpt.getCondition().equals(miBpt.getCondition())) {
plBpt.setCondition(miBpt.getCondition());
}
if (plBpt.getIgnoreCount() != miBpt.getIgnoreCount()) {
plBpt.setIgnoreCount(miBpt.getIgnoreCount());
}
if (oldData.isPending() != miBpt.isPending()) {
if (miBpt.isPending()) {
plBpt.decrementInstallCount();
} else {
plBpt.incrementInstallCount();
}
}
if (plBpt instanceof ICTracepoint && miBpt.isTracepoint()) {
ICTracepoint plTpt = (ICTracepoint)plBpt;
if (plTpt.getPassCount() != miBpt.getPassCount()) {
// GDB (up to 7.5) doesn't emit notification when the pass count is modified.
plTpt.setPassCount(miBpt.getPassCount());
}
if (!miBpt.getCommands().equals(plBpt.getMarker().getAttribute(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE))) {
StringBuilder sb = new StringBuilder();
boolean first = true;
String[] commands = miBpt.getCommands().split(TracepointActionManager.TRACEPOINT_ACTION_DELIMITER);
for (ITracepointAction action : getActionsFromCommands(commands)) {
if (first) {
first = false;
} else {
sb.append(TracepointActionManager.TRACEPOINT_ACTION_DELIMITER);
}
sb.append(action.getName());
}
// Target breakpoints and platform breakpoints use the same format
// to store trace commands. This format is different than the format
// used by GDB. We need to switch to the platform format to avoid unnecessary
// modifications of target breakpoints.
miBpt.setCommands(sb.toString());
plBpt.getMarker().setAttribute(
BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE, sb.toString());
}
} else if (plBpt instanceof ICDynamicPrintf && miBpt.isDynamicPrintf()) {
// Cannot synchronize the string as there is a bug in GDB 7.7 that corrupts it.
// https://sourceware.org/bugzilla/show_bug.cgi?id=15806
// If we were to synchronize here, we would overwrite the string defined by
// the user with the corrupted one!
// Truth is that we don't need to synchronize the string anyway because there
// is currently no way to change a dprintf string in GDB; instead a new
// dprintf must be created. That means that there will be no =breakpoint-modifed
// event that indicates a real dprintf string change; only the other fields can
// change and are handled as any other breakpoint.
//
// ICDynamicPrintf plDPrintf = (ICDynamicPrintf)plBpt;
// if (!plDPrintf.getPrintfString().equals(miBpt.getPrintfString())) {
// plDPrintf.setPrintfString(miBpt.getPrintfString());
// }
}
}
catch(CoreException e) {
contextBreakpoints.put(miBpt.getNumber(), oldData);
GdbPlugin.log(e.getStatus());
}
}
private void setThreadSpecificBreakpoint(
final ICBreakpoint plBpt,
MIBreakpoint miBpt) {
try {
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;
}
IProcessDMContext procDmc =
DMContexts.getAncestorOfType(contDMC, IProcessDMContext.class);
if (procDmc == 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];
}
for (IExecutionDMContext execDMC : execDMCs) {
String ctxThreadId = ((IMIExecutionDMContext)execDMC).getThreadId();
if (execDMC instanceof IMIExecutionDMContext && ctxThreadId.equals(threadId)) {
// The platform breakpoint is already restricted to the given thread.
return;
}
}
IExecutionDMContext[] newExecDMCs = new IExecutionDMContext[execDMCs.length + 1];
System.arraycopy(execDMCs, 0, newExecDMCs, 0, execDMCs.length);
newExecDMCs[execDMCs.length] = processes.createExecutionContext(
contDMC,
processes.createThreadContext(procDmc, threadId),
threadId);
bpExtension.setThreadFilters(newExecDMCs);
}
catch(CoreException e) {
GdbPlugin.log(e);
}
}
private ICBreakpoint getPlatformBreakpoint(MIBreakpoint miBpt, String fileName) {
for (IBreakpoint b : DebugPlugin.getDefault().getBreakpointManager().getBreakpoints()) {
if (b instanceof ICTracepoint
&& miBpt.isTracepoint()
&& isPlatformTracepoint((ICTracepoint)b, miBpt, fileName)) {
return (ICBreakpoint)b;
}
if (b instanceof ICDynamicPrintf
&& miBpt.isDynamicPrintf()
&& isPlatformDynamicPrintf((ICDynamicPrintf)b, miBpt, fileName)) {
return (ICBreakpoint)b;
}
if (b instanceof ICWatchpoint
&& miBpt.isWatchpoint()
&& isPlatformWatchpoint((ICWatchpoint)b, miBpt)) {
return (ICBreakpoint)b;
}
if (b instanceof ICLineBreakpoint
&& !miBpt.isWatchpoint()
&& !isCatchpoint(miBpt)
&& !miBpt.isTracepoint()
&& !miBpt.isDynamicPrintf()
&& isPlatformLineBreakpoint((ICLineBreakpoint)b, miBpt, fileName)) {
return (ICBreakpoint)b;
}
}
return null;
}
private ICBreakpoint createPlatformBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
if (miBpt.isWatchpoint()) {
return createPlatformWatchpoint(fileName, miBpt);
}
else if (miBpt.isTracepoint()) {
return createPlatformTracepoint(fileName, miBpt);
}
else if (miBpt.isDynamicPrintf()) {
return createPlatformDynamicPrintf(fileName, miBpt);
}
else {
return createPlatformLocationBreakpoint(fileName, miBpt);
}
}
private ICBreakpoint createPlatformLocationBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
if (isAddressBreakpoint(miBpt)) {
return createPlatformAddressBreakpoint(fileName, miBpt);
}
else if (isFunctionBreakpoint(miBpt)) {
return createPlatformFunctionBreakpoint(fileName, miBpt);
}
else {
return createPlatformLineBreakpoint(fileName, miBpt);
}
}
private ICBreakpoint createPlatformAddressBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
try {
return CDIDebugModel.createAddressBreakpoint(
null,
null,
resource,
type,
getPlatformAddress(miBpt.getAddress()),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
true);
}
catch(NumberFormatException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
String.format("Invalid breakpoint address: %s", miBpt.getAddress()))); //$NON-NLS-1$
}
}
private ICBreakpoint createPlatformFunctionTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
return CDIDebugModel.createFunctionTracepoint(
fileName,
resource,
type,
getFunctionName(miBpt),
-1,
-1,
getLineNumber(miBpt),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
true);
}
private ICBreakpoint createPlatformLineTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
return CDIDebugModel.createLineTracepoint(
fileName,
resource,
type,
getLineNumber(miBpt),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
true);
}
private ICBreakpoint createPlatformTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
if (isAddressBreakpoint(miBpt)) {
return createPlatformAddressTracepoint(fileName, miBpt);
}
else if (isFunctionBreakpoint(miBpt)) {
return createPlatformFunctionTracepoint(fileName, miBpt);
}
else {
return createPlatformLineTracepoint(fileName, miBpt);
}
}
private ICBreakpoint createPlatformAddressTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
try {
return CDIDebugModel.createAddressTracepoint(
null,
null,
resource,
type,
getLineNumber(miBpt),
getPlatformAddress(miBpt.getAddress()),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
true);
}
catch(NumberFormatException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
String.format("Invalid breakpoint address: %s", miBpt.getAddress()))); //$NON-NLS-1$
}
}
private ICBreakpoint createPlatformFunctionBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
return CDIDebugModel.createFunctionBreakpoint(
fileName,
resource,
type,
getFunctionName(miBpt),
-1,
-1,
getLineNumber(miBpt),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
true);
}
private ICBreakpoint createPlatformLineBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
return CDIDebugModel.createLineBreakpoint(
fileName,
resource,
type,
getLineNumber(miBpt),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
true);
}
private ICBreakpoint createPlatformDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
if (isAddressBreakpoint(miBpt)) {
return createPlatformAddressDynamicPrintf(fileName, miBpt);
}
// TODO This is currently causing problems because we think a normal dprintf is a function one
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=400628#c16 which says:
// "synchronization of function dprintf does not work"
// else if (isFunctionBreakpoint(miBpt)) {
// return createPlatformFunctionDynamicPrintf(fileName, miBpt);
// }
else {
return createPlatformLineDynamicPrintf(fileName, miBpt);
}
}
private ICBreakpoint createPlatformAddressDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
try {
return CDIDebugModel.createAddressDynamicPrintf(
null,
null,
resource,
type,
getLineNumber(miBpt),
getPlatformAddress(miBpt.getAddress()),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
miBpt.getPrintfString(),
true);
}
catch(NumberFormatException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
String.format("Invalid breakpoint address: %s", miBpt.getAddress()))); //$NON-NLS-1$
}
}
// Unused, see TODO in createPlatformDynamicPrintf and Bug 400628 Comment 16
@SuppressWarnings("unused")
private ICBreakpoint createPlatformFunctionDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
return CDIDebugModel.createFunctionDynamicPrintf(
fileName,
resource,
type,
getFunctionName(miBpt),
-1,
-1,
getLineNumber(miBpt),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
miBpt.getPrintfString(),
true);
}
private ICBreakpoint createPlatformLineDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
return CDIDebugModel.createLineDynamicPrintf(
fileName,
resource,
type,
getLineNumber(miBpt),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
miBpt.getPrintfString(),
true);
}
private ICBreakpoint createPlatformWatchpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
IResource resource = getResource(fileName);
int type = 0;
if (miBpt.isTemporary()) {
type |= ICBreakpointType.TEMPORARY;
}
if (miBpt.isHardware()) {
type |= ICBreakpointType.HARDWARE;
}
return CDIDebugModel.createWatchpoint(
fileName,
resource,
type,
miBpt.isAccessWatchpoint() || miBpt.isWriteWatchpoint(),
miBpt.isAccessWatchpoint() || miBpt.isReadWatchpoint(),
miBpt.getExpression(),
miBpt.isEnabled(),
miBpt.getIgnoreCount(),
miBpt.getCondition(),
true);
}
private IBreakpointsTargetDMContext getBreakpointsTargetContext(ICommandControlService commandControl, MIBreakpoint miBpt) {
IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
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) {
return null;
}
return DMContexts.getAncestorOfType(contContext, IBreakpointsTargetDMContext.class);
}
public void getTargetBreakpoint(
IBreakpointsTargetDMContext context,
Map<String, Object> attributes,
DataRequestMonitor<MIBreakpoint> rm) {
Map<String, MIBreakpoint> map = fCreatedTargetBreakpoints.get(context);
if (map == null) {
rm.done();
return;
}
String type = (String)attributes.get(MIBreakpoints.BREAKPOINT_TYPE);
if (MIBreakpoints.BREAKPOINT.equals(type)) {
rm.done(getTargetLineBreakpoint(
map.values(),
(String)attributes.get(MIBreakpoints.FILE_NAME),
(Integer)attributes.get(MIBreakpoints.LINE_NUMBER),
(String)attributes.get(MIBreakpoints.FUNCTION),
(String)attributes.get(MIBreakpoints.ADDRESS),
(Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
(Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
}
else if (MIBreakpoints.TRACEPOINT.equals(type)) {
rm.done(getTargetTracepoint(
map.values(),
(String)attributes.get(MIBreakpoints.FILE_NAME),
(Integer)attributes.get(MIBreakpoints.LINE_NUMBER),
(String)attributes.get(MIBreakpoints.FUNCTION),
(String)attributes.get(MIBreakpoints.ADDRESS),
(Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
(Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
}
else if (MIBreakpoints.DYNAMICPRINTF.equals(type)) {
rm.done(getTargetDPrintf(
map.values(),
(String)attributes.get(MIBreakpoints.FILE_NAME),
(Integer)attributes.get(MIBreakpoints.LINE_NUMBER),
(String)attributes.get(MIBreakpoints.FUNCTION),
(String)attributes.get(MIBreakpoints.ADDRESS),
(Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
(Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
}
else if (MIBreakpoints.WATCHPOINT.equals(type)) {
rm.done(getTargetWatchpoint(
map.values(),
(String)attributes.get(MIBreakpoints.EXPRESSION),
(Boolean)attributes.get(MIBreakpoints.READ),
(Boolean)attributes.get(MIBreakpoints.WRITE),
(Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
(Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
} else {
rm.done();
}
}
private MIBreakpoint getTargetLineBreakpoint(
Collection<MIBreakpoint> targetBreakpoints,
String fileName,
Integer lineNumber,
String function,
String address,
Boolean isHardware,
Boolean isTemporary) {
for (MIBreakpoint miBpt : targetBreakpoints) {
if (!miBpt.isWatchpoint() && !isCatchpoint(miBpt) && !miBpt.isTracepoint() && !miBpt.isDynamicPrintf()
&& compareBreakpointAttributes(
miBpt, fileName, lineNumber, function, address, isHardware, isTemporary)) {
return miBpt;
}
}
return null;
}
private MIBreakpoint getTargetTracepoint(
Collection<MIBreakpoint> targetBreakpoints,
String fileName,
Integer lineNumber,
String function,
String address,
Boolean isHardware,
Boolean isTemporary) {
for (MIBreakpoint miBpt : targetBreakpoints) {
if (miBpt.isTracepoint()
&& compareBreakpointAttributes(
miBpt, fileName, lineNumber, function, address, isHardware, isTemporary)) {
return miBpt;
}
}
return null;
}
private MIBreakpoint getTargetDPrintf(
Collection<MIBreakpoint> targetBreakpoints,
String fileName,
Integer lineNumber,
String function,
String address,
Boolean isHardware,
Boolean isTemporary) {
for (MIBreakpoint miBpt : targetBreakpoints) {
if (miBpt.isDynamicPrintf()
&& compareBreakpointAttributes(
miBpt, fileName, lineNumber, function, address, isHardware, isTemporary)) {
return miBpt;
}
}
return null;
}
private MIBreakpoint getTargetWatchpoint(
Collection<MIBreakpoint> targetBreakpoints,
String expression,
boolean readAccess,
boolean writeAccess,
Boolean isHardware,
Boolean isTemporary) {
for (MIBreakpoint miBpt : targetBreakpoints) {
if (!miBpt.isWatchpoint()) {
continue;
}
if (expression == null || !expression.equals(miBpt.getExpression())) {
continue;
}
if (readAccess && writeAccess && !miBpt.isAccessWatchpoint()) {
continue;
}
if (readAccess && !writeAccess && !miBpt.isReadWatchpoint()) {
continue;
}
if (!readAccess && writeAccess && !miBpt.isWriteWatchpoint()) {
continue;
}
if (!compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary)) {
continue;
}
return miBpt;
}
return null;
}
private boolean compareBreakpointAttributes(
MIBreakpoint miBpt,
String fileName,
Integer lineNumber,
String function,
String address,
Boolean isHardware,
Boolean isTemporary) {
return compareBreakpointLocationAttributes(miBpt, fileName, lineNumber, function, address)
&& compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary);
}
private boolean compareBreakpointLocationAttributes(
MIBreakpoint miBpt,
String fileName,
Integer lineNumber,
String function,
String address) {
if (isFunctionBreakpoint(miBpt) && (function == null || !function.equals(getFunctionName(miBpt)))) {
return false;
}
if (isAddressBreakpoint(miBpt)
&& (address == null || !address.equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString()))) {
return false;
}
if (isLineBreakpoint(miBpt)) {
String miBptFileName = getFileName(miBpt);
if (fileName == null || miBptFileName == null || !new File(fileName).equals(new File(miBptFileName))) {
return false;
}
if (lineNumber == null || lineNumber.intValue() != getLineNumber(miBpt)) {
return false;
}
}
return true;
}
private boolean compareBreakpointTypeAttributes(MIBreakpoint miBpt, Boolean isHardware, Boolean isTemporary) {
if ((isHardware == null && miBpt.isHardware())
|| (isHardware != null && isHardware.booleanValue() != miBpt.isHardware())) {
return false;
}
if ((isTemporary == null && miBpt.isTemporary())
|| (isTemporary != null && isTemporary.booleanValue() != miBpt.isTemporary())) {
return false;
}
return true;
}
public void removeCreatedTargetBreakpoint(IBreakpointsTargetDMContext context, MIBreakpoint miBpt) {
Map<String, MIBreakpoint> map = fCreatedTargetBreakpoints.get(context);
if (map != null) {
map.remove(miBpt.getNumber());
}
}
private boolean isPlatformLineBreakpoint(ICLineBreakpoint plBpt, MIBreakpoint miBpt, String fileName) {
if (plBpt instanceof ICAddressBreakpoint) {
return isAddressBreakpoint(miBpt) ?
isPlatformAddressBreakpoint((ICAddressBreakpoint)plBpt, miBpt) : false;
}
if (plBpt instanceof ICFunctionBreakpoint) {
return isFunctionBreakpoint(miBpt) ?
isPlatformFunctionBreakpoint((ICFunctionBreakpoint)plBpt, miBpt) : false;
}
try {
if (fileName == null || plBpt.getSourceHandle() == null
|| !new File(fileName).equals(new File(plBpt.getSourceHandle()))) {
return false;
}
if (plBpt.getLineNumber() != getLineNumber(miBpt)) {
return false;
}
return true;
}
catch(CoreException e) {
GdbPlugin.log(e.getStatus());
}
return false;
}
private boolean isPlatformFunctionBreakpoint(ICFunctionBreakpoint plBpt, MIBreakpoint miBpt) {
try {
return (plBpt.getFunction() != null && plBpt.getFunction().equals(getFunctionName(miBpt)));
}
catch(CoreException e) {
GdbPlugin.log(e.getStatus());
}
return false;
}
private boolean isPlatformAddressBreakpoint(ICAddressBreakpoint plBpt, MIBreakpoint miBpt) {
try {
return (plBpt.getAddress() != null
&& plBpt.getAddress().equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString()));
}
catch(CoreException e) {
GdbPlugin.log(e.getStatus());
}
return false;
}
private boolean isPlatformWatchpoint(ICWatchpoint plBpt, MIBreakpoint miBpt) {
try {
if (plBpt.getExpression() != null && plBpt.getExpression().equals(miBpt.getExpression()) ) {
if (miBpt.isAccessWatchpoint()) {
return plBpt.isWriteType() && plBpt.isReadType();
}
else if (miBpt.isReadWatchpoint()) {
return !plBpt.isWriteType() && plBpt.isReadType();
}
else if (miBpt.isWriteWatchpoint()) {
return plBpt.isWriteType() && !plBpt.isReadType();
}
}
}
catch(CoreException e) {
GdbPlugin.log(e.getStatus());
}
return false;
}
private boolean isPlatformTracepoint(ICTracepoint plBpt, MIBreakpoint miBpt, String fileName) {
return isPlatformLineBreakpoint(plBpt, miBpt, fileName);
}
private boolean isPlatformDynamicPrintf(ICDynamicPrintf plBpt, MIBreakpoint miBpt, String fileName) {
return isPlatformLineBreakpoint(plBpt, miBpt, fileName);
}
/** @since 5.0 */
public boolean isTargetBreakpointDeleted(IBreakpointsTargetDMContext context, String bpId, boolean remove) {
Set<String> set = fDeletedTargetBreakpoints.get(context);
if (set != null) {
return (remove) ? set.remove(bpId) : set.contains(bpId);
}
return false;
}
/**
* Returns the list of tracepoint actions generated from the given command string.
* If the corresponding action for a command doesn't exist in TracepointActionManager
* the new action is created and added.
*
* @param commands list of gdb tracepoint commands separated by TracepointActionManager.TRACEPOINT_ACTION_DELIMITER
*/
private ITracepointAction[] getActionsFromCommands(String[] commands) {
List<ITracepointAction> list = new ArrayList<ITracepointAction>();
TracepointActionManager tam = TracepointActionManager.getInstance();
WhileSteppingAction whileStepping = null;
List<ITracepointAction> subActions = null;
for (String command : commands) {
// Check if an action for this command exists
boolean found = false;
for (ITracepointAction action :tam.getActions()) {
if (command.equals(action.getSummary())) {
if (whileStepping == null || subActions == null) {
list.add(action);
} else {
subActions.add(action);
}
found = true;
break;
}
}
if (!found) {
// Create a new action if an action for this command doesn't exists
ITracepointAction action = null;
if (command.startsWith(TC_COLLECT)) {
action = createCollectAction(command.substring(TC_COLLECT.length()));
} else if (command.startsWith(TC_TEVAL)) {
action = createEvaluateAction(command.substring(TC_TEVAL.length()));
} else if (command.startsWith(TC_WHILE_STEPPING)) {
whileStepping = createWhileSteppingAction(command.substring(TC_WHILE_STEPPING.length()));
if (whileStepping != null) {
subActions = new ArrayList<ITracepointAction>();
}
}
else if (command.equals(TC_END)) {
if (whileStepping == null || subActions == null) {
continue;
}
StringBuilder sb = new StringBuilder();
boolean first = true;
for (ITracepointAction a : subActions) {
if (first) {
first = false;
} else {
sb.append(',');
}
sb.append(a.getName());
}
whileStepping.setSubActionsNames(sb.toString());
whileStepping.setSubActionsContent(sb.toString());
action = whileStepping;
// Search for existing action for this 'while-stepping' command
for (ITracepointAction a :tam.getActions()) {
if (whileStepping.getSummary().equals(a.getSummary())) {
action = a;
found = true;
break;
}
}
whileStepping = null;
subActions.clear();
subActions = null;
}
if (action != null) {
if (!found) {
TracepointActionManager.getInstance().addAction(action);
}
if (whileStepping == null || subActions == null) {
list.add(action);
}
else {
subActions.add(action);
}
}
}
TracepointActionManager.getInstance().saveActionData();
}
return list.toArray(new ITracepointAction[list.size()]);
}
private CollectAction createCollectAction(String collectStr) {
CollectAction action = new CollectAction();
action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
action.setCollectString(collectStr);
return action;
}
private EvaluateAction createEvaluateAction(String evalStr) {
EvaluateAction action = new EvaluateAction();
action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
action.setEvalString(evalStr);
return action;
}
private WhileSteppingAction createWhileSteppingAction(String str) {
WhileSteppingAction action = new WhileSteppingAction();
action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
try {
action.setStepCount(Integer.parseInt(str.trim()));
}
catch(NumberFormatException e) {
return null;
}
return action;
}
protected void getSource(
IBreakpointsTargetDMContext bpTargetDMC,
final String debuggerPath,
final DataRequestMonitor<String> rm) {
ISourceLookup sourceLookup = getServicesTracker().getService(ISourceLookup.class);
if (sourceLookup == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Source lookup service is not available")); //$NON-NLS-1$
rm.done();
return;
}
ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(bpTargetDMC, ISourceLookupDMContext.class);
if (srcDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "No source lookup context")); //$NON-NLS-1$
rm.done();
return;
}
if (debuggerPath == null || debuggerPath.isEmpty()) {
rm.done();
return;
}
sourceLookup.getSource(
srcDmc,
debuggerPath,
new DataRequestMonitor<Object>(getExecutor(), rm) {
@Override
@ConfinedToDsfExecutor("fExecutor")
protected void handleCompleted() {
String fileName = null;
if (isSuccess()) {
if (getData() instanceof IFile) {
fileName = ((IFile)getData()).getLocation().toOSString();
}
else if (getData() instanceof File) {
fileName = ((File)getData()).getAbsolutePath();
}
else if (getData() instanceof ITranslationUnit) {
IPath location = ((ITranslationUnit)getData()).getLocation();
if (location != null) {
fileName = location.toOSString();
}
}
else if (getData() instanceof LocalFileStorage) {
fileName = ((LocalFileStorage)getData()).getFile().getAbsolutePath();
}
}
rm.setData((fileName != null && !fileName.isEmpty()) ? fileName : debuggerPath);
rm.done();
}
});
}
private boolean isFunctionBreakpoint(MIBreakpoint miBpt) {
String origFunction = getFunctionFromOriginalLocation(miBpt.getOriginalLocation());
if (miBpt.getFunction().isEmpty()) {
return !origFunction.isEmpty();
}
String function = miBpt.getFunction();
// For C++ the function name for "break x" is reported as "x()".
// To compare it to the name retrieved from the original location
// we need to remove "()".
int index = function.indexOf('(');
if (index > 0 && origFunction.indexOf('(') == -1) {
return function.substring(0, index).equals(origFunction);
}
return function.equals(origFunction);
}
private boolean isAddressBreakpoint(MIBreakpoint miBpt) {
return miBpt.getOriginalLocation().startsWith("*"); //$NON-NLS-1$
}
private boolean isLineBreakpoint(MIBreakpoint miBpt) {
return !isFunctionBreakpoint(miBpt) && !isAddressBreakpoint(miBpt);
}
private IAddress getPlatformAddress(String miAddress) {
int radix = 10;
if (miAddress.startsWith("0x")) { //$NON-NLS-1$
radix = 16;
miAddress = miAddress.substring(2);
}
return new Addr64(new BigInteger(miAddress, radix));
}
private boolean isBreakpointTargetTracked(IBreakpointsTargetDMContext btTargetDMC) {
return fTrackedTargets.contains(btTargetDMC);
}
private String getFileName(MIBreakpoint miBpt) {
String fileName = (miBpt.getFullName() != null && !miBpt.getFullName().isEmpty()) ?
miBpt.getFullName() : miBpt.getFile();
if (fileName != null && !fileName.isEmpty()) {
return fileName;
}
// When a breakpoint is set from the console on an invalid file both
// 'file' and 'fullname' attributes are not available, we need to parse
// the 'original-location' attribute to retrieve the file name.
String origLocation = miBpt.getOriginalLocation();
if (origLocation.isEmpty()) {
// Shouldn't happen
GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid 'original-location' attribute")); //$NON-NLS-1$
return ""; //$NON-NLS-1$
}
if (origLocation.startsWith("*")) { //$NON-NLS-1$
// Address breakpoint
return ""; //$NON-NLS-1$
}
int index = origLocation.lastIndexOf(':');
return (index > 0) ? origLocation.substring(0, index) : ""; //$NON-NLS-1$
}
private int getLineNumber(MIBreakpoint miBpt) {
int lineNumber = miBpt.getLine();
if (lineNumber != -1) {
return lineNumber;
}
// When a breakpoint is set from the console on an invalid file
// the 'line' attributes is not available, we need to parse
// the 'original-location' attribute to retrieve the line number.
String origLocation = miBpt.getOriginalLocation();
if (origLocation.isEmpty()) {
// Shouldn't happen
GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid 'original-location' attribute")); //$NON-NLS-1$
return -1;
}
if (origLocation.startsWith("*")) { //$NON-NLS-1$
// Address breakpoint
return -1;
}
int index = origLocation.lastIndexOf(':');
if (index > 0 && origLocation.length() > index + 1) {
try {
return Integer.valueOf(origLocation.substring(index + 1, origLocation.length())).intValue();
}
catch(NumberFormatException e) {
// not a line breakpoint
}
}
return -1;
}
private String getFunctionName(MIBreakpoint miBpt) {
if (miBpt.getFunction() != null && !miBpt.getFunction().isEmpty())
return miBpt.getFunction();
// When a function breakpoint is set from the console, the symbol associated with
// the function may not be known to GDB. In this case the 'function' attribute is
// not available, we need to parse the 'original-location' attribute to retrieve
// the function name.
return getFunctionFromOriginalLocation(miBpt.getOriginalLocation());
}
private IResource getResource(String fileName) {
IResource resource = null;
if (fileName == null || fileName.isEmpty()) {
resource = ResourcesPlugin.getWorkspace().getRoot();
} else {
IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(
new File(fileName).toURI());
if (files.length > 0) {
resource = files[0];
}
else {
resource = ResourcesPlugin.getWorkspace().getRoot();
}
}
return resource;
}
@DsfServiceEventHandler
public void eventDispatched(IExitedDMEvent e) {
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<String, MIBreakpoint> createdBreakpoints = fCreatedTargetBreakpoints.remove(bpTargetDMContext);
if (createdBreakpoints != null) {
createdBreakpoints.clear();
}
Map<String, MIBreakpoint> modifications = fPendingModifications.remove(bpTargetDMContext);
if (modifications != null) {
modifications.clear();
}
Set<String> deletedBreakpoints = fDeletedTargetBreakpoints.remove(bpTargetDMContext);
if (deletedBreakpoints != null) {
deletedBreakpoints.clear();
}
}
}
private String getFunctionFromOriginalLocation(String origLocation) {
if (origLocation.isEmpty()) {
// Shouldn't happen
GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid 'original-location' attribute")); //$NON-NLS-1$
return ""; //$NON-NLS-1$
}
if (origLocation.startsWith("*")) { //$NON-NLS-1$
// Address breakpoint
return ""; //$NON-NLS-1$
}
int index = origLocation.lastIndexOf(':');
String function = (index >= 0) ? origLocation.substring(index + 1) : origLocation;
try {
//TODO This does not work for dprintf since the output of the orginal location can look like this:
//original-location="/home/lmckhou/runtime-TestDSF/Producer/src/Producer.cpp:100,\\"Hit line %d of /home/lmckhou/runtime-TestDSF/Producer/src/Producer.cpp\\\\n\\",100"
Integer.valueOf(function);
// Line breakpoint
return ""; //$NON-NLS-1$
}
catch(NumberFormatException e) {
// possible function breakpoint
}
return function;
}
protected boolean isCatchpoint(MIBreakpoint miBpt) {
// Since we are using the CLI 'catch' command to set catchpoints GDB will emit
// the 'breakpoint-created' notification even if the catchpoint is set from UI.
// In case of 'catch' and 'throw' events the value of the 'type' attribute in
// the breakpoint notification's data is 'breakpoint' instead of 'catchpoint'.
// In this cases to identify the correct type we need to check the content of
// the 'what' attribute.
return (miBpt.isCatchpoint() ||
(!miBpt.isWatchpoint() &&
(CE_EXCEPTION_CATCH.equals(miBpt.getExpression()) ||
CE_EXCEPTION_THROW.equals(miBpt.getExpression()))));
}
}