blob: eddbafdc9a912a52b51cdad5ce58033e8f4ec637 [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.pdi.model;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.ptp.core.util.BitList;
import org.eclipse.ptp.debug.core.pdi.IPDILocator;
import org.eclipse.ptp.debug.core.pdi.IPDISession;
import org.eclipse.ptp.debug.core.pdi.PDIException;
import org.eclipse.ptp.debug.core.pdi.PDILocationFactory;
import org.eclipse.ptp.debug.core.pdi.SessionObject;
import org.eclipse.ptp.debug.core.pdi.event.IPDIEvent;
import org.eclipse.ptp.debug.core.pdi.manager.IPDIRegisterManager;
import org.eclipse.ptp.debug.core.pdi.manager.IPDIVariableManager;
import org.eclipse.ptp.debug.core.pdi.model.IPDIGlobalVariable;
import org.eclipse.ptp.debug.core.pdi.model.IPDIGlobalVariableDescriptor;
import org.eclipse.ptp.debug.core.pdi.model.IPDIInstruction;
import org.eclipse.ptp.debug.core.pdi.model.IPDIMixedInstruction;
import org.eclipse.ptp.debug.core.pdi.model.IPDIRegister;
import org.eclipse.ptp.debug.core.pdi.model.IPDIRegisterDescriptor;
import org.eclipse.ptp.debug.core.pdi.model.IPDIRegisterGroup;
import org.eclipse.ptp.debug.core.pdi.model.IPDIRuntimeOptions;
import org.eclipse.ptp.debug.core.pdi.model.IPDISharedLibrary;
import org.eclipse.ptp.debug.core.pdi.model.IPDIStackFrame;
import org.eclipse.ptp.debug.core.pdi.model.IPDIStackFrameDescriptor;
import org.eclipse.ptp.debug.core.pdi.model.IPDITarget;
import org.eclipse.ptp.debug.core.pdi.model.IPDIThread;
import org.eclipse.ptp.debug.core.pdi.model.IPDIVariable;
import org.eclipse.ptp.debug.core.pdi.model.aif.IAIF;
import org.eclipse.ptp.debug.core.pdi.request.IPDIGetInfoThreadsRequest;
import org.eclipse.ptp.debug.core.pdi.request.IPDISetThreadSelectRequest;
/**
* @author clement
*
*/
public class Target extends SessionObject implements IPDITarget {
private Thread[] noThreads = new Thread[0];
private Thread[] currentThreads;
private int currentThreadId;
private final ReentrantLock lock = new ReentrantLock();
public Target(IPDISession session, BitList tasks) {
super(session, tasks);
currentThreads = noThreads;
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#createGlobalVariable(org.eclipse.ptp.debug.core.pdi.model.IPDIGlobalVariableDescriptor)
*/
public IPDIGlobalVariable createGlobalVariable(
IPDIGlobalVariableDescriptor varDesc) throws PDIException {
if (varDesc instanceof IPDIGlobalVariableDescriptor) {
IPDIVariableManager varMgr = getSession().getVariableManager();
return varMgr.createGlobalVariable((IPDIGlobalVariableDescriptor) varDesc);
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#createRegister(org.eclipse.ptp.debug.core.pdi.model.IPDIRegisterDescriptor)
*/
public IPDIRegister createRegister(IPDIRegisterDescriptor varDesc)
throws PDIException {
if (varDesc instanceof RegisterDescriptor) {
return session.getRegisterManager().createRegister((RegisterDescriptor) varDesc);
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#evaluateExpressionToString(org.eclipse.ptp.debug.core.pdi.model.IPDIStackFrame, java.lang.String)
*/
public String evaluateExpressionToString(IPDIStackFrame context, String expr)
throws PDIException {
Target target = (Target) context.getTarget();
Thread currentThread = (Thread) target.getCurrentThread();
IPDIStackFrame currentFrame = currentThread.getCurrentStackFrame();
target.setCurrentThread((IPDIThread) context.getThread(), false);
((Thread) context.getThread()).setCurrentStackFrame(
(StackFrame) context, false);
try {
IAIF aif = null;
IPDIVariable var = session.getVariableManager().getVariableByName(tasks, expr);
if (var == null) {
aif = session.getExpressionManager().getExpressionValue(getTasks(), expr);
} else {
aif = var.getAIF();
}
if (aif != null)
return aif.getValue().toString();
throw new PDIException(getTasks(), "Unknonw varibale: " + expr);
} finally {
target.setCurrentThread(currentThread, false);
currentThread.setCurrentStackFrame(currentFrame, false);
}
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#getCurrentThread()
*/
public synchronized Thread getCurrentThread() throws PDIException {
Thread[] threads = getThreads();
for (int i = 0; i < threads.length; i++) {
Thread pthread = (Thread) threads[i];
if (pthread.getId() == currentThreadId) {
return pthread;
}
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#getGlobalVariableDescriptors(java.lang.String, java.lang.String, java.lang.String)
*/
public IPDIGlobalVariableDescriptor getGlobalVariableDescriptors(
String filename, String function, String name) throws PDIException {
return session.getVariableManager().getGlobalVariableDescriptor(
getTasks(), filename, function, name);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#getInstructions(java.math.BigInteger, java.math.BigInteger)
*/
public IPDIInstruction[] getInstructions(BigInteger startAddress,
BigInteger endAddress) throws PDIException {
return session.getSourceManager().getInstructions(getTasks(),
startAddress, endAddress);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#getInstructions(java.lang.String, int)
*/
public IPDIInstruction[] getInstructions(String filename, int linenum)
throws PDIException {
return session.getSourceManager().getInstructions(getTasks(), filename,
linenum);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#getInstructions(java.lang.String, int, int)
*/
public IPDIInstruction[] getInstructions(String filename, int linenum,
int lines) throws PDIException {
return session.getSourceManager().getInstructions(getTasks(), filename,
linenum, lines);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#getMixedInstructions(java.math.BigInteger, java.math.BigInteger)
*/
public IPDIMixedInstruction[] getMixedInstructions(BigInteger startAddress,
BigInteger endAddress) throws PDIException {
return session.getSourceManager().getMixedInstructions(getTasks(),
startAddress, endAddress);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#getMixedInstructions(java.lang.String, int)
*/
public IPDIMixedInstruction[] getMixedInstructions(String filename,
int linenum) throws PDIException {
return session.getSourceManager().getMixedInstructions(getTasks(),
filename, linenum);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#getMixedInstructions(java.lang.String, int, int)
*/
public IPDIMixedInstruction[] getMixedInstructions(String filename,
int linenum, int lines) throws PDIException {
return session.getSourceManager().getMixedInstructions(getTasks(),
filename, linenum, lines);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#getRegisterGroups()
*/
public IPDIRegisterGroup[] getRegisterGroups() throws PDIException {
return session.getRegisterManager().getRegisterGroups(getTasks());
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#getRuntimeOptions()
*/
public IPDIRuntimeOptions getRuntimeOptions() {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISharedLibraryManagement#getSharedLibraries()
*/
public IPDISharedLibrary[] getSharedLibraries() throws PDIException {
throw new PDIException(getTasks(),
"Not implemented yet - Target: getSharedLibraries()");
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#getSourcePaths()
*/
public String[] getSourcePaths() throws PDIException {
return session.getSourceManager().getSourcePaths(getTasks());
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#getThreads()
*/
public synchronized Thread[] getThreads() throws PDIException {
if (currentThreads.length == 0) {
currentThreads = getPThreads();
}
return currentThreads;
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#lockTarget()
*/
public void lockTarget() {
lock.lock();
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#releaseTarget()
*/
public void releaseTarget() {
lock.unlock();
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#setCurrentThread(org.eclipse.ptp.debug.internal.core.pdi.model.Thread, boolean)
*/
public void setCurrentThread(IPDIThread pthread, boolean doUpdate)
throws PDIException {
if (pthread instanceof IPDIThread) {
int id = pthread.getId();
if (id == 0) {
return;
}
if (currentThreadId != id) {
IPDISetThreadSelectRequest request = session.getRequestFactory().getSetThreadSelectRequest(
session, getTasks(), id);
session.getEventRequestManager().addEventRequest(request);
currentThreadId = request.getThreadId(getTasks());
IPDIStackFrameDescriptor frame = request.getStackFrame(getTasks());
if (frame != null) {
int depth = pthread.getStackFrameCount();
IPDILocator locator = PDILocationFactory.newLocator(frame.getLocator()
.getFile(), frame.getLocator().getFunction(), frame
.getLocator().getLineNumber(), frame.getLocator()
.getAddress());
pthread.setCurrentStackFrame(session.getModelFactory().newStackFrame(session, pthread, depth
- frame.getLevel(), locator));
}
if (doUpdate) {
IPDIRegisterManager regMgr = session.getRegisterManager();
if (regMgr.isAutoUpdate()) {
regMgr.update(getTasks());
}
IPDIVariableManager varMgr = session.getVariableManager();
if (varMgr.isAutoUpdate()) {
varMgr.update(getTasks());
}
}
}
if (currentThreadId != id) {
session.getEventManager().fireEvents(
new IPDIEvent[] { session.getEventFactory().newDestroyedEvent(
session.getEventFactory().newThreadInfo(session, getTasks(), id, getThread(id))) });
throw new PDIException(getTasks(),
"Target - Cannot switch to thread " + id);
}
} else {
throw new PDIException(getTasks(), "Target - Unknown_thread");
}
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDISourceManagement#setSourcePaths(java.lang.String[])
*/
public void setSourcePaths(String[] srcPaths) throws PDIException {
session.getSourceManager().setSourcePaths(getTasks(), srcPaths);
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#setSupended(boolean)
*/
public synchronized void setSupended(boolean state) {
notifyAll();
}
/* (non-Javadoc)
* @see org.eclipse.ptp.debug.core.pdi.model.IPDITarget#updateState(int)
*/
public synchronized void updateState(int newThreadId) {
Thread[] oldThreads = currentThreads;
lockTarget();
currentThreadId = newThreadId;
try {
currentThreads = getPThreads();
} catch (PDIException e) {
currentThreads = noThreads;
}
releaseTarget();
List<Integer> pList = new ArrayList<Integer>(currentThreads.length);
for (int i = 0; i < currentThreads.length; i++) {
boolean found = false;
for (int j = 0; j < oldThreads.length; j++) {
if (currentThreads[i].getId() == oldThreads[j].getId()) {
oldThreads[j].clearState();
currentThreads[i] = oldThreads[j];
found = true;
break;
}
}
if (!found) {
pList.add(new Integer(currentThreads[i].getId()));
}
}
if (!pList.isEmpty()) {
IPDIEvent[] events = new IPDIEvent[pList.size()];
for (int j = 0; j < events.length; j++) {
int id = ((Integer) pList.get(j)).intValue();
events[j] = session.getEventFactory().newCreatedEvent(
session.getEventFactory().newThreadInfo(session, getTasks(), id, getThread(id)));
}
session.getEventManager().fireEvents(events);
}
// Fire destroyed event for old threads
List<Integer> dList = new ArrayList<Integer>(oldThreads.length);
for (int i = 0; i < oldThreads.length; i++) {
boolean found = false;
for (int j = 0; j < currentThreads.length; j++) {
if (currentThreads[j].getId() == oldThreads[i].getId()) {
found = true;
break;
}
}
if (!found) {
dList.add(new Integer(oldThreads[i].getId()));
}
}
if (!dList.isEmpty()) {
IPDIEvent[] events = new IPDIEvent[dList.size()];
for (int j = 0; j < events.length; j++) {
int id = ((Integer) dList.get(j)).intValue();
events[j] = session.getEventFactory().newDestroyedEvent(
session.getEventFactory().newThreadInfo(session, getTasks(), id, getThread(id)));
}
session.getEventManager().fireEvents(events);
}
}
/**
* @return
* @throws PDIException
*/
private synchronized Thread[] getPThreads() throws PDIException {
Thread[] pthreads = noThreads;
lockTarget();
try {
IPDIGetInfoThreadsRequest request = session.getRequestFactory().getGetInfoThreadsRequest(
getTasks());
session.getEventRequestManager().addEventRequest(request);
String[] ids = request.getThreadIds(getTasks());
if (ids.length > 0) {
pthreads = new Thread[ids.length];
for (int i = 0; i < ids.length; i++) {
int tid = 0;
try {
tid = Integer.parseInt(ids[i]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
pthreads[i] = new Thread(session, this, tid);
}
} else {
pthreads = new Thread[] { new Thread(session, this, 0) };
}
currentThreadId = pthreads[0].getId();
if (currentThreadId == 0 && pthreads.length > 1) {
currentThreadId = pthreads[1].getId();
}
} finally {
releaseTarget();
}
return pthreads;
}
/**
* @param tid
* @return
*/
private Thread getThread(int tid) {
Thread th = null;
if (currentThreads != null) {
for (int i = 0; i < currentThreads.length; i++) {
Thread pthread = currentThreads[i];
if (pthread.getId() == tid) {
th = pthread;
break;
}
}
}
return th;
}
}