/*******************************************************************************
* Copyright (c) 2000, 2010 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Ken Ryall (Nokia) - bugs 118894, 170027, 91771
* Wind River Systems - adapted to work with platform Modules view (bug 210558)
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core.model;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.IAddressFactory;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.CDebugUtils;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.core.ICDebugConstants;
import org.eclipse.cdt.debug.core.ICGlobalVariableManager;
import org.eclipse.cdt.debug.core.cdi.CDIException;
import org.eclipse.cdt.debug.core.cdi.ICDIAddressLocation;
import org.eclipse.cdt.debug.core.cdi.ICDIBreakpointHit;
import org.eclipse.cdt.debug.core.cdi.ICDIEndSteppingRange;
import org.eclipse.cdt.debug.core.cdi.ICDIErrorInfo;
import org.eclipse.cdt.debug.core.cdi.ICDIEventBreakpointHit;
import org.eclipse.cdt.debug.core.cdi.ICDIFunctionLocation;
import org.eclipse.cdt.debug.core.cdi.ICDILineLocation;
import org.eclipse.cdt.debug.core.cdi.ICDILocation;
import org.eclipse.cdt.debug.core.cdi.ICDISession;
import org.eclipse.cdt.debug.core.cdi.ICDISessionConfiguration;
import org.eclipse.cdt.debug.core.cdi.ICDISessionObject;
import org.eclipse.cdt.debug.core.cdi.ICDISharedLibraryEvent;
import org.eclipse.cdt.debug.core.cdi.ICDISignalReceived;
import org.eclipse.cdt.debug.core.cdi.ICDIWatchpointScope;
import org.eclipse.cdt.debug.core.cdi.ICDIWatchpointTrigger;
import org.eclipse.cdt.debug.core.cdi.event.ICDIChangedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDICreatedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIDestroyedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIDisconnectedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIEventListener;
import org.eclipse.cdt.debug.core.cdi.event.ICDIExitedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIRestartedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIResumedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDISuspendedEvent;
import org.eclipse.cdt.debug.core.cdi.model.ICDIAddressFactoryManagement;
import org.eclipse.cdt.debug.core.cdi.model.ICDIDisposable;
import org.eclipse.cdt.debug.core.cdi.model.ICDIGlobalVariableDescriptor;
import org.eclipse.cdt.debug.core.cdi.model.ICDIObject;
import org.eclipse.cdt.debug.core.cdi.model.ICDISharedLibrary;
import org.eclipse.cdt.debug.core.cdi.model.ICDISignal;
import org.eclipse.cdt.debug.core.cdi.model.ICDITarget;
import org.eclipse.cdt.debug.core.cdi.model.ICDITarget2;
import org.eclipse.cdt.debug.core.cdi.model.ICDITargetConfiguration;
import org.eclipse.cdt.debug.core.cdi.model.ICDITargetConfiguration2;
import org.eclipse.cdt.debug.core.cdi.model.ICDIThread;
import org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor;
import org.eclipse.cdt.debug.core.model.CDebugElementState;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpointType;
import org.eclipse.cdt.debug.core.model.ICDebugElement;
import org.eclipse.cdt.debug.core.model.ICDebugElementStatus;
import org.eclipse.cdt.debug.core.model.ICDebugTarget;
import org.eclipse.cdt.debug.core.model.ICGlobalVariable;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
import org.eclipse.cdt.debug.core.model.ICModule;
import org.eclipse.cdt.debug.core.model.ICSignal;
import org.eclipse.cdt.debug.core.model.IDebuggerProcessSupport;
import org.eclipse.cdt.debug.core.model.IDisassembly;
import org.eclipse.cdt.debug.core.model.IExecFileInfo;
import org.eclipse.cdt.debug.core.model.IGlobalVariableDescriptor;
import org.eclipse.cdt.debug.core.model.IModuleRetrieval;
import org.eclipse.cdt.debug.core.model.IPersistableRegisterGroup;
import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
import org.eclipse.cdt.debug.core.sourcelookup.CProjectSourceContainer;
import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator;
import org.eclipse.cdt.debug.core.sourcelookup.ISourceLookupChangeListener;
import org.eclipse.cdt.debug.internal.core.CBreakpointManager;
import org.eclipse.cdt.debug.internal.core.CGlobalVariableManager;
import org.eclipse.cdt.debug.internal.core.CMemoryBlockRetrievalExtension;
import org.eclipse.cdt.debug.internal.core.CRegisterManager;
import org.eclipse.cdt.debug.internal.core.CSettingsManager;
import org.eclipse.cdt.debug.internal.core.CSignalManager;
import org.eclipse.cdt.debug.internal.core.ICDebugInternalConstants;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupParticipant;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceManager;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IExpressionListener;
import org.eclipse.debug.core.IExpressionManager;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IRegisterGroup;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;
import org.eclipse.debug.core.sourcelookup.containers.FolderSourceContainer;
import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
import com.ibm.icu.text.MessageFormat;
/**
* Debug target for C/C++ debug model.
*/
public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEventListener, ILaunchListener, IExpressionListener, ISourceLookupChangeListener {
/**
* Threads contained in this debug target.
* When a thread starts it is added to the list.
* When a thread ends it is removed from the list.
*/
private ArrayList<CThread> fThreads;
/**
* Associated inferior process, or <code>null</code> if not available.
*/
private IProcess fDebuggeeProcess = null;
/**
* The underlying CDI target.
*/
private ICDITarget fCDITarget;
/**
* The name of this target.
*/
private String fName;
/**
* The launch this target is contained in
*/
private ILaunch fLaunch;
/**
* The debug configuration of this session
*/
private ICDITargetConfiguration fConfig;
/**
* The disassembly manager for this target.
*/
private Disassembly fDisassembly;
/**
* The new disassembly manager for this target.
*/
private DisassemblyRetrieval fDisassemblyRetrieval;
/**
* The module manager for this target.
*/
private CModuleManager fModuleManager;
/**
* The signal manager for this target.
*/
private CSignalManager fSignalManager;
/**
* The register manager for this target.
*/
private CRegisterManager fRegisterManager;
/**
* A breakpoint manager for this target.
*/
private CBreakpointManager fBreakpointManager;
/**
* The global variable manager for this target.
*/
private CGlobalVariableManager fGlobalVariableManager;
/**
* container for Default format information
*/
private CSettingsManager fFormatManager;
/**
* The executable binary file associated with this target.
*/
private IBinaryObject fBinaryFile;
/**
* The project associated with this target.
*/
private IProject fProject;
/**
* Whether the target is little endian.
*/
private Boolean fIsLittleEndian = null;
/**
* The target's preference set.
*/
private Preferences fPreferences = null;
/**
* The address factory of this target.
*/
private IAddressFactory fAddressFactory;
/**
* Support for the memory retrieval on this target.
*/
private CMemoryBlockRetrievalExtension fMemoryBlockRetrieval;
/**
* Internal ID that uniquely identifies this CDebugTarget.
*/
private String internalD = Integer.toString(lastInternalID++);
private static int lastInternalID = 1;
/**
* Constructor for CDebugTarget.
*/
public CDebugTarget(ILaunch launch, IProject project, ICDITarget cdiTarget, String name, IProcess debuggeeProcess, IBinaryObject file, boolean allowsTerminate, boolean allowsDisconnect) {
super(null);
setLaunch(launch);
setDebugTarget(this);
setName(name);
setProcess(debuggeeProcess);
setProject(project);
setExecFile(file);
setCDITarget(cdiTarget);
setState(CDebugElementState.SUSPENDED);
initializePreferences();
setConfiguration(cdiTarget.getConfiguration());
setThreadList(new ArrayList<CThread>(5));
createDisassembly();
setModuleManager(new CModuleManager(this));
setSignalManager(new CSignalManager(this));
setRegisterManager(new CRegisterManager(this));
setBreakpointManager(new CBreakpointManager(this));
setGlobalVariableManager(new CGlobalVariableManager(this));
setFormatManager(new CSettingsManager(this));
setMemoryBlockRetrieval(new CMemoryBlockRetrievalExtension(this));
initialize();
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
DebugPlugin.getDefault().getExpressionManager().addExpressionListener(this);
getCDISession().getEventManager().addEventListener(this);
}
protected void initialize() {
initializeSourceLookupPath();
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(1);
debugEvents.add(createCreateEvent());
initializeThreads(debugEvents);
initializeBreakpoints();
initializeRegisters();
initializeSourceManager();
initializeModuleManager();
initializeMemoryBlocks();
getLaunch().addDebugTarget(this);
fireEventSet(debugEvents.toArray(new DebugEvent[debugEvents.size()]));
}
private void initializeBreakpoints() {
getBreakpointManager().initialize();
}
public void start(String stopSymbol, boolean resume) throws DebugException {
ICDITargetConfiguration config = getConfiguration();
if (config.supportsBreakpoints()) {
getBreakpointManager().setInitialBreakpoints();
if (stopSymbol != null && stopSymbol.length() != 0) {
// See if the expression is a numeric address
try {
IAddress address = getAddressFactory().createAddress(stopSymbol);
stopAtAddress(address);
} catch (NumberFormatException nfexc) {
// OK, expression is not a simple, absolute numeric value; keep trucking and try to resolve as expression
stopAtSymbol(stopSymbol);
}
}
}
if (config.supportsResume() && resume) {
resume();
}
}
/**
* Adds all of the pre-existing threads to this debug target.
*/
protected void initializeThreads(List<DebugEvent> debugEvents) {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget == null) {
return;
}
ICDIThread[] cdiThreads = new ICDIThread[0];
try {
cdiThreads = cdiTarget.getThreads();
} catch (CDIException e) {
// ignore
}
DebugEvent suspendEvent = null;
for (int i = 0; i < cdiThreads.length; ++i) {
CThread thread = createThread(cdiThreads[i]);
debugEvents.add(thread.createCreateEvent());
try {
if (cdiThreads[i].equals(cdiTarget.getCurrentThread()) && thread.isSuspended()) {
// Use BREAKPOINT as a detail to force perspective switch
suspendEvent = thread.createSuspendEvent(DebugEvent.BREAKPOINT);
}
} catch (CDIException e) {
// ignore
}
}
if (suspendEvent != null) {
debugEvents.add(suspendEvent);
}
}
protected void initializeRegisters() {
getRegisterManager().initialize();
}
protected void initializeSourceManager() {
ISourceLocator locator = getLaunch().getSourceLocator();
if (locator instanceof IAdaptable) {
ICSourceLocator clocator = (ICSourceLocator)((IAdaptable)locator).getAdapter(ICSourceLocator.class);
if (clocator instanceof IAdaptable) {
CSourceManager sm = (CSourceManager)((IAdaptable)clocator).getAdapter(CSourceManager.class);
if (sm != null)
sm.setDebugTarget(this);
}
IResourceChangeListener listener = (IResourceChangeListener)((IAdaptable)locator).getAdapter(IResourceChangeListener.class);
if (listener != null)
CCorePlugin.getWorkspace().addResourceChangeListener(listener);
}
}
protected void initializeSourceLookupPath() {
ISourceLocator locator = getLaunch().getSourceLocator();
if (locator instanceof ISourceLookupDirector) {
ISourceLookupParticipant[] participants = ((ISourceLookupDirector)locator).getParticipants();
for (int i = 0; i < participants.length; ++i) {
if (participants[i] instanceof CSourceLookupParticipant) {
((CSourceLookupParticipant)participants[i]).addSourceLookupChangeListener(this);
}
}
setSourceLookupPath(((ISourceLookupDirector)locator).getSourceContainers());
}
}
protected void initializeModuleManager() {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget == null) {
return;
}
ICDISharedLibrary[] slibs = new ICDISharedLibrary[0];
try {
slibs = cdiTarget.getSharedLibraries();
} catch (CDIException e) {
DebugPlugin.log(e);
}
ICModule[] modules = null;
if (getExecFile() != null) {
modules = new ICModule[slibs.length + 1];
modules[0] = CModule.createExecutable(this, getExecFile().getPath());
} else {
modules = new ICModule[slibs.length];
}
for (int i = 0; i < slibs.length; ++i) {
modules[i + 1] = CModule.createSharedLibrary(this, slibs[i]);
}
getModuleManager().addModules(modules);
}
protected void initializeMemoryBlocks() {
getMemoryBlockRetrieval().initialize();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
*/
public IProcess getProcess() {
return fDebuggeeProcess;
}
/**
* Sets the process associated with this debug target, possibly <code>null</code>. Set on creation.
*
* @param process the system process associated with the underlying CDI target,
* or <code>null</code> if no process is associated with this debug target
* (for a core dump debugging).
*/
protected void setProcess(IProcess debuggeeProcess) {
fDebuggeeProcess = debuggeeProcess;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
*/
public IThread[] getThreads() {
List<CThread> threads = getThreadList();
return threads.toArray(new IThread[threads.size()]);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IDebugTarget#hasThreads()
*/
public boolean hasThreads() throws DebugException {
return getThreadList().size() > 0;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IDebugTarget#getName()
*/
public String getName() throws DebugException {
return fName;
}
/**
* Sets the name of this debug target.
*
* @param name the name of this debug target
*/
public void setName(String name) {
fName = name;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
*/
public boolean supportsBreakpoint(IBreakpoint breakpoint) {
if (!getConfiguration().supportsBreakpoints())
return false;
return (breakpoint instanceof ICBreakpoint && getBreakpointManager().supportsBreakpoint((ICBreakpoint)breakpoint));
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.ILaunchListener#launchRemoved(org.eclipse.debug.core.ILaunch)
*/
public void launchRemoved(ILaunch launch) {
if (!isAvailable()) {
return;
}
if (launch.equals(getLaunch())) {
// This target has been deregistered, but it hasn't been successfully terminated.
// Update internal state to reflect that it is disconnected
disconnected();
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.ILaunchListener#launchAdded(org.eclipse.debug.core.ILaunch)
*/
public void launchAdded(ILaunch launch) {
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.ILaunchListener#launchChanged(org.eclipse.debug.core.ILaunch)
*/
public void launchChanged(ILaunch launch) {
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#canTerminate()
*/
public boolean canTerminate() {
return supportsTerminate() && isAvailable();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#isTerminated()
*/
public boolean isTerminated() {
return (getState().equals(CDebugElementState.TERMINATED));
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#terminate()
*/
public void terminate() throws DebugException {
if (!canTerminate()) {
return;
}
final CDebugElementState newState = CDebugElementState.TERMINATING;
changeState(newState);
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
cdiTarget.terminate();
}
} catch (CDIException e) {
if (getState() == newState) {
restoreOldState();
}
targetRequestFailed(e.getMessage(), null);
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canResume()
*/
public boolean canResume() {
return getConfiguration().supportsResume() && isSuspended();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
*/
public boolean canSuspend() {
if (!getConfiguration().supportsSuspend())
return false;
if (getState().equals(CDebugElementState.RESUMED)) {
// only allow suspend if no threads are currently suspended
IThread[] threads = getThreads();
for (int i = 0; i < threads.length; i++) {
if (threads[i].isSuspended()) {
return false;
}
}
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
*/
public boolean isSuspended() {
return (getState().equals(CDebugElementState.SUSPENDED));
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#resume()
*/
public void resume() throws DebugException {
if (!canResume())
return;
final CDebugElementState newState = CDebugElementState.RESUMING;
changeState(newState);
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
cdiTarget.resume(false);
}
} catch (CDIException e) {
if (getState() == newState) {
restoreOldState();
}
targetRequestFailed(e.getMessage(), null);
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#suspend()
*/
public void suspend() throws DebugException {
if (!canSuspend())
return;
final CDebugElementState newState = CDebugElementState.SUSPENDING;
changeState(newState);
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
cdiTarget.suspend();
}
} catch (CDIException e) {
if (getState() == newState) {
restoreOldState();
}
targetRequestFailed(e.getMessage(), null);
}
}
protected boolean isSuspending() {
return (getState().equals(CDebugElementState.SUSPENDING));
}
/**
* Notifies threads that the target has been suspended.
*/
protected void suspendThreads(ICDISuspendedEvent event) {
Iterator<CThread> it = getThreadList().iterator();
while (it.hasNext()) {
CThread thread = it.next();
ICDIThread suspensionThread = null;
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
suspensionThread = cdiTarget.getCurrentThread();
}
} catch (CDIException e) {
// ignore
}
thread.suspendByTarget(event.getReason(), suspensionThread);
}
}
/**
* Refreshes the thread list.
*/
protected synchronized List<CThread> refreshThreads() {
ArrayList<CThread> newThreads = new ArrayList<CThread>(5);
ArrayList<CThread> list = new ArrayList<CThread>(5);
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(5);
List<CThread> oldList = (List<CThread>)getThreadList().clone();
ICDIThread[] cdiThreads = new ICDIThread[0];
ICDIThread currentCDIThread = null;
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
cdiThreads = cdiTarget.getThreads();
currentCDIThread = cdiTarget.getCurrentThread();
}
} catch (CDIException e) {
}
for (int i = 0; i < cdiThreads.length; ++i) {
CThread thread = findThread(oldList, cdiThreads[i]);
if (thread == null) {
thread = new CThread(this, cdiThreads[i]);
newThreads.add(thread);
}
else {
oldList.remove(thread);
}
thread.setCurrent(cdiThreads[i].equals(currentCDIThread));
list.add(thread);
}
Iterator<CThread> it = oldList.iterator();
while (it.hasNext()) {
CThread thread = it.next();
thread.terminated();
debugEvents.add(thread.createTerminateEvent());
}
setThreadList(list);
it = newThreads.iterator();
while (it.hasNext()) {
debugEvents.add(it.next().createCreateEvent());
}
if (debugEvents.size() > 0)
fireEventSet(debugEvents.toArray(new DebugEvent[debugEvents.size()]));
return newThreads;
}
/**
* Notifies threads that the target has been resumed.
*/
protected synchronized void resumeThreads(List<DebugEvent> debugEvents, int detail) {
Iterator<CThread> it = getThreadList().iterator();
while (it.hasNext()) {
it.next().resumedByTarget(detail, debugEvents);
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
*/
public void breakpointAdded(IBreakpoint breakpoint) {
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
*/
public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
*/
public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
}
/**
* Returns whether this debug target supports disconnecting.
*
* @return whether this debug target supports disconnecting
*/
protected boolean supportsDisconnect() {
return getConfiguration().supportsDisconnect();
}
/**
* Returns whether this debug target supports termination.
*
* @return whether this debug target supports termination
*/
protected boolean supportsTerminate() {
return getConfiguration().supportsTerminate();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
*/
public boolean canDisconnect() {
return supportsDisconnect() && isAvailable();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDisconnect#disconnect()
*/
public void disconnect() throws DebugException {
if (isDisconnecting()) {
return;
}
final CDebugElementState newState = CDebugElementState.DISCONNECTING;
changeState(newState);
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
cdiTarget.disconnect();
}
} catch (CDIException e) {
if (getState() == newState) {
restoreOldState();
}
targetRequestFailed(e.getMessage(), null);
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
*/
public boolean isDisconnected() {
return (getState().equals(CDebugElementState.DISCONNECTED));
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
*/
public boolean supportsStorageRetrieval() {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
*/
public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
*/
@Override
public ILaunch getLaunch() {
return fLaunch;
}
/**
* Sets the launch this target is contained in
*
* @param launch the launch this target is contained in
*/
private void setLaunch(ILaunch launch) {
fLaunch = launch;
}
/**
* Returns the list of threads contained in this debug target.
*
* @return list of threads
*/
protected ArrayList<CThread> getThreadList() {
return fThreads;
}
/**
* Sets the list of threads contained in this debug target. Set to an empty collection on creation. Threads are added and removed as they start and end. On
* termination this collection is set to the immutable singleton empty list.
*
* @param threads empty list
*/
private void setThreadList(ArrayList<CThread> threads) {
fThreads = threads;
}
private void setCDITarget(ICDITarget cdiTarget) {
fCDITarget = cdiTarget;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
if (adapter.equals(ICDebugElement.class))
return this;
if (adapter.equals(CDebugElement.class))
return this;
if (adapter.equals(IDebugTarget.class))
return this;
if (adapter.equals(ICDebugTarget.class))
return this;
if (adapter.equals(CDebugTarget.class))
return this;
if (adapter.equals(ICDITarget.class))
return fCDITarget;
if (adapter.equals(IDebuggerProcessSupport.class))
return this;
if (adapter.equals(IExecFileInfo.class))
return this;
if (adapter.equals(CBreakpointManager.class))
return getBreakpointManager();
if (adapter.equals(CSignalManager.class))
return getSignalManager();
if (adapter.equals(CRegisterManager.class))
return getRegisterManager();
if (adapter.equals(ICGlobalVariableManager.class))
return getGlobalVariableManager();
if (adapter.equals(ICDISession.class))
return getCDISession();
if (adapter.equals(IMemoryBlockRetrievalExtension.class))
return getMemoryBlockRetrieval();
if (adapter.equals(IMemoryBlockRetrieval.class))
return getMemoryBlockRetrieval();
if (adapter.equals(IModuleRetrieval.class))
return getModuleManager();
// Force adapters to be loaded. Otherwise the adapter manager may not find
// the model proxy adapter for CDT debug elements.
Platform.getAdapterManager().loadAdapter(this, adapter.getName());
return super.getAdapter(adapter);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.cdi.event.ICDIEventListener#handleDebugEvents(org.eclipse.cdt.debug.core.cdi.event.ICDIEvent[])
*/
public void handleDebugEvents(ICDIEvent[] events) {
for (int i = 0; i < events.length; i++) {
ICDIEvent event = events[i];
ICDIObject source = event.getSource();
final ICDITarget cdiTarget = getCDITarget();
if (source == null && event instanceof ICDIDestroyedEvent) {
handleTerminatedEvent((ICDIDestroyedEvent)event);
}
else if (source != null && cdiTarget != null && source.getTarget().equals(cdiTarget)) {
if (event instanceof ICDICreatedEvent) {
if (source instanceof ICDIThread) {
handleThreadCreatedEvent((ICDICreatedEvent)event);
}
if (source instanceof ICDISharedLibrary) {
getModuleManager().sharedLibraryLoaded((ICDISharedLibrary)source);
}
}
else if (event instanceof ICDISuspendedEvent) {
if (source instanceof ICDITarget) {
handleSuspendedEvent((ICDISuspendedEvent)event);
}
}
else if (event instanceof ICDIResumedEvent) {
if (source instanceof ICDITarget) {
handleResumedEvent((ICDIResumedEvent)event);
}
}
else if (event instanceof ICDIExitedEvent) {
if (source instanceof ICDITarget) {
handleExitedEvent((ICDIExitedEvent)event);
}
}
else if (event instanceof ICDIDestroyedEvent) {
if (source instanceof ICDIThread) {
handleThreadTerminatedEvent((ICDIDestroyedEvent)event);
}
if (source instanceof ICDISharedLibrary) {
getModuleManager().sharedLibraryUnloaded((ICDISharedLibrary)source);
}
}
else if (event instanceof ICDIDisconnectedEvent) {
if (source instanceof ICDITarget) {
handleDisconnectedEvent((ICDIDisconnectedEvent)event);
}
}
else if (event instanceof ICDIChangedEvent) {
if (source instanceof ICDITarget) {
handleChangedEvent((ICDIChangedEvent)event);
}
if (source instanceof ICDISharedLibrary) {
handleSymbolsLoaded((ICDISharedLibrary)source);
}
if (source instanceof ICDISignal) {
getSignalManager().signalChanged((ICDISignal)source);
}
}
else if (event instanceof ICDIRestartedEvent) {
if (source instanceof ICDITarget) {
handleRestartedEvent((ICDIRestartedEvent)event);
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRestart#canRestart()
*/
public boolean canRestart() {
return getConfiguration().supportsRestart() && isSuspended();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRestart#restart()
*/
public void restart() throws DebugException {
if (!canRestart()) {
return;
}
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget == null) {
return;
}
try {
ILaunchConfiguration launchConfig = getLaunch().getLaunchConfiguration();
if (launchConfig.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT)) {
String mainSymbol = launchConfig.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
ICDILocation location = null;
// See if the expression is a numeric address
try {
IAddress address = getAddressFactory().createAddress(mainSymbol);
location = cdiTarget.createAddressLocation(address.getValue());
} catch (NumberFormatException nfexc) {
// OK, expression is not a simple, absolute numeric value; keep trucking and try to resolve as expression
location = cdiTarget.createFunctionLocation("", mainSymbol); //$NON-NLS-1$
}
setInternalTemporaryBreakpoint(location);
}
} catch (CoreException e) {
requestFailed(e.getMessage(), e);
}
final CDebugElementState newState = CDebugElementState.RESTARTING;
changeState(newState);
try {
cdiTarget.restart();
} catch (CDIException e) {
if (getState() == newState) {
restoreOldState();
}
targetRequestFailed(e.getMessage(), e);
}
}
/**
* Returns whether this target is available to handle client requests.
*
* @return whether this target is available to handle client requests
*/
public boolean isAvailable() {
return !(isTerminated() || isTerminating() || isDisconnected() || isDisconnecting());
}
/**
* Returns whether this target is in the process of terminating.
*
* @return whether this target is terminating
*/
protected boolean isTerminating() {
return (getState().equals(CDebugElementState.TERMINATING));
}
/**
* Updates the state of this target to be terminated, if not already terminated.
*/
protected void terminated() {
if (!isTerminated()) {
if (!isDisconnected()) {
setState(CDebugElementState.TERMINATED);
}
cleanup();
fireTerminateEvent();
}
}
/**
* Returns whether this target is in the process of terminating.
*
* @return whether this target is terminating
*/
protected boolean isDisconnecting() {
return (getState().equals(CDebugElementState.DISCONNECTING));
}
/**
* Updates the state of this target for disconnection.
*/
protected void disconnected() {
if (!isDisconnected()) {
setState(CDebugElementState.DISCONNECTED);
cleanup();
fireTerminateEvent();
}
}
/**
* Cleans up the internal state of this debug target as a result of a session ending.
*/
protected void cleanup() {
resetStatus();
removeAllThreads();
getCDISession().getEventManager().removeEventListener(this);
DebugPlugin.getDefault().getExpressionManager().removeExpressionListener(this);
DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
saveFormats();
saveGlobalVariables();
disposeGlobalVariableManager();
disposeModuleManager();
disposeSignalManager();
saveRegisterGroups();
disposeRegisterManager();
saveMemoryBlocks();
disposeMemoryBlockRetrieval();
disposeDisassembly();
disposeSourceManager();
disposeSourceLookupPath();
disposeBreakpointManager();
removeAllExpressions();
disposePreferences();
ICDITarget cdiTarget = getCDITarget();
// TODO: apparently we're not really done with the ICDITarget. The
// arrival of a terminate event from gdb requires access to this (see
// SessionManager.handleDebugEvent()). Reported by Mikhail. Need to
// revisit this.
// setCDITarget(null);
if (cdiTarget instanceof ICDIDisposable) {
((ICDIDisposable)cdiTarget).dispose();
}
}
/**
* Removes all threads from this target's collection of threads, firing a terminate event for each.
*/
protected void removeAllThreads() {
List<CThread> threads = getThreadList();
setThreadList(new ArrayList<CThread>(0));
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(threads.size());
Iterator<CThread> it = threads.iterator();
while (it.hasNext()) {
CThread thread = it.next();
thread.terminated();
debugEvents.add(thread.createTerminateEvent());
}
fireEventSet(debugEvents.toArray(new DebugEvent[debugEvents.size()]));
}
/**
* Removes all expressions from this target.
*/
protected void removeAllExpressions() {
IExpressionManager em = DebugPlugin.getDefault().getExpressionManager();
IExpression[] expressions = em.getExpressions();
for (int i = 0; i < expressions.length; ++i) {
if (expressions[i] instanceof CExpression && expressions[i].getDebugTarget().equals(this)) {
em.removeExpression(expressions[i]);
}
}
}
/**
* Creates, adds and returns a thread for the given underlying CDI thread. A creation event is fired for the thread. Returns <code>null</code> if during
* the creation of the thread this target is set to the disconnected state.
*
* @param thread the underlying CDI thread
* @return model thread
*/
protected CThread createThread(ICDIThread cdiThread) {
CThread thread = new CThread(this, cdiThread);
getThreadList().add(thread);
return thread;
}
private void handleSuspendedEvent(ICDISuspendedEvent event) {
setState(CDebugElementState.SUSPENDED);
ICDISessionObject reason = event.getReason();
setCurrentStateInfo(reason);
// Reset the registers that have errors.
getRegisterManager().targetSuspended();
getBreakpointManager().skipBreakpoints(false);
List<CThread> newThreads = refreshThreads();
if (event.getSource() instanceof ICDITarget) {
if (!(this.getConfiguration() instanceof ICDITargetConfiguration2) || !((ICDITargetConfiguration2)this.getConfiguration()).supportsThreadControl())
suspendThreads(event);
} else if (event.getSource() instanceof ICDIThread) {
// We need this for debuggers that don't have notifications
// for newly created threads.
CThread thread = findThread((ICDIThread)event.getSource());
if (thread != null && newThreads.contains(thread)) {
ICDIEvent[] evts = new ICDIEvent[]{ event };
thread.handleDebugEvents(evts);
}
}
if (reason instanceof ICDIEndSteppingRange) {
handleEndSteppingRange((ICDIEndSteppingRange)reason);
}
else if (reason instanceof ICDIBreakpointHit) {
handleBreakpointHit((ICDIBreakpointHit)reason);
}
else if (reason instanceof ICDISignalReceived) {
handleSuspendedBySignal((ICDISignalReceived)reason);
}
else if (reason instanceof ICDIWatchpointTrigger) {
handleWatchpointTrigger((ICDIWatchpointTrigger)reason);
}
else if (reason instanceof ICDIWatchpointScope) {
handleWatchpointScope((ICDIWatchpointScope)reason);
}
else if (reason instanceof ICDIErrorInfo) {
handleErrorInfo((ICDIErrorInfo)reason);
}
else if (reason instanceof ICDISharedLibraryEvent) {
handleSuspendedBySolibEvent((ICDISharedLibraryEvent)reason);
}
else if (reason instanceof ICDIEventBreakpointHit) {
handleEventBreakpointHit((ICDIEventBreakpointHit)reason);
}
else { // reason is not specified
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
}
private void handleResumedEvent(ICDIResumedEvent event) {
setState(CDebugElementState.RESUMED);
setCurrentStateInfo(null);
resetStatus();
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(10);
int detail = DebugEvent.UNSPECIFIED;
switch(event.getType()) {
case ICDIResumedEvent.CONTINUE:
detail = DebugEvent.CLIENT_REQUEST;
break;
case ICDIResumedEvent.STEP_INTO:
case ICDIResumedEvent.STEP_INTO_INSTRUCTION:
detail = DebugEvent.STEP_INTO;
break;
case ICDIResumedEvent.STEP_OVER:
case ICDIResumedEvent.STEP_OVER_INSTRUCTION:
detail = DebugEvent.STEP_OVER;
break;
case ICDIResumedEvent.STEP_RETURN:
detail = DebugEvent.STEP_RETURN;
break;
}
debugEvents.add(createResumeEvent(detail));
if (!(this.getConfiguration() instanceof ICDITargetConfiguration2) || !((ICDITargetConfiguration2)this.getConfiguration()).supportsThreadControl())
resumeThreads(debugEvents, detail);
fireEventSet(debugEvents.toArray(new DebugEvent[debugEvents.size()]));
}
private void handleEndSteppingRange(ICDIEndSteppingRange endSteppingRange) {
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
private void handleBreakpointHit(ICDIBreakpointHit breakpointHit) {
fireSuspendEvent(DebugEvent.BREAKPOINT);
}
private void handleEventBreakpointHit(ICDIEventBreakpointHit breakpointHit) {
fireSuspendEvent(DebugEvent.BREAKPOINT);
}
private void handleWatchpointTrigger(ICDIWatchpointTrigger wt) {
fireSuspendEvent(DebugEvent.BREAKPOINT);
}
private void handleWatchpointScope(ICDIWatchpointScope ws) {
getBreakpointManager().watchpointOutOfScope(ws.getWatchpoint());
fireSuspendEvent(DebugEvent.BREAKPOINT);
}
private void handleSuspendedBySignal(ICDISignalReceived signal) {
fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
}
private void handleErrorInfo(ICDIErrorInfo info) {
setStatus(ICDebugElementStatus.ERROR, (info != null) ? info.getMessage() : null);
if (info != null) {
MultiStatus status = new MultiStatus(CDebugCorePlugin.getUniqueIdentifier(), ICDebugInternalConstants.STATUS_CODE_ERROR, CoreModelMessages.getString("CDebugTarget.1"), //$NON-NLS-1$
null);
StringTokenizer st = new StringTokenizer(info.getDetailMessage(), "\n\r"); //$NON-NLS-1$
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (token.length() > 200) {
token = token.substring(0, 200);
}
status.add(new Status(IStatus.ERROR, status.getPlugin(), ICDebugInternalConstants.STATUS_CODE_ERROR, token, null));
}
CDebugUtils.error(status, this);
}
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
private void handleSuspendedBySolibEvent(ICDISharedLibraryEvent solibEvent) {
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
private void handleExitedEvent(ICDIExitedEvent event) {
removeAllThreads();
setState(CDebugElementState.EXITED);
setCurrentStateInfo(event.getReason());
fireChangeEvent(DebugEvent.CONTENT);
ICDISessionConfiguration sessionConfig = getCDISession().getConfiguration();
if (sessionConfig != null && sessionConfig.terminateSessionOnExit())
terminated();
}
private void handleTerminatedEvent(ICDIDestroyedEvent event) {
terminated();
}
private void handleDisconnectedEvent(ICDIDisconnectedEvent event) {
disconnected();
}
private void handleChangedEvent(ICDIChangedEvent event) {
}
private void handleRestartedEvent(ICDIRestartedEvent event) {
}
private void handleThreadCreatedEvent(ICDICreatedEvent event) {
ICDIThread cdiThread = (ICDIThread)event.getSource();
CThread thread = findThread(cdiThread);
if (thread == null) {
thread = createThread(cdiThread);
thread.fireCreationEvent();
}
}
private void handleThreadTerminatedEvent(ICDIDestroyedEvent event) {
ICDIThread cdiThread = (ICDIThread)event.getSource();
List<CThread> threads = getThreadList();
List<CThread> threadsToRemove = new ArrayList<CThread>(1);
for (int i = 0; i < threads.size(); i++) {
CThread cthread = threads.get(i);
// It's possible CThread has handled the thread-terminated event
// before us (by appearing first in the EventManager)
// and has disassociated itself from the ICDIThread.
// So handle any disassociated CThreads we find. Chances are
// there's only one and it's the one we got the terminated event
// for. See bugzilla 254888.
ICDIThread cdithread = cthread.getCDIThread();
if (cdithread == null || cdithread.equals(cdiThread)) {
threadsToRemove.add(cthread);
}
}
for (CThread cthread : threadsToRemove) {
threads.remove(cthread);
cthread.terminated();
cthread.fireTerminateEvent();
}
}
/**
* Finds and returns the model thread for the associated CDI thread, or <code>null</code> if not found.
*
* @param the underlying CDI thread
* @return the associated model thread
*/
public CThread findThread(ICDIThread cdiThread) {
return findThread(getThreadList(), cdiThread);
}
public CThread findThread(List<CThread> threads, ICDIThread cdiThread) {
for (int i = 0; i < threads.size(); i++) {
CThread t = threads.get(i);
ICDIThread thisCdiThread = t.getCDIThread();
if (thisCdiThread != null && thisCdiThread.equals(cdiThread))
return t;
}
return null;
}
/**
* Returns the debug configuration of this target.
*
* @return the debug configuration of this target
*/
protected ICDITargetConfiguration getConfiguration() {
return fConfig;
}
/**
* Sets the debug configuration of this target.
*
* @param config the debug configuration to set
*/
private void setConfiguration(ICDITargetConfiguration config) {
fConfig = config;
}
protected boolean supportsExpressionEvaluation() {
return getConfiguration().supportsExpressionEvaluation();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IExpressionListener#expressionAdded(org.eclipse.debug.core.model.IExpression)
*/
public void expressionAdded(IExpression expression) {
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IExpressionListener#expressionChanged(org.eclipse.debug.core.model.IExpression)
*/
public void expressionChanged(IExpression expression) {
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IExpressionListener#expressionRemoved(org.eclipse.debug.core.model.IExpression)
*/
public void expressionRemoved(IExpression expression) {
if (expression instanceof CExpression && expression.getDebugTarget().equals(this)) {
((CExpression)expression).dispose();
}
}
public void setInternalTemporaryBreakpoint(ICDILocation location) throws DebugException {
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget == null) {
return;
}
if (location instanceof ICDIFunctionLocation) {
cdiTarget.setFunctionBreakpoint(ICBreakpointType.TEMPORARY, (ICDIFunctionLocation)location, null, false);
} else if (location instanceof ICDILineLocation) {
cdiTarget.setLineBreakpoint(ICBreakpointType.TEMPORARY, (ICDILineLocation)location, null, false);
} else if (location instanceof ICDIAddressLocation) {
cdiTarget.setAddressBreakpoint(ICBreakpointType.TEMPORARY, (ICDIAddressLocation)location, null, false);
} else {
// ???
targetRequestFailed("not_a_location", null); //$NON-NLS-1$
}
} catch (CDIException e) {
targetRequestFailed(e.getMessage(), null);
}
}
protected IThread getCurrentThread() {
IThread[] threads = getThreads();
for (int i = 0; i < threads.length; ++i) {
if (((CThread)threads[i]).isCurrent())
return threads[i];
}
return null;
}
protected ISourceLocator getSourceLocator() {
return getLaunch().getSourceLocator();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IExecFileInfo#isLittleEndian()
*/
public boolean isLittleEndian() {
if (fIsLittleEndian == null) {
fIsLittleEndian = Boolean.TRUE;
IBinaryObject file;
file = getBinaryFile();
if (file != null) {
fIsLittleEndian = Boolean.valueOf(file.isLittleEndian());
}
}
return fIsLittleEndian.booleanValue();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IExecFileInfo#getExecFile()
*/
public IBinaryObject getExecFile() {
return getBinaryFile();
}
public IBinaryObject getBinaryFile() {
return fBinaryFile;
}
private void setExecFile(IBinaryObject file) {
fBinaryFile = file;
}
private void setProject(IProject project) {
fProject = project;
}
public IProject getProject() {
return fProject;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IExecFileInfo#getGlobals()
*/
public IGlobalVariableDescriptor[] getGlobals() throws DebugException {
ICDITarget cdiTarget = getCDITarget();
// If the backend can give us the globals...
boolean hasCDIGlobals = false;
ArrayList<IGlobalVariableDescriptor> list = new ArrayList<IGlobalVariableDescriptor>();
if (cdiTarget instanceof ICDITarget2) {
ICDIGlobalVariableDescriptor[] cdiGlobals = ((ICDITarget2) cdiTarget).getGlobalVariables();
hasCDIGlobals = cdiGlobals != null;
if (hasCDIGlobals) {
for (int i = 0; i < cdiGlobals.length; i++) {
list.add(CVariableFactory.createGlobalVariableDescriptor(cdiGlobals[i].getName(), null));
}
}
}
// otherwise ask the binary
if (!hasCDIGlobals) {
IBinaryObject file = getBinaryFile();
if (file != null) {
list.addAll(getCFileGlobals(file));
}
}
return list.toArray(new IGlobalVariableDescriptor[list.size()]);
}
private List<IGlobalVariableDescriptor> getCFileGlobals(IBinaryObject file) {
ArrayList<IGlobalVariableDescriptor> list = new ArrayList<IGlobalVariableDescriptor>();
ISymbol[] symbols = file.getSymbols();
for (int i = 0; i < symbols.length; ++i) {
if (symbols[i].getType() == ISymbol.VARIABLE) {
list.add(CVariableFactory.createGlobalVariableDescriptor(symbols[i]));
}
}
return list;
}
protected void setModuleManager(CModuleManager mm) {
fModuleManager = mm;
}
protected CModuleManager getModuleManager() {
return fModuleManager;
}
protected void disposeModuleManager() {
fModuleManager.dispose();
fModuleManager = null;
}
protected void setSignalManager(CSignalManager sm) {
fSignalManager = sm;
}
protected CSignalManager getSignalManager() {
return fSignalManager;
}
protected void disposeSignalManager() {
fSignalManager.dispose();
}
protected void saveRegisterGroups() {
fRegisterManager.save();
}
protected void disposeRegisterManager() {
fRegisterManager.dispose();
}
protected void saveGlobalVariables() {
fGlobalVariableManager.save();
}
protected void saveFormats() {
fFormatManager.save();
}
protected void disposeGlobalVariableManager() {
fGlobalVariableManager.dispose();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeWithoutSignal#canResumeWithoutSignal()
*/
public boolean canResumeWithoutSignal() {
// Check if the configuration supports this!!!
return (canResume() && getCurrentStateInfo() instanceof ICDISignalReceived);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeWithoutSignal#resumeWithoutSignal()
*/
public void resumeWithoutSignal() throws DebugException {
if (!canResume())
return;
final CDebugElementState newState = CDebugElementState.RESUMING;
changeState(newState);
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
cdiTarget.resume(false);
}
} catch (CDIException e) {
if (getState() == newState) {
restoreOldState();
}
targetRequestFailed(e.getMessage(), e);
}
}
public CRegisterManager getRegisterManager() {
// Workaround for bug #309212. gdb 7.0 returns "No registers" error
// at the beginning of the session.
fRegisterManager.initialize();
return fRegisterManager;
}
protected void setRegisterManager(CRegisterManager registerManager) {
fRegisterManager = registerManager;
}
public IRegisterGroup[] getRegisterGroups(CStackFrame frame) throws DebugException {
return getRegisterManager().getRegisterGroups(frame);
}
protected void disposeSourceManager() {
ISourceLocator locator = getSourceLocator();
if (locator instanceof IAdaptable) {
IResourceChangeListener listener = (IResourceChangeListener)((IAdaptable)locator).getAdapter(IResourceChangeListener.class);
if (listener != null)
CCorePlugin.getWorkspace().removeResourceChangeListener(listener);
}
}
protected void disposeSourceLookupPath() {
ISourceLocator locator = getLaunch().getSourceLocator();
if (locator instanceof ISourceLookupDirector) {
ISourceLookupParticipant[] participants = ((ISourceLookupDirector)locator).getParticipants();
for (int i = 0; i < participants.length; ++i) {
if (participants[i] instanceof CSourceLookupParticipant) {
((CSourceLookupParticipant)participants[i]).removeSourceLookupChangeListener(this);
}
}
}
}
protected void saveMemoryBlocks() {
getMemoryBlockRetrieval().save();
}
protected void disposeMemoryBlockRetrieval() {
getMemoryBlockRetrieval().dispose();
}
protected CBreakpointManager getBreakpointManager() {
return fBreakpointManager;
}
protected void setBreakpointManager(CBreakpointManager manager) {
fBreakpointManager = manager;
}
protected void disposeBreakpointManager() {
if (getBreakpointManager() != null)
getBreakpointManager().dispose();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
String result = ""; //$NON-NLS-1$
try {
result = getName();
} catch (DebugException e) {
}
return result;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#getDisassembly()
*/
public IDisassembly getDisassembly() throws DebugException {
return fDisassembly;
}
public DisassemblyRetrieval getDisassemblyRetrieval() {
return fDisassemblyRetrieval;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#getSignals()
*/
public ICSignal[] getSignals() throws DebugException {
CSignalManager sm = getSignalManager();
if (sm != null) {
return sm.getSignals();
}
return new ICSignal[0];
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#hasSignals()
*/
public boolean hasSignals() throws DebugException {
CSignalManager sm = getSignalManager();
if (sm != null) {
return (sm.getSignals().length > 0);
}
return false;
}
private void createDisassembly() {
this.fDisassembly = new Disassembly(this);
this.fDisassemblyRetrieval = new DisassemblyRetrieval(this);
}
private void disposeDisassembly() {
if (fDisassembly != null)
fDisassembly.dispose();
fDisassembly = null;
if (fDisassemblyRetrieval != null)
fDisassemblyRetrieval.dispose();
fDisassemblyRetrieval = null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IBreakpointTarget#getBreakpointAddress(org.eclipse.cdt.debug.core.model.ICLineBreakpoint)
*/
public IAddress getBreakpointAddress(ICLineBreakpoint breakpoint) throws DebugException {
return (getBreakpointManager() != null) ? getBreakpointManager().getBreakpointAddress(breakpoint) : getAddressFactory().getZero();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ISteppingModeTarget#enableInstructionStepping(boolean)
*/
public void enableInstructionStepping(boolean enabled) {
fPreferences.setValue(PREF_INSTRUCTION_STEPPING_MODE, enabled);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ISteppingModeTarget#isInstructionSteppingEnabled()
*/
public boolean isInstructionSteppingEnabled() {
return fPreferences.getBoolean(PREF_INSTRUCTION_STEPPING_MODE);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ISteppingModeTarget#supportsInstructionStepping()
*/
public boolean supportsInstructionStepping() {
return getConfiguration().supportsInstructionStepping();
}
private void initializePreferences() {
fPreferences = new Preferences();
fPreferences.setDefault(PREF_INSTRUCTION_STEPPING_MODE, CDebugCorePlugin.getDefault().getPluginPreferences().getBoolean(ICDebugConstants.PREF_INSTRUCTION_STEP_MODE_ON));
}
private void disposePreferences() {
if (fPreferences != null) {
// persist current instruction stepping mode
CDebugCorePlugin.getDefault().getPluginPreferences().setValue(ICDebugConstants.PREF_INSTRUCTION_STEP_MODE_ON, fPreferences.getBoolean(PREF_INSTRUCTION_STEPPING_MODE));
CDebugCorePlugin.getDefault().savePluginPreferences();
}
fPreferences = null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ITargetProperties#addPropertyChangeListener(org.eclipse.core.runtime.Preferences.IPropertyChangeListener)
*/
public void addPropertyChangeListener(IPropertyChangeListener listener) {
if (fPreferences != null)
fPreferences.addPropertyChangeListener(listener);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ITargetProperties#removePropertyChangeListener(org.eclipse.core.runtime.Preferences.IPropertyChangeListener)
*/
public void removePropertyChangeListener(IPropertyChangeListener listener) {
if (fPreferences != null)
fPreferences.removePropertyChangeListener(listener);
}
protected CGlobalVariableManager getGlobalVariableManager() {
return fGlobalVariableManager;
}
private void setGlobalVariableManager(CGlobalVariableManager globalVariableManager) {
fGlobalVariableManager = globalVariableManager;
}
protected CSettingsManager getFormatManager() {
return fFormatManager;
}
private void setFormatManager(CSettingsManager formatManager) {
fFormatManager = formatManager;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#isPostMortem()
*/
public boolean isPostMortem() {
return false;
}
public IAddressFactory getAddressFactory() {
if (fAddressFactory == null) {
// Ask CDI plug-in for the default AddressFactory.
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget instanceof ICDIAddressFactoryManagement) {
fAddressFactory = ((ICDIAddressFactoryManagement) cdiTarget).getAddressFactory();
}
// And if that doesn't work, use the one from the file.
if (fAddressFactory == null) {
if (getExecFile() != null && getProject() != null) {
IBinaryObject file;
file = getBinaryFile();
if (file != null) {
fAddressFactory = file.getAddressFactory();
}
}
}
}
return fAddressFactory;
}
private CMemoryBlockRetrievalExtension getMemoryBlockRetrieval() {
return fMemoryBlockRetrieval;
}
private void setMemoryBlockRetrieval(CMemoryBlockRetrievalExtension memoryBlockRetrieval) {
fMemoryBlockRetrieval = memoryBlockRetrieval;
}
private void changeState(CDebugElementState state) {
setState(state);
Iterator<CThread> it = getThreadList().iterator();
while (it.hasNext()) {
it.next().setState(state);
}
}
protected void restoreOldState() {
restoreState();
Iterator<CThread> it = getThreadList().iterator();
while (it.hasNext()) {
it.next().restoreState();
}
}
private void handleSymbolsLoaded(ICDISharedLibrary library) {
getModuleManager().symbolsLoaded(library);
}
public ICGlobalVariable createGlobalVariable(IGlobalVariableDescriptor info) throws DebugException {
ICDIVariableDescriptor vo = null;
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
vo = cdiTarget.getGlobalVariableDescriptors(info.getPath().lastSegment(), null, info.getName());
}
} catch (CDIException e) {
throw new DebugException(new Status(IStatus.ERROR, CDIDebugModel.getPluginIdentifier(), DebugException.TARGET_REQUEST_FAILED, e.getMessage(), null));
}
return CVariableFactory.createGlobalVariable(this, info, vo);
}
public void sourceContainersChanged(ISourceLookupDirector director) {
setSourceLookupPath(director.getSourceContainers());
}
private void setSourceLookupPath(ISourceContainer[] containers) {
// LinkedHashSet allows quick lookup and deterministic ordering. We need
// the former to efficiently prevent infinite recursion
LinkedHashSet<String> list = new LinkedHashSet<String>(containers.length);
getSourceLookupPath(list, containers);
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
cdiTarget.setSourcePaths(list.toArray(new String[list.size()]));
}
} catch (CDIException e) {
CDebugCorePlugin.log(e);
}
}
private void getSourceLookupPath(LinkedHashSet<String> list, ISourceContainer[] containers) {
for (ISourceContainer container : containers) {
String pathToAdd = null;
if (container instanceof CProjectSourceContainer) {
IProject project = ((CProjectSourceContainer) container).getProject();
if (project != null && project.exists())
pathToAdd = project.getLocation().toPortableString();
} else if (container instanceof ProjectSourceContainer) { // For backward compatibility
IProject project = ((ProjectSourceContainer) container).getProject();
if (project != null && project.exists())
pathToAdd = project.getLocation().toPortableString();
} else if (container instanceof FolderSourceContainer) {
IContainer folderContainer = ((FolderSourceContainer) container).getContainer();
if (folderContainer != null && folderContainer.exists()) {
pathToAdd = folderContainer.getLocation().toPortableString();
}
} if (container instanceof DirectorySourceContainer) {
File dir = ((DirectorySourceContainer) container).getDirectory();
if (dir != null && dir.exists()) {
IPath path = new Path(dir.getAbsolutePath());
pathToAdd = path.toPortableString();
}
}
if (pathToAdd != null) {
// 291912. Avoid infinite recursion
if (list.contains(pathToAdd)) {
continue;
}
list.add(pathToAdd);
}
if (container.isComposite()) {
try {
getSourceLookupPath(list, container.getSourceContainers());
} catch (CoreException e) {
CDebugCorePlugin.log(e.getStatus());
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#getRegisterDescriptors()
*/
public IRegisterDescriptor[] getRegisterDescriptors() throws DebugException {
return getRegisterManager().getAllRegisterDescriptors();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#addUserDefinedRegisterGroup(java.lang.String, org.eclipse.cdt.debug.core.model.IRegisterDescriptor[])
*/
public void addRegisterGroup(String name, IRegisterDescriptor[] descriptors) {
getRegisterManager().addRegisterGroup(name, descriptors);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#removeRegisterGroups(org.eclipse.debug.core.model.IRegisterGroup[])
*/
public void removeRegisterGroups(IRegisterGroup[] groups) {
getRegisterManager().removeRegisterGroups(groups);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#modifyRegisterGroup(org.eclipse.cdt.debug.core.model.IPersistableRegisterGroup, org.eclipse.cdt.debug.core.model.IRegisterDescriptor[])
*/
public void modifyRegisterGroup(IPersistableRegisterGroup group, IRegisterDescriptor[] descriptors) {
getRegisterManager().modifyRegisterGroup(group, descriptors);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#restoreDefaultRegisterGroups()
*/
public void restoreDefaultRegisterGroups() {
getRegisterManager().restoreDefaults();
}
protected void skipBreakpoints(boolean enabled) {
getBreakpointManager().skipBreakpoints(enabled);
}
/**
* 'stopExpression' is used solely for the error message if the request
* fails. Where to stop is dictated entirely by 'location'
* @param symbol
*/
private void stopAtLocation(ICDILocation location, String stopExpression) throws DebugException {
try {
setInternalTemporaryBreakpoint(location);
} catch (CoreException e) {
final ICDITarget cdiTarget = getCDITarget();
boolean isTerminated = cdiTarget != null && cdiTarget.isTerminated();
if (isTerminated) {
String message = MessageFormat.format(CoreModelMessages.getString("CDebugTarget.0"), new String[]{ stopExpression }); //$NON-NLS-1$
MultiStatus status = new MultiStatus(CDebugCorePlugin.getUniqueIdentifier(), IStatus.OK, message, null);
status.add(e.getStatus());
throw new DebugException(status);
}
String message = MessageFormat.format(CoreModelMessages.getString("CDebugTarget.2"), new String[]{ stopExpression, e.getStatus().getMessage() }); //$NON-NLS-1$
IStatus newStatus = new Status(IStatus.WARNING, e.getStatus().getPlugin(), ICDebugInternalConstants.STATUS_CODE_QUESTION, message, null);
if (!CDebugUtils.question(newStatus, this)) {
throw new DebugException(new Status(IStatus.OK, e.getStatus().getPlugin(), e.getStatus().getCode(), e.getStatus().getMessage(), null));
}
}
}
protected void stopAtSymbol(String stopSymbol) throws DebugException {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
ICDILocation location = cdiTarget.createFunctionLocation("", stopSymbol); //$NON-NLS-1$
stopAtLocation(location, stopSymbol);
}
}
protected void stopAtAddress(IAddress address) throws DebugException {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
ICDIAddressLocation location = cdiTarget.createAddressLocation(address.getValue());
stopAtLocation(location, address.toHexAddressString());
}
}
protected void stopInMain() throws DebugException {
String mainSymbol = ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT;
try {
final ICDITarget cdiTarget = getCDITarget();
if (cdiTarget != null) {
mainSymbol = getLaunch().getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
ICDILocation location = cdiTarget.createFunctionLocation("", mainSymbol); //$NON-NLS-1$
setInternalTemporaryBreakpoint(location);
}
} catch (CoreException e) {
String message = MessageFormat.format(CoreModelMessages.getString("CDebugTarget.2"), new String[]{ mainSymbol, e.getStatus().getMessage() }); //$NON-NLS-1$
IStatus newStatus = new Status(IStatus.WARNING, e.getStatus().getPlugin(), ICDebugInternalConstants.STATUS_CODE_QUESTION, message, null);
if (!CDebugUtils.question(newStatus, this)) {
terminate();
throw new DebugException(new Status(IStatus.OK, e.getStatus().getPlugin(), e.getStatus().getCode(), e.getStatus().getMessage(), null));
}
}
}
public boolean hasModules() throws DebugException {
CModuleManager mm = getModuleManager();
if (mm != null)
return mm.hasModules();
return false;
}
public ICModule[] getModules() throws DebugException {
CModuleManager mm = getModuleManager();
if (mm != null)
return mm.getModules();
return new ICModule[0];
}
public void loadSymbolsForAllModules() throws DebugException {
CModuleManager mm = getModuleManager();
if (mm != null)
mm.loadSymbolsForAllModules();
}
public String getInternalID() {
return internalD;
}
}