blob: 35f96c772ddd14efb898ffb4713832039a1a5e7f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 The Regents of the University of California.
* This material was produced under U.S. Government contract W-7405-ENG-36
* for Los Alamos National Laboratory, which is operated by the University
* of California for the U.S. Department of Energy. The U.S. Government has
* rights to use, reproduce, and distribute this software. NEITHER THE
* GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
* to produce derivative works, such modified software should be clearly marked,
* so as not to confuse it with the version available from LANL.
*
* Additionally, 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
*
* LA-CC 04-115
*******************************************************************************/
package org.eclipse.ptp.debug.internal.core.model;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
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.cdi.CDIException;
import org.eclipse.cdt.debug.core.model.ICModule;
import org.eclipse.cdt.debug.core.model.IDebuggerProcessSupport;
import org.eclipse.cdt.debug.core.model.IDisassembly;
import org.eclipse.cdt.debug.core.model.IPersistableRegisterGroup;
import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
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.resources.ResourcesPlugin;
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.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.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 org.eclipse.ptp.core.util.BitList;
import org.eclipse.ptp.debug.core.IPDebugConstants;
import org.eclipse.ptp.debug.core.PDebugUtils;
import org.eclipse.ptp.debug.core.PTPDebugCorePlugin;
import org.eclipse.ptp.debug.core.cdi.IPCDIBreakpointHit;
import org.eclipse.ptp.debug.core.cdi.IPCDIEndSteppingRange;
import org.eclipse.ptp.debug.core.cdi.IPCDIErrorInfo;
import org.eclipse.ptp.debug.core.cdi.IPCDISession;
import org.eclipse.ptp.debug.core.cdi.IPCDISessionConfiguration;
import org.eclipse.ptp.debug.core.cdi.IPCDISessionObject;
import org.eclipse.ptp.debug.core.cdi.IPCDISharedLibraryEvent;
import org.eclipse.ptp.debug.core.cdi.IPCDISignalReceived;
import org.eclipse.ptp.debug.core.cdi.IPCDIWatchpointScope;
import org.eclipse.ptp.debug.core.cdi.IPCDIWatchpointTrigger;
import org.eclipse.ptp.debug.core.cdi.PCDIException;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIChangedEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDICreatedEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIDestroyedEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIDisconnectedEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIEventListener;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIExitedEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIRestartedEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDIResumedEvent;
import org.eclipse.ptp.debug.core.cdi.event.IPCDISuspendedEvent;
import org.eclipse.ptp.debug.core.cdi.model.IPCDIObject;
import org.eclipse.ptp.debug.core.cdi.model.IPCDISignal;
import org.eclipse.ptp.debug.core.cdi.model.IPCDITarget;
import org.eclipse.ptp.debug.core.cdi.model.IPCDITargetConfiguration;
import org.eclipse.ptp.debug.core.cdi.model.IPCDIThread;
import org.eclipse.ptp.debug.core.cdi.model.IPCDIVariableDescriptor;
import org.eclipse.ptp.debug.core.launch.IPLaunch;
import org.eclipse.ptp.debug.core.model.IExecFileInfo;
import org.eclipse.ptp.debug.core.model.IGlobalVariableDescriptor;
import org.eclipse.ptp.debug.core.model.IPBreakpoint;
import org.eclipse.ptp.debug.core.model.IPDebugElement;
import org.eclipse.ptp.debug.core.model.IPDebugElementStatus;
import org.eclipse.ptp.debug.core.model.IPDebugTarget;
import org.eclipse.ptp.debug.core.model.IPGlobalVariable;
import org.eclipse.ptp.debug.core.model.IPGlobalVariableManager;
import org.eclipse.ptp.debug.core.model.IPLineBreakpoint;
import org.eclipse.ptp.debug.core.model.IPSignal;
import org.eclipse.ptp.debug.core.model.PDebugElementState;
import org.eclipse.ptp.debug.core.sourcelookup.IPSourceLocator;
import org.eclipse.ptp.debug.core.sourcelookup.ISourceLookupChangeListener;
import org.eclipse.ptp.debug.internal.core.PGlobalVariableManager;
import org.eclipse.ptp.debug.internal.core.PSignalManager;
import org.eclipse.ptp.debug.internal.core.PTPMemoryBlockRetrievalExtension;
import org.eclipse.ptp.debug.internal.core.sourcelookup.PSourceLookupParticipant;
import org.eclipse.ptp.debug.internal.core.sourcelookup.PSourceManager;
/**
* @author Clement chu
*
*/
public class PDebugTarget extends PDebugElement implements IPDebugTarget, IPCDIEventListener, ILaunchListener, IExpressionListener, ISourceLookupChangeListener {
private final String PROCESS_NAME = "Process ";
private ArrayList<IThread> fThreads;
private IProcess fDebuggeeProcess = null;
private IPCDITarget fCDITarget;
private IPLaunch fLaunch;
private IPCDITargetConfiguration fConfig;
private PGlobalVariableManager fGlobalVariableManager;
private PSignalManager fSignalManager;
private IBinaryObject fBinaryFile;
private Boolean fIsLittleEndian = null;
private Preferences fPreferences = null;
private IAddressFactory fAddressFactory;
/**
* Support for the memory retrival on this target.
*/
private PTPMemoryBlockRetrievalExtension fMemoryBlockRetrieval;
public PDebugTarget(IPLaunch launch, IPCDITarget cdiTarget, IProcess debuggeeProcess, IBinaryObject file, boolean allowsTerminate, boolean allowsDisconnect) {
super(null);
fLaunch = launch;
fCDITarget = cdiTarget;
setDebugTarget(this);
setProcess(debuggeeProcess);
setExecFile(file);
initializePreferences();
setConfiguration((IPCDITargetConfiguration)cdiTarget.getConfiguration());
setThreadList(new ArrayList<IThread>(5));
if (fCDITarget.isTerminated()) {
setState(PDebugElementState.TERMINATED);
} else {
if (fCDITarget.isSuspended())
setState(PDebugElementState.SUSPENDED);
else
setState(PDebugElementState.UNDEFINED);
setGlobalVariableManager(new PGlobalVariableManager(this));
setMemoryBlockRetrieval(new PTPMemoryBlockRetrievalExtension(this));
setSignalManager(new PSignalManager(this));
initialize();
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
DebugPlugin.getDefault().getExpressionManager().addExpressionListener(this);
getCDISession().getEventManager().addEventListener(this);
}
}
public int getTargetID() {
return fCDITarget.getTargetID();
}
public BitList getTask() {
return fCDITarget.getTask();
}
private PTPMemoryBlockRetrievalExtension getMemoryBlockRetrieval() {
return fMemoryBlockRetrieval;
}
private void setMemoryBlockRetrieval(PTPMemoryBlockRetrievalExtension memoryBlockRetrieval) {
fMemoryBlockRetrieval = memoryBlockRetrieval;
}
protected void initialize() {
initializeSourceLookupPath();
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(1);
debugEvents.add(createCreateEvent());
initializeThreads(debugEvents);
initializeSourceManager();
initializeMemoryBlocks();
fireEventSet((DebugEvent[]) debugEvents.toArray(new DebugEvent[debugEvents.size()]));
}
protected void initializeThreads(List<DebugEvent> debugEvents) {
IPCDIThread[] cdiThreads = new IPCDIThread[0];
try {
if (isSuspended())
cdiThreads = getCDITarget().getThreads();
} catch (PCDIException e) {
// ignore
}
DebugEvent suspendEvent = null;
for (int i = 0; i < cdiThreads.length; ++i) {
PThread thread = createThread(cdiThreads[i]);
debugEvents.add(thread.createCreateEvent());
try {
if (cdiThreads[i].equals(getCDITarget().getCurrentThread()) && thread.isSuspended()) {
// Use BREAKPOINT as a detail to force perspective switch
suspendEvent = thread.createSuspendEvent(DebugEvent.BREAKPOINT);
}
} catch (PCDIException e) {
// ignore
}
}
if (suspendEvent != null) {
debugEvents.add(suspendEvent);
}
}
protected void initializeMemoryBlocks() {
getMemoryBlockRetrieval().initialize();
}
protected void initializeSourceManager() {
ISourceLocator locator = getLaunch().getSourceLocator();
if (locator instanceof IAdaptable) {
IPSourceLocator clocator = (IPSourceLocator) ((IAdaptable) locator).getAdapter(IPSourceLocator.class);
if (clocator instanceof IAdaptable) {
PSourceManager sm = (PSourceManager) ((IAdaptable) clocator).getAdapter(PSourceManager.class);
if (sm != null)
sm.setDebugTarget(this);
}
IResourceChangeListener listener = (IResourceChangeListener) ((IAdaptable) locator).getAdapter(IResourceChangeListener.class);
if (listener != null)
ResourcesPlugin.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 PSourceLookupParticipant) {
((PSourceLookupParticipant) participants[i]).addSourceLookupChangeListener(this);
}
}
setSourceLookupPath(((ISourceLookupDirector) locator).getSourceContainers());
}
}
public IProcess getProcess() {
return fDebuggeeProcess;
}
protected void setProcess(IProcess debuggeeProcess) {
fDebuggeeProcess = debuggeeProcess;
}
public IThread[] getThreads() {
List<IThread> threads = getThreadList();
return (IThread[]) threads.toArray(new IThread[threads.size()]);
}
public boolean hasThreads() throws DebugException {
return getThreadList().size() > 0;
}
public String getName() throws DebugException {
return PROCESS_NAME + getTargetID();
}
public boolean supportsBreakpoint(IBreakpoint breakpoint) {
if (!getConfiguration().supportsBreakpoints())
return false;
// return (breakpoint instanceof IPBreakpoint && getBreakpointManager().supportsBreakpoint( (IPBreakpoint)breakpoint ));
return (breakpoint instanceof IPBreakpoint);
}
public void launchRemoved(ILaunch launch) {
if (!isAvailable()) {
return;
}
if (launch.equals(getLaunch())) {
disconnected();
}
}
public void launchAdded(ILaunch launch) {}
public void launchChanged(ILaunch launch) {}
public boolean canTerminate() {
return supportsTerminate() && isAvailable();
}
public boolean isTerminated() {
return (getState().equals(PDebugElementState.TERMINATED));
}
public void terminate() throws DebugException {
if (!canTerminate()) {
return;
}
changeState(PDebugElementState.TERMINATING);
try {
getCDITarget().terminate();
} catch (PCDIException e) {
restoreOldState();
targetRequestFailed(e.getMessage(), null);
}
}
public boolean canResume() {
return getConfiguration().supportsResume() && isSuspended();
}
public boolean canSuspend() {
if (!getConfiguration().supportsSuspend())
return false;
if (getState().equals(PDebugElementState.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;
}
public boolean isSuspended() {
return (getState().equals(PDebugElementState.SUSPENDED));
}
public void resume() throws DebugException {
if (!canResume())
return;
changeState(PDebugElementState.RESUMING);
try {
getCDITarget().resume(false);
} catch (PCDIException e) {
restoreOldState();
targetRequestFailed(e.getMessage(), null);
}
}
public void suspend() throws DebugException {
if (!canSuspend())
return;
changeState(PDebugElementState.SUSPENDING);
try {
getCDITarget().suspend();
} catch (CDIException e) {
restoreOldState();
targetRequestFailed(e.getMessage(), null);
}
}
protected boolean isSuspending() {
return (getState().equals(PDebugElementState.SUSPENDING));
}
protected void suspendThreads(IPCDISuspendedEvent event) {
Iterator it = getThreadList().iterator();
while (it.hasNext()) {
PThread thread = (PThread) it.next();
IPCDIThread suspensionThread = null;
try {
suspensionThread = (IPCDIThread)getCDITarget().getCurrentThread();
} catch (PCDIException e) {
// ignore
}
thread.suspendByTarget(event.getReason(), suspensionThread);
}
}
protected synchronized List refreshThreads() {
ArrayList<IThread> newThreads = new ArrayList<IThread>(5);
ArrayList<IThread> list = new ArrayList<IThread>(5);
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(5);
List oldList = (List) getThreadList().clone();
IPCDIThread[] cdiThreads = new IPCDIThread[0];
IPCDIThread currentCDIThread = null;
try {
cdiThreads = (IPCDIThread[])getCDITarget().getThreads();
currentCDIThread = (IPCDIThread)getCDITarget().getCurrentThread();
} catch (PCDIException e) {
}
for (int i = 0; i < cdiThreads.length; ++i) {
PThread thread = findThread(oldList, cdiThreads[i]);
if (thread == null) {
thread = new PThread(this, cdiThreads[i]);
newThreads.add(thread);
} else {
oldList.remove(thread);
}
thread.setCurrent(cdiThreads[i].equals(currentCDIThread));
list.add(thread);
}
Iterator it = oldList.iterator();
while (it.hasNext()) {
PThread thread = (PThread) it.next();
thread.terminated();
debugEvents.add(thread.createTerminateEvent());
}
setThreadList(list);
it = newThreads.iterator();
while (it.hasNext()) {
debugEvents.add(((PThread) it.next()).createCreateEvent());
}
if (debugEvents.size() > 0)
fireEventSet((DebugEvent[]) debugEvents.toArray(new DebugEvent[debugEvents.size()]));
return newThreads;
}
protected synchronized void resumeThreads(List debugEvents, int detail) {
Iterator it = getThreadList().iterator();
while (it.hasNext()) {
((PThread) it.next()).resumedByTarget(detail, debugEvents);
}
}
public void breakpointAdded(IBreakpoint breakpoint) {}
public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {}
public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {}
protected boolean supportsDisconnect() {
// No Discount
// return getConfiguration().supportsDisconnect();
return false;
}
protected boolean supportsTerminate() {
return getConfiguration().supportsTerminate();
}
public boolean canDisconnect() {
// No disconnet
// return supportsDisconnect() && isAvailable();
return false;
}
public void disconnect() throws DebugException {
if (isDisconnecting()) {
return;
}
changeState(PDebugElementState.DISCONNECTING);
try {
getCDITarget().disconnect();
} catch (PCDIException e) {
restoreOldState();
targetRequestFailed(e.getMessage(), null);
}
}
public boolean isDisconnected() {
return (getState().equals(PDebugElementState.DISCONNECTED));
}
public boolean supportsStorageRetrieval() {
return false;
}
public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
return null;
}
public ILaunch getLaunch() {
return fLaunch;
}
protected ArrayList<IThread> getThreadList() {
return fThreads;
}
private void setThreadList(ArrayList<IThread> threads) {
fThreads = threads;
}
public Object getAdapter(Class adapter) {
if (adapter.equals(IPDebugElement.class))
return this;
if (adapter.equals(PDebugElement.class))
return this;
if (adapter.equals(IDebugTarget.class))
return this;
if (adapter.equals(IPDebugTarget.class))
return this;
if (adapter.equals(PDebugTarget.class))
return this;
if (adapter.equals(IPCDITarget.class))
return fCDITarget;
if (adapter.equals(IDebuggerProcessSupport.class))
return this;
if (adapter.equals(IExecFileInfo.class))
return this;
if (adapter.equals(IPGlobalVariableManager.class))
return getGlobalVariableManager();
if (adapter.equals(IPCDISession.class))
return getCDISession();
if (adapter.equals(IMemoryBlockRetrievalExtension.class))
return getMemoryBlockRetrieval();
if ( adapter.equals( IMemoryBlockRetrieval.class ) )
return getMemoryBlockRetrieval();
return super.getAdapter(adapter);
}
public void handleDebugEvents(IPCDIEvent[] events) {
for (int i = 0; i < events.length; i++) {
IPCDIEvent event = events[i];
if (!event.containTask(getTargetID()))
return;
IPCDIObject source = event.getSource(getTargetID());
if (source == null && event instanceof IPCDIDestroyedEvent) {
handleTerminatedEvent((IPCDIDestroyedEvent) event, source);
} else if (source != null && source.getTarget().equals(getCDITarget())) {
if (event instanceof IPCDICreatedEvent) {
if (source instanceof IPCDIThread) {
handleThreadCreatedEvent((IPCDICreatedEvent) event, source);
}
} else if (event instanceof IPCDISuspendedEvent) {
if (source instanceof IPCDITarget) {
handleSuspendedEvent((IPCDISuspendedEvent) event, source);
}
} else if (event instanceof IPCDIResumedEvent) {
if (source instanceof IPCDITarget) {
handleResumedEvent((IPCDIResumedEvent) event, source);
}
} else if (event instanceof IPCDIExitedEvent) {
if (source instanceof IPCDITarget) {
handleExitedEvent((IPCDIExitedEvent) event, source);
}
} else if (event instanceof IPCDIDestroyedEvent) {
if (source instanceof IPCDIThread) {
handleThreadTerminatedEvent((IPCDIDestroyedEvent) event, source);
}
} else if (event instanceof IPCDIDisconnectedEvent) {
if (source instanceof IPCDITarget) {
handleDisconnectedEvent((IPCDIDisconnectedEvent) event, source);
}
} else if (event instanceof IPCDIChangedEvent) {
if (source instanceof IPCDITarget) {
handleChangedEvent((IPCDIChangedEvent) event, source);
}
if (source instanceof IPCDISignal) {
getSignalManager().signalChanged((IPCDISignal)source);
}
} else if (event instanceof IPCDIRestartedEvent) {
if (source instanceof IPCDITarget) {
handleRestartedEvent((IPCDIRestartedEvent) event, source);
}
}
}
}
}
public boolean canRestart() {
// return getConfiguration().supportsRestart() && isSuspended();
// Cannot restart
return false;
}
public void restart() throws DebugException {
if (!canRestart()) {
return;
}
changeState(PDebugElementState.RESTARTING);
//IPCDILocation location = (IPCDILocation)getCDITarget().createFunctionLocation("", "main");
//setInternalTemporaryBreakpoint(location);
try {
getCDITarget().restart();
} catch (PCDIException e) {
restoreOldState();
targetRequestFailed(e.getMessage(), e);
}
}
public boolean isAvailable() {
return !(isTerminated() || isTerminating() || isDisconnected() || isDisconnecting());
}
protected boolean isTerminating() {
return (getState().equals(PDebugElementState.TERMINATING));
}
public void terminated() {
if (!isTerminated()) {
if (!isDisconnected()) {
setState(PDebugElementState.TERMINATED);
}
cleanup();
fireTerminateEvent();
}
}
protected boolean isDisconnecting() {
return (getState().equals(PDebugElementState.DISCONNECTING));
}
protected void disconnected() {
if (!isDisconnected()) {
setState(PDebugElementState.DISCONNECTED);
cleanup();
fireTerminateEvent();
}
}
public void cleanup() {
resetStatus();
removeAllThreads();
getCDISession().getEventManager().removeEventListener(this);
DebugPlugin.getDefault().getExpressionManager().removeExpressionListener(this);
DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
saveGlobalVariables();
//saveMemoryBlocks(); //Don't save to launch configuration
disposeMemoryBlockRetrieval();
disposeGlobalVariableManager();
disposeSourceManager();
disposeSourceLookupPath();
removeAllExpressions();
disposePreferences();
}
protected void saveMemoryBlocks() {
getMemoryBlockRetrieval().save();
}
protected void disposeMemoryBlockRetrieval() {
getMemoryBlockRetrieval().dispose();
}
protected void removeAllThreads() {
List<IThread> threads = getThreadList();
setThreadList(new ArrayList<IThread>(0));
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(threads.size());
Iterator it = threads.iterator();
while (it.hasNext()) {
PThread thread = (PThread) it.next();
thread.terminated();
debugEvents.add(thread.createTerminateEvent());
}
fireEventSet((DebugEvent[]) debugEvents.toArray(new DebugEvent[debugEvents.size()]));
}
protected void removeAllExpressions() {
IExpressionManager em = DebugPlugin.getDefault().getExpressionManager();
IExpression[] expressions = em.getExpressions();
for (int i = 0; i < expressions.length; ++i) {
if (expressions[i] instanceof PExpression && expressions[i].getDebugTarget().equals(this)) {
em.removeExpression(expressions[i]);
}
}
}
protected PThread createThread(IPCDIThread cdiThread) {
PThread thread = new PThread(this, cdiThread);
getThreadList().add(thread);
return thread;
}
private void handleSuspendedEvent(IPCDISuspendedEvent event, IPCDIObject source) {
setState(PDebugElementState.SUSPENDED);
IPCDISessionObject reason = event.getReason();
setCurrentStateInfo(reason);
skipBreakpoints(false);
List newThreads = refreshThreads();
if (source instanceof IPCDITarget) {
//if (!(this.getConfiguration() instanceof ICDITargetConfiguration2) || !((ICDITargetConfiguration2)this.getConfiguration()).supportsThreadControl())
suspendThreads(event);
}
// We need this for debuggers that don't have notifications for newly created threads.
else if (source instanceof IPCDIThread) {
PThread thread = findThread((IPCDIThread) source);
if (thread != null && newThreads.contains(thread)) {
IPCDIEvent[] evts = new IPCDIEvent[] { event };
thread.handleDebugEvents(evts);
}
}
if (reason instanceof IPCDIEndSteppingRange) {
handleEndSteppingRange((IPCDIEndSteppingRange) reason);
} else if (reason instanceof IPCDIBreakpointHit) {
handleBreakpointHit((IPCDIBreakpointHit) reason);
} else if (reason instanceof IPCDISignalReceived) {
handleSuspendedBySignal((IPCDISignalReceived) reason);
} else if (reason instanceof IPCDIWatchpointTrigger) {
handleWatchpointTrigger((IPCDIWatchpointTrigger) reason);
} else if (reason instanceof IPCDIWatchpointScope) {
handleWatchpointScope((IPCDIWatchpointScope) reason);
} else if (reason instanceof IPCDIErrorInfo) {
handleErrorInfo((IPCDIErrorInfo) reason);
} else if (reason instanceof IPCDISharedLibraryEvent) {
handleSuspendedBySolibEvent((IPCDISharedLibraryEvent) reason);
} else { // reason is not specified
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
}
private void handleResumedEvent(IPCDIResumedEvent event, IPCDIObject source) {
setState(PDebugElementState.RESUMED);
setCurrentStateInfo(null);
resetStatus();
ArrayList<DebugEvent> debugEvents = new ArrayList<DebugEvent>(10);
int detail = DebugEvent.UNSPECIFIED;
switch (event.getType()) {
case IPCDIResumedEvent.CONTINUE:
detail = DebugEvent.CLIENT_REQUEST;
break;
case IPCDIResumedEvent.STEP_INTO:
case IPCDIResumedEvent.STEP_INTO_INSTRUCTION:
detail = DebugEvent.STEP_INTO;
break;
case IPCDIResumedEvent.STEP_OVER:
case IPCDIResumedEvent.STEP_OVER_INSTRUCTION:
detail = DebugEvent.STEP_OVER;
break;
case IPCDIResumedEvent.STEP_RETURN:
detail = DebugEvent.STEP_RETURN;
break;
}
debugEvents.add(createResumeEvent(detail));
//if (!(this.getConfiguration() instanceof ICDITargetConfiguration2) || !((ICDITargetConfiguration2)this.getConfiguration()).supportsThreadControl())
resumeThreads(debugEvents, detail);
fireEventSet((DebugEvent[]) debugEvents.toArray(new DebugEvent[debugEvents.size()]));
}
private void handleEndSteppingRange(IPCDIEndSteppingRange endSteppingRange) {
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
private void handleBreakpointHit(IPCDIBreakpointHit breakpointHit) {
fireSuspendEvent(DebugEvent.BREAKPOINT);
}
private void handleWatchpointTrigger(IPCDIWatchpointTrigger wt) {
fireSuspendEvent(DebugEvent.BREAKPOINT);
}
private void handleWatchpointScope(IPCDIWatchpointScope ws) {
// DONNY
// getBreakpointManager().watchpointOutOfScope( ws.getWatchpoint() ); fireSuspendEvent( DebugEvent.BREAKPOINT );
}
private void handleSuspendedBySignal(IPCDISignalReceived signal) {
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
private void handleErrorInfo(IPCDIErrorInfo info) {
setStatus(IPDebugElementStatus.ERROR, (info != null) ? info.getMessage() : null);
if (info != null) {
MultiStatus status = new MultiStatus(PTPDebugCorePlugin.getUniqueIdentifier(), IPDebugConstants.STATUS_CODE_ERROR, CoreModelMessages.getString("PDebugTarget.1"), null);
StringTokenizer st = new StringTokenizer(info.getDetailMessage(), "\n\r");
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (token.length() > 200) {
token = token.substring(0, 200);
}
status.add(new Status(IStatus.ERROR, status.getPlugin(), IPDebugConstants.STATUS_CODE_ERROR, token, null));
}
PDebugUtils.error(status, this);
}
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
private void handleSuspendedBySolibEvent(IPCDISharedLibraryEvent solibEvent) {
fireSuspendEvent(DebugEvent.UNSPECIFIED);
}
private void handleExitedEvent(IPCDIExitedEvent event, IPCDIObject source) {
removeAllThreads();
setState(PDebugElementState.EXITED);
setCurrentStateInfo(event.getReason());
fireChangeEvent(DebugEvent.CONTENT);
IPCDISessionConfiguration sessionConfig = getCDISession().getConfiguration();
if (sessionConfig != null && sessionConfig.terminateSessionOnExit())
terminated();
}
private void handleTerminatedEvent(IPCDIDestroyedEvent event, IPCDIObject source) {
terminated();
}
private void handleDisconnectedEvent(IPCDIDisconnectedEvent event, IPCDIObject source) {
disconnected();
}
private void handleChangedEvent(IPCDIChangedEvent event, IPCDIObject source) {}
private void handleRestartedEvent(IPCDIRestartedEvent event, IPCDIObject source) {}
private void handleThreadCreatedEvent(IPCDICreatedEvent event, IPCDIObject source) {
IPCDIThread cdiThread = (IPCDIThread) source;
PThread thread = findThread(cdiThread);
if (thread == null) {
thread = createThread(cdiThread);
thread.fireCreationEvent();
}
}
private void handleThreadTerminatedEvent(IPCDIDestroyedEvent event, IPCDIObject source) {
IPCDIThread cdiThread = (IPCDIThread) source;
PThread thread = findThread(cdiThread);
if (thread != null) {
getThreadList().remove(thread);
thread.terminated();
thread.fireTerminateEvent();
}
}
public PThread findThread(IPCDIThread cdiThread) {
List threads = getThreadList();
for (int i = 0; i < threads.size(); i++) {
PThread t = (PThread) threads.get(i);
if (t.getCDIThread().equals(cdiThread))
return t;
}
return null;
}
public PThread findThread(List threads, IPCDIThread cdiThread) {
for (int i = 0; i < threads.size(); i++) {
PThread t = (PThread) threads.get(i);
if (t.getCDIThread().equals(cdiThread))
return t;
}
return null;
}
protected IPCDITargetConfiguration getConfiguration() {
return fConfig;
}
private void setConfiguration(IPCDITargetConfiguration config) {
fConfig = config;
}
protected boolean supportsExpressionEvaluation() {
return getConfiguration().supportsExpressionEvaluation();
}
public void expressionAdded(IExpression expression) {}
public void expressionChanged(IExpression expression) {}
public void expressionRemoved(IExpression expression) {
if (expression instanceof PExpression && expression.getDebugTarget().equals(this)) {
((PExpression) expression).dispose();
}
}
/*
public void setInternalTemporaryBreakpoint(IPCDILocation location) throws DebugException {
try {
if (location instanceof ICDIFunctionLocation) {
getCDITarget().setFunctionBreakpoint(IPCDIBreakpoint.TEMPORARY, (IPCDIFunctionLocation) location, null, false);
} else if (location instanceof ICDILineLocation) {
getCDITarget().setLineBreakpoint(IPCDIBreakpoint.TEMPORARY, (IPCDILineLocation) location, null, false);
} else if (location instanceof ICDIAddressLocation) {
getCDITarget().setAddressBreakpoint(IPCDIBreakpoint.TEMPORARY, (IPCDIAddressLocation) location, null, false);
} else {
// ???
targetRequestFailed("not_a_location", null);
}
} catch (PCDIException e) {
targetRequestFailed(e.getMessage(), null);
}
}
*/
protected IThread getCurrentThread() throws DebugException {
IThread[] threads = getThreads();
for (int i = 0; i < threads.length; ++i) {
if (((PThread) threads[i]).isCurrent())
return threads[i];
}
return null;
}
protected ISourceLocator getSourceLocator() {
return getLaunch().getSourceLocator();
}
public boolean isLittleEndian() {
if (fIsLittleEndian == null) {
fIsLittleEndian = Boolean.TRUE;
IBinaryObject file = getBinaryFile();
if (file != null) {
fIsLittleEndian = new Boolean(file.isLittleEndian());
}
}
return fIsLittleEndian.booleanValue();
}
public IBinaryObject getExecFile() {
return getBinaryFile();
}
public IBinaryObject getBinaryFile() {
return fBinaryFile;
}
private void setExecFile(IBinaryObject file) {
fBinaryFile = file;
}
protected void saveGlobalVariables() {
fGlobalVariableManager.save();
}
protected void disposeGlobalVariableManager() {
fGlobalVariableManager.dispose();
}
public boolean canResumeWithoutSignal() {
// Check if the configuration supports this!!!
return (canResume() && getCurrentStateInfo() instanceof IPCDISignalReceived);
}
public void resumeWithoutSignal() throws DebugException {
if (!canResume())
return;
changeState(PDebugElementState.RESUMING);
try {
getCDITarget().resume(false);
} catch (PCDIException e) {
restoreOldState();
targetRequestFailed(e.getMessage(), e);
}
}
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 PSourceLookupParticipant) {
((PSourceLookupParticipant) participants[i]).removeSourceLookupChangeListener(this);
}
}
}
}
public String toString() {
String result = "";
try {
result = getName();
} catch (DebugException e) {
}
return result;
}
public IPSignal[] getSignals() throws DebugException {
PSignalManager sm = getSignalManager();
if (sm != null) {
return sm.getSignals();
}
return new IPSignal[0];
}
public boolean hasSignals() throws DebugException {
PSignalManager sm = getSignalManager();
if (sm != null) {
return (sm.getSignals().length > 0);
}
return false;
}
public IAddress getBreakpointAddress(IPLineBreakpoint breakpoint) throws DebugException {
// TODO Not implement yet
return null;
}
public void enableInstructionStepping(boolean enabled) {
fPreferences.setValue(PREF_INSTRUCTION_STEPPING_MODE, enabled);
}
public boolean supportsInstructionStepping() {
return getConfiguration().supportsInstructionStepping();
}
public boolean isInstructionSteppingEnabled() {
// TODO Not implement yet
// return fPreferences.getBoolean( PREF_INSTRUCTION_STEPPING_MODE ) || CDebugCorePlugin.getDefault().getPluginPreferences().getBoolean( ICDebugConstants.PREF_INSTRUCTION_STEP_MODE_ON );
return false;
}
private void initializePreferences() {
fPreferences = new Preferences();
fPreferences.setDefault(PREF_INSTRUCTION_STEPPING_MODE, false);
}
private void disposePreferences() {
fPreferences = null;
}
public void addPropertyChangeListener(IPropertyChangeListener listener) {
if (fPreferences != null)
fPreferences.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(IPropertyChangeListener listener) {
if (fPreferences != null)
fPreferences.removePropertyChangeListener(listener);
}
protected PGlobalVariableManager getGlobalVariableManager() {
return fGlobalVariableManager;
}
private void setGlobalVariableManager(PGlobalVariableManager globalVariableManager) {
fGlobalVariableManager = globalVariableManager;
}
protected void setSignalManager(PSignalManager sm) {
fSignalManager = sm;
}
protected PSignalManager getSignalManager() {
return fSignalManager;
}
protected void disposeSignalManager() {
fSignalManager.dispose();
}
public boolean isPostMortem() {
return false;
}
public IAddressFactory getAddressFactory() {
if (fAddressFactory == null) {
if (getExecFile() != null) {
IBinaryObject file = getBinaryFile();
if (file != null) {
fAddressFactory = file.getAddressFactory();
}
}
}
return fAddressFactory;
}
private void changeState(PDebugElementState state) {
setState(state);
Iterator it = getThreadList().iterator();
while (it.hasNext()) {
((PThread) it.next()).setState(state);
}
}
protected void restoreOldState() {
restoreState();
Iterator it = getThreadList().iterator();
while (it.hasNext()) {
((PThread) it.next()).restoreState();
}
}
protected void skipBreakpoints(boolean enabled) {
// FIXME Donny
// We do not have skipBreakpoints support for each individual target
// getBreakpointManager().skipBreakpoints( enabled );
}
public IDisassembly getDisassembly() throws DebugException {
// TODO Not implement yet
return null;
}
public IPGlobalVariable createGlobalVariable(IGlobalVariableDescriptor info) throws DebugException {
IPCDIVariableDescriptor vo = null;
try {
vo = (IPCDIVariableDescriptor)getCDITarget().getGlobalVariableDescriptors(info.getPath().lastSegment(), null, info.getName());
} catch (PCDIException e) {
throw new DebugException(new Status(IStatus.ERROR, PTPDebugCorePlugin.getUniqueIdentifier(), DebugException.TARGET_REQUEST_FAILED, (vo != null) ? vo.getName() + ": " + e.getMessage() : e.getMessage(), null)); //$NON-NLS-1$
}
return PVariableFactory.createGlobalVariable(this, info, vo);
}
public boolean hasModules() throws DebugException {
// TODO Not implement yet
return false;
}
public ICModule[] getModules() throws DebugException {
// TODO Not implement yet
return null;
}
public void loadSymbolsForAllModules() throws DebugException {
// TODO Not implement yet
}
public IRegisterDescriptor[] getRegisterDescriptors() throws DebugException {
// TODO Not implement yet
return null;
}
public void addRegisterGroup(String name, IRegisterDescriptor[] descriptors) {
// TODO Not implement yet
}
public void removeRegisterGroups(IRegisterGroup[] groups) {
// TODO Not implement yet
}
public void modifyRegisterGroup(IPersistableRegisterGroup group, IRegisterDescriptor[] descriptors) {
// TODO Not implement yet
}
public void restoreDefaultRegisterGroups() {
// TODO Not implement yet
}
public IGlobalVariableDescriptor[] getGlobals() throws DebugException {
ArrayList<IGlobalVariableDescriptor> list = new ArrayList<IGlobalVariableDescriptor>();
IBinaryObject file = getBinaryFile();
if (file != null) {
list.addAll(getCFileGlobals(file));
}
return (IGlobalVariableDescriptor[]) list.toArray(new IGlobalVariableDescriptor[list.size()]);
}
private List<IGlobalVariableDescriptor> getCFileGlobals(IBinaryObject file) throws DebugException {
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(PVariableFactory.createGlobalVariableDescriptor(symbols[i]));
}
}
return list;
}
public void sourceContainersChanged(ISourceLookupDirector director) {
setSourceLookupPath(director.getSourceContainers());
}
private void setSourceLookupPath(ISourceContainer[] containers) {
ArrayList<String> list = new ArrayList<String>(containers.length);
getSourceLookupPath(list, containers);
try {
getCDITarget().setSourcePaths((String[]) list.toArray(new String[list.size()]));
} catch (CDIException e) {
PTPDebugCorePlugin.log(e);
}
}
private void getSourceLookupPath(List<String> list, ISourceContainer[] containers) {
for (int i = 0; i < containers.length; ++i) {
if (containers[i] instanceof ProjectSourceContainer) {
IProject project = ((ProjectSourceContainer) containers[i]).getProject();
if (project != null && project.exists())
list.add(project.getLocation().toPortableString());
}
if (containers[i] instanceof FolderSourceContainer) {
IContainer container = ((FolderSourceContainer) containers[i]).getContainer();
if (container != null && container.exists())
list.add(container.getLocation().toPortableString());
}
if (containers[i] instanceof DirectorySourceContainer) {
File dir = ((DirectorySourceContainer) containers[i]).getDirectory();
if (dir != null && dir.exists()) {
IPath path = new Path(dir.getAbsolutePath());
list.add(path.toPortableString());
}
}
if (containers[i].isComposite()) {
try {
getSourceLookupPath(list, containers[i].getSourceContainers());
} catch (CoreException e) {
PTPDebugCorePlugin.log(e.getStatus());
}
}
}
}
}