blob: 02761b5b580fa31f564554430a7cb0182b94b189 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 - 2016 Ericsson and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Marc Khouzam (Ericsson) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
import java.util.Hashtable;
import java.util.Map;
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.concurrent.Sequence.Step;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsSynchronizer;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
/**
* Breakpoints service for GDB 7.7.
* This version supports dynamic printf
*
* @since 4.4
*/
public class GDBBreakpoints_7_7 extends GDBBreakpoints_7_6 {
private IMICommandControl fConnection;
private IMIRunControl fRunControl;
private CommandFactory fCommandFactory;
public GDBBreakpoints_7_7(DsfSession session) {
super(session);
}
@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);
fRunControl = getServicesTracker().getService(IMIRunControl.class);
if (fConnection == null || fRunControl == null) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Service is not available")); //$NON-NLS-1$
return;
}
fCommandFactory = fConnection.getCommandFactory();
// Register this service
register(
new String[] { IBreakpoints.class.getName(), IBreakpointsExtension.class.getName(),
MIBreakpoints.class.getName(), GDBBreakpoints_7_0.class.getName(),
GDBBreakpoints_7_2.class.getName(), GDBBreakpoints_7_4.class.getName(),
GDBBreakpoints_7_6.class.getName(), GDBBreakpoints_7_7.class.getName() },
new Hashtable<String, String>());
rm.done();
}
@Override
public void shutdown(RequestMonitor requestMonitor) {
unregister();
super.shutdown(requestMonitor);
}
@Override
protected void addDynamicPrintf(final IBreakpointsTargetDMContext context, final Map<String, Object> attributes,
final DataRequestMonitor<IBreakpointDMContext> drm) {
final MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
if (bs != null) {
// Skip the dprintf set from the console or from outside of Eclipse
// because they are already installed on the target.
bs.getTargetBreakpoint(context, attributes, new DataRequestMonitor<MIBreakpoint>(getExecutor(), drm) {
@Override
@ConfinedToDsfExecutor("fExecutor")
protected void handleSuccess() {
MIBreakpoint miBpt = getData();
if (miBpt != null) {
bs.removeCreatedTargetBreakpoint(context, miBpt);
MIBreakpointDMData newBreakpoint = createMIBreakpointDMData(miBpt);
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
IBreakpointDMContext dmc = new MIBreakpointDMContext(GDBBreakpoints_7_7.this,
new IDMContext[] { context }, newBreakpoint.getNumber());
drm.setData(dmc);
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
drm.done();
} else {
doAddDynamicPrintf(context, attributes, drm);
}
}
});
} else {
doAddDynamicPrintf(context, attributes, drm);
}
}
/**
* Add a Dynamic Printf.
*/
protected void doAddDynamicPrintf(final IBreakpointsTargetDMContext context, Map<String, Object> attributes,
final DataRequestMonitor<IBreakpointDMContext> finalRm) {
// Select the context breakpoints map
final Map<String, MIBreakpointDMData> contextBreakpoints = getBreakpointMap(context);
if (contextBreakpoints == null) {
finalRm.done(
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
return;
}
// Extract the relevant parameters (providing default values to avoid potential NPEs)
final String location = formatLocation(attributes);
if (location.equals(NULL_STRING)) {
finalRm.done(
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
return;
}
final String printfStr = (String) getProperty(attributes, MIBreakpoints.PRINTF_STRING, ""); //$NON-NLS-1$
final Boolean enabled = (Boolean) getProperty(attributes, MIBreakpoints.IS_ENABLED, true);
final Boolean isTemporary = (Boolean) getProperty(attributes, MIBreakpointDMData.IS_TEMPORARY, false);
final String condition = (String) getProperty(attributes, MIBreakpoints.CONDITION, NULL_STRING);
final Integer ignoreCount = (Integer) getProperty(attributes, MIBreakpoints.IGNORE_COUNT, 0);
String threadId = (String) getProperty(attributes, MIBreakpointDMData.THREAD_ID, "0"); //$NON-NLS-1$
final int tid = Integer.parseInt(threadId);
final Step insertDPrintf = new Step() {
@Override
public void execute(final RequestMonitor rm) {
// Execute the command
fConnection.queueCommand(
fCommandFactory.createMIDPrintfInsert(context, isTemporary, condition, ignoreCount, tid,
!enabled, location, printfStr),
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// With MI, an invalid location won't generate an error
if (getData().getMIBreakpoints().length == 0) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED,
DYNAMIC_PRINTF_INSERTION_FAILURE, null));
return;
}
// Create a breakpoint object and store it in the map
final MIBreakpointDMData newBreakpoint = createMIBreakpointDMData(
getData().getMIBreakpoints()[0]);
String reference = newBreakpoint.getNumber();
if (reference.isEmpty()) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED,
DYNAMIC_PRINTF_INSERTION_FAILURE, null));
return;
}
contextBreakpoints.put(reference, newBreakpoint);
// Format the return value
MIBreakpointDMContext dmc = new MIBreakpointDMContext(GDBBreakpoints_7_7.this,
new IDMContext[] { context }, reference);
finalRm.setData(dmc);
// Flag the event
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
rm.done();
}
@Override
protected void handleError() {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED,
DYNAMIC_PRINTF_INSERTION_FAILURE, getStatus().getException()));
}
});
}
};
fRunControl.executeWithTargetAvailable(context, new Step[] { insertDPrintf }, finalRm);
}
}