blob: 20072bceb2df98a0995772f3d9c11a5c38b143b5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2017 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:
* Ericsson - initial API and implementation
* Nokia - create and use backend service.
* Onur Akdemir (TUBITAK BILGEM-ITI) - Multi-process debugging (Bug 237306)
* Marc Khouzam (Ericsson) - Support for GDB 7.4 (Bug 367788)
* Marc Khouzam (Ericsson) - Include IGDBHardware service for the multicore visualizer (Bug 335027)
* Vladimir Prus (Mentor Graphics) - Support for OS resources.
* 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)
* Marc Khouzam (Ericsson) - Support dynamic printf in bp service 7.5 (Bug 400628)
* Alvaro Sanchez-Leon (Ericsson) - Allow user to edit the register groups (Bug 235747)
* Marc Dumais (Ericsson) - Update GDBHardwareAndOS service to take advantage of GDB providing CPU/core info (bug 464184)
* Intel Corporation - Added Reverse Debugging BTrace support
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.dsf.debug.service.AbstractDsfDebugServicesFactory;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
import org.eclipse.cdt.dsf.debug.service.IDisassembly;
import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory;
import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IMemory;
import org.eclipse.cdt.dsf.debug.service.IModules;
import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.service.GDBFocusSynchronizer;
import org.eclipse.cdt.dsf.gdb.internal.service.IGDBFocusSynchronizer;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
import org.eclipse.cdt.dsf.gdb.service.command.CommandFactory_6_8;
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl;
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0;
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_12;
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_2;
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_4;
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_7;
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
import org.eclipse.cdt.dsf.mi.service.IMIExpressions;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsSynchronizer;
import org.eclipse.cdt.dsf.mi.service.MIDisassembly;
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
import org.eclipse.cdt.dsf.mi.service.MIModules;
import org.eclipse.cdt.dsf.mi.service.MIStack;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.service.IDsfService;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.osgi.util.NLS;
public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
/** @since 4.0 */
public static final String GDB_6_8_VERSION = "6.8"; //$NON-NLS-1$
/** @since 4.0 */
public static final String GDB_7_0_VERSION = "7.0"; //$NON-NLS-1$
/** @since 4.0 */
public static final String GDB_7_1_VERSION = "7.1"; //$NON-NLS-1$
/** @since 4.0 */
public static final String GDB_7_2_VERSION = "7.2"; //$NON-NLS-1$
/** @since 4.1 */
public static final String GDB_7_2_1_VERSION = "7.2.1"; //$NON-NLS-1$
/** @since 4.1 */
public static final String GDB_7_3_VERSION = "7.3"; //$NON-NLS-1$
/** @since 4.1 */
public static final String GDB_7_4_VERSION = "7.4"; //$NON-NLS-1$
/** @since 4.2 */
public static final String GDB_7_5_VERSION = "7.5"; //$NON-NLS-1$
/** @since 4.2 */
public static final String GDB_7_6_VERSION = "7.5.50"; //$NON-NLS-1$
/** @since 4.4 */
public static final String GDB_7_7_VERSION = "7.7"; //$NON-NLS-1$
/** @since 4.8 */
public static final String GDB_7_10_VERSION = "7.10"; //$NON-NLS-1$
/** @since 5.4 */
public static final String GDB_7_11_VERSION = "7.11"; //$NON-NLS-1$
/** @since 5.2 */
public static final String GDB_7_12_VERSION = "7.12"; //$NON-NLS-1$
private final String fVersion;
private final ILaunchConfiguration fConfiguration;
/** @since 5.0 */
public GdbDebugServicesFactory(String version, ILaunchConfiguration config) {
fVersion = version;
fConfiguration = config;
}
/**
* @deprecated Use {@link GdbDebugServicesFactory#GdbDebugServicesFactory(String, ILaunchConfiguration)
*/
@Deprecated
public GdbDebugServicesFactory(String version) {
fVersion = version;
fConfiguration = null;
}
/**
* Returns the launch configuration. This is useful for cases where the
* service to use is dependent on the launch settings.
*
* @return configuration or <code>null</code>
* @since 5.0
*/
protected ILaunchConfiguration getConfiguration() {
return fConfiguration;
}
/**
* Returns true if the services should be created for non-stop mode.
* @return <code>true</code> if services should be created for GDB non-stop
* @since 5.0
*/
protected boolean getIsNonStopMode() {
ILaunchConfiguration configuration = getConfiguration();
if (configuration == null) {
return false;
}
return LaunchUtils.getIsNonStopMode(configuration);
}
public String getVersion() {
return fVersion;
}
@Override
@SuppressWarnings("unchecked")
public <V> V createService(Class<V> clazz, DsfSession session, Object... optionalArguments) {
if (MIBreakpointsManager.class.isAssignableFrom(clazz)) {
return (V) createBreakpointManagerService(session);
} else if (ICommandControl.class.isAssignableFrom(clazz)) {
for (Object arg : optionalArguments) {
if (arg instanceof ILaunchConfiguration) {
return (V) createCommandControl(session, (ILaunchConfiguration) arg);
}
}
} else if (IMIBackend.class.isAssignableFrom(clazz)) {
for (Object arg : optionalArguments) {
if (arg instanceof ILaunchConfiguration) {
return (V) createBackendGDBService(session, (ILaunchConfiguration) arg);
}
}
} else if (IGDBTraceControl.class.isAssignableFrom(clazz)) {
for (Object arg : optionalArguments) {
if (arg instanceof ILaunchConfiguration) {
return (V) createTraceControlService(session, (ILaunchConfiguration) arg);
}
}
} else if (IGDBHardwareAndOS.class.isAssignableFrom(clazz)) {
for (Object arg : optionalArguments) {
if (arg instanceof ILaunchConfiguration) {
return (V) createHardwareAndOSService(session, (ILaunchConfiguration) arg);
}
}
} else if (MIBreakpointsSynchronizer.class.isAssignableFrom(clazz)) {
return (V) createBreakpointsSynchronizerService(session);
} else if (IGDBFocusSynchronizer.class.isAssignableFrom(clazz)) {
return (V) createFocusSynchronizerService(session);
}
return super.createService(clazz, session, optionalArguments);
}
protected MIBreakpointsManager createBreakpointManagerService(DsfSession session) {
if (compareVersionWith(GDB_7_2_VERSION) >= 0) {
return new GDBBreakpointsManager_7_2(session, CDebugCorePlugin.PLUGIN_ID);
}
if (compareVersionWith(GDB_7_0_VERSION) >= 0) {
return new GDBBreakpointsManager_7_0(session, CDebugCorePlugin.PLUGIN_ID);
}
return new MIBreakpointsManager(session, CDebugCorePlugin.PLUGIN_ID);
}
@Override
protected IBreakpoints createBreakpointService(DsfSession session) {
if (compareVersionWith(GDB_7_7_VERSION) >= 0) {
return new GDBBreakpoints_7_7(session);
}
if (compareVersionWith(GDB_7_6_VERSION) >= 0) {
return new GDBBreakpoints_7_6(session);
}
if (compareVersionWith(GDB_7_4_VERSION) >= 0) {
return new GDBBreakpoints_7_4(session);
}
// This service is available for GDB 7.2 but there is a pre-release of GDB that
// supports the same features and has version of 6.8.50.20090414
if (compareVersionWith(GDB_7_2_VERSION) >= 0 || "6.8.50.20090414".equals(fVersion)) { //$NON-NLS-1$
return new GDBBreakpoints_7_2(session);
}
if (compareVersionWith(GDB_7_0_VERSION) >= 0) {
return new GDBBreakpoints_7_0(session);
}
return new MIBreakpoints(session);
}
protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) {
if (compareVersionWith(GDB_7_12_VERSION) >= 0) {
return new GDBControl_7_12(session, config, new CommandFactory_6_8());
}
if (compareVersionWith(GDB_7_7_VERSION) >= 0) {
return new GDBControl_7_7(session, config, new CommandFactory_6_8());
}
if (compareVersionWith(GDB_7_4_VERSION) >= 0) {
return new GDBControl_7_4(session, config, new CommandFactory_6_8());
}
if (compareVersionWith(GDB_7_2_VERSION) >= 0) {
return new GDBControl_7_2(session, config, new CommandFactory_6_8());
}
if (compareVersionWith(GDB_7_0_VERSION) >= 0) {
return new GDBControl_7_0(session, config, new CommandFactory_6_8());
}
if (compareVersionWith(GDB_6_8_VERSION) >= 0) {
return new GDBControl(session, config, new CommandFactory_6_8());
}
return new GDBControl(session, config, new CommandFactory());
}
protected IMIBackend createBackendGDBService(DsfSession session, ILaunchConfiguration lc) {
if (compareVersionWith(GDB_7_12_VERSION) >= 0) {
return new GDBBackend_7_12(session, lc);
}
return new GDBBackend(session, lc);
}
@Override
protected IDisassembly createDisassemblyService(DsfSession session) {
if (compareVersionWith(GDB_7_3_VERSION) >= 0) {
return new GDBDisassembly_7_3(session);
}
return new MIDisassembly(session);
}
@Override
protected IExpressions createExpressionService(DsfSession session) {
// Replace the standard Expressions service with a version that supports pattern matching.
// Pass in the original service which will be used as a delegate.
// This way of doing things allows to keep the pattern matching aspect isolated
// and easy to remove.
IMIExpressions originialExpressionService = new MIExpressions(session);
return new GDBPatternMatchingExpressions(session, originialExpressionService);
}
@Override
protected IMemory createMemoryService(DsfSession session) {
if (compareVersionWith(GDB_7_6_VERSION) >= 0) {
return new GDBMemory_7_6(session);
}
if (compareVersionWith(GDB_7_0_VERSION) >= 0) {
return new GDBMemory_7_0(session);
}
return new GDBMemory(session);
}
@Override
protected IModules createModulesService(DsfSession session) {
return new MIModules(session);
}
@Override
protected IProcesses createProcessesService(DsfSession session) {
if (compareVersionWith(GDB_7_12_VERSION) >= 0) {
return new GDBProcesses_7_12(session);
}
if (compareVersionWith(GDB_7_11_VERSION) >= 0) {
return new GDBProcesses_7_11(session);
}
if (compareVersionWith(GDB_7_10_VERSION) >= 0) {
return new GDBProcesses_7_10(session);
}
if (compareVersionWith(GDB_7_4_VERSION) >= 0) {
return new GDBProcesses_7_4(session);
}
if (compareVersionWith(GDB_7_3_VERSION) >= 0) {
return new GDBProcesses_7_3(session);
}
if (compareVersionWith(GDB_7_2_1_VERSION) >= 0) {
return new GDBProcesses_7_2_1(session);
}
if (compareVersionWith(GDB_7_2_VERSION) >= 0) {
return new GDBProcesses_7_2(session);
}
if (compareVersionWith(GDB_7_1_VERSION) >= 0) {
return new GDBProcesses_7_1(session);
}
if (compareVersionWith(GDB_7_0_VERSION) >= 0) {
return new GDBProcesses_7_0(session);
}
return new GDBProcesses(session);
}
@Override
protected IRegisters createRegistersService(DsfSession session) {
return new GDBRegisters(session);
}
@Override
protected IRunControl createRunControlService(DsfSession session) {
// First check for the non-stop case
if (getIsNonStopMode()) {
if (compareVersionWith(GDB_7_2_VERSION) >= 0) {
return new GDBRunControl_7_2_NS(session);
}
return new GDBRunControl_7_0_NS(session);
}
// Else, handle all-stop mode
if (compareVersionWith(GDB_7_12_VERSION) >= 0) {
return new GDBRunControl_7_12(session);
}
if (compareVersionWith(GDB_7_10_VERSION) >= 0) {
return new GDBRunControl_7_10(session);
}
if (compareVersionWith(GDB_7_6_VERSION) >= 0) {
return new GDBRunControl_7_6(session);
}
if (compareVersionWith(GDB_7_0_VERSION) >= 0) {
return new GDBRunControl_7_0(session);
}
return new GDBRunControl(session);
}
@Override
protected ISourceLookup createSourceLookupService(DsfSession session) {
return new GDBSourceLookup(session);
}
@Override
protected IStack createStackService(DsfSession session) {
return new MIStack(session);
}
/** @since 3.0 */
protected IGDBTraceControl createTraceControlService(DsfSession session, ILaunchConfiguration config) {
if (compareVersionWith(GDB_7_4_VERSION) >= 0) {
return new GDBTraceControl_7_4(session, config);
}
// This service is available for GDB 7.2 but there is a pre-release of GDB that
// supports the same features and has version of 6.8.50.20090414
if (compareVersionWith(GDB_7_2_VERSION) >= 0 || "6.8.50.20090414".equals(fVersion)) { //$NON-NLS-1$
return new GDBTraceControl_7_2(session, config);
}
// There is currently no implementation of the TraceControl service before GDB 7.2
// It could be done with restricted functionality for GDB 7.1 and maybe even 7.0
// but the service would have to be properly coded, as some MI commands don't exists
// in those older GDB versions. Also, gdbserver only supports tracing starting with 7.2
return null;
}
/** @since 4.1 */
protected IGDBHardwareAndOS createHardwareAndOSService(DsfSession session, ILaunchConfiguration config) {
if (compareVersionWith(GDB_7_10_VERSION) >= 0) {
return new GDBHardwareAndOS_7_10(session);
}
if (compareVersionWith(GDB_7_5_VERSION) >= 0) {
return new GDBHardwareAndOS_7_5(session);
}
return new GDBHardwareAndOS(session);
}
/**
* @since 4.2
*/
protected MIBreakpointsSynchronizer createBreakpointsSynchronizerService(DsfSession session) {
return new MIBreakpointsSynchronizer(session);
}
/**
* @since 5.2
*/
protected IGDBFocusSynchronizer createFocusSynchronizerService(DsfSession session) {
return new GDBFocusSynchronizer(session);
}
/**
* Compares the GDB version of the current debug session with the one specified by
* parameter 'version'. Returns -1, 0, or 1 if the current version is less than,
* equal to, or greater than the specified version, respectively.
* @param version The version to compare with
* @return -1, 0, or 1 if the current version is less than, equal to, or greater than
* the specified version, respectively.
* @since 4.8
*/
protected int compareVersionWith(String version) {
return LaunchUtils.compareVersions(getVersion(), version);
}
/**
* A static method that will compare the version of GDB for the specified session and
* the minimum GDB version required by the caller. A warning will be logged if the
* running version is not sufficient.
*
* @param session The debug session running GDB
* @param minVersion The minimum version of GDB required
* @param service The service requesting the check.
*
* @since 4.8
*/
public static void validateGdbVersion(DsfSession session, String minVersion, IDsfService service) {
ILaunch launch = (ILaunch) session.getModelAdapter(ILaunch.class);
if (launch instanceof GdbLaunch) {
IDsfDebugServicesFactory servicesFactory = ((GdbLaunch) launch).getServiceFactory();
if (servicesFactory instanceof GdbDebugServicesFactory) {
String version = ((GdbDebugServicesFactory) servicesFactory).getVersion();
if (LaunchUtils.compareVersions(minVersion, version) > 0) {
assert false;
GdbPlugin.log(
new Status(IStatus.WARNING, GdbPlugin.PLUGIN_ID, NLS.bind(Messages.GDB_Version_Mismatch,
new Object[] { version, service.getClass().getName(), minVersion })));
}
return;
}
}
assert false;
}
}