| /* |
| * (c) Copyright QNX Software Systems Ltd. 2002. |
| * All Rights Reserved. |
| * |
| */ |
| package org.eclipse.cdt.debug.mi.core.cdi.model; |
| |
| import org.eclipse.cdt.debug.core.cdi.CDIException; |
| import org.eclipse.cdt.debug.core.cdi.ICDILocation; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDISignal; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDIThread; |
| import org.eclipse.cdt.debug.mi.core.MIException; |
| import org.eclipse.cdt.debug.mi.core.MISession; |
| import org.eclipse.cdt.debug.mi.core.cdi.MI2CDIException; |
| import org.eclipse.cdt.debug.mi.core.cdi.RegisterManager; |
| import org.eclipse.cdt.debug.mi.core.cdi.Session; |
| import org.eclipse.cdt.debug.mi.core.cdi.VariableManager; |
| import org.eclipse.cdt.debug.mi.core.command.CommandFactory; |
| import org.eclipse.cdt.debug.mi.core.command.MIStackInfoDepth; |
| import org.eclipse.cdt.debug.mi.core.command.MIStackListFrames; |
| import org.eclipse.cdt.debug.mi.core.command.MIStackSelectFrame; |
| import org.eclipse.cdt.debug.mi.core.output.MIFrame; |
| import org.eclipse.cdt.debug.mi.core.output.MIInfo; |
| import org.eclipse.cdt.debug.mi.core.output.MIStackInfoDepthInfo; |
| import org.eclipse.cdt.debug.mi.core.output.MIStackListFramesInfo; |
| |
| /** |
| */ |
| public class Thread extends CObject implements ICDIThread { |
| |
| static ICDIStackFrame[] noStack = new ICDIStackFrame[0]; |
| int id; |
| ICDIStackFrame currentFrame; |
| int stackdepth = 0; |
| |
| public Thread(ICDITarget target, int threadId) { |
| super(target); |
| id = threadId; |
| } |
| |
| public int getId() { |
| return id; |
| } |
| |
| public void clearState() { |
| stackdepth = 0; |
| currentFrame = null; |
| } |
| |
| public String toString() { |
| return Integer.toString(id); |
| } |
| |
| public void updateState() { |
| try { |
| getCurrentStackFrame(); |
| } catch (CDIException e) { |
| } |
| } |
| |
| public ICDIStackFrame getCurrentStackFrame() throws CDIException { |
| if (currentFrame == null) { |
| ICDIStackFrame[] frames = getStackFrames(0, 0); |
| if (frames.length > 0) { |
| currentFrame = frames[0]; |
| } |
| } |
| return currentFrame; |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#getStackFrames() |
| */ |
| public ICDIStackFrame[] getStackFrames() throws CDIException { |
| int depth = 0; |
| ICDIStackFrame[] stacks = noStack; |
| Session session = (Session)getTarget().getSession(); |
| Target currentTarget = (Target)session.getCurrentTarget(); |
| ICDIThread currentThread = currentTarget.getCurrentThread(); |
| currentTarget.setCurrentThread(this, false); |
| try { |
| MISession mi = session.getMISession(); |
| CommandFactory factory = mi.getCommandFactory(); |
| MIStackListFrames frames = factory.createMIStackListFrames(); |
| depth = getStackFrameCount(); |
| mi.postCommand(frames); |
| MIStackListFramesInfo info = frames.getMIStackListFramesInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| MIFrame[] miFrames = info.getMIFrames(); |
| stacks = new StackFrame[miFrames.length]; |
| for (int i = 0; i < stacks.length; i++) { |
| stacks[i] = new StackFrame(this, miFrames[i], depth - miFrames[i].getLevel()); |
| } |
| } catch (MIException e) { |
| //throw new CDIException(e.getMessage()); |
| //System.out.println(e); |
| } catch (CDIException e) { |
| //throw e; |
| //System.out.println(e); |
| } finally { |
| currentTarget.setCurrentThread(currentThread, false); |
| } |
| if (currentFrame == null) { |
| for (int i = 0; i < stacks.length; i++) { |
| if (stacks[i].getLevel() == depth) { |
| currentFrame = stacks[i]; |
| } |
| } |
| } |
| return stacks; |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#getStackFrames() |
| */ |
| public int getStackFrameCount() throws CDIException { |
| if (stackdepth == 0) { |
| Session session = (Session)(getTarget().getSession()); |
| Target currentTarget = (Target)session.getCurrentTarget(); |
| ICDIThread currentThread = currentTarget.getCurrentThread(); |
| currentTarget.setCurrentThread(this, false); |
| try { |
| MISession mi = session.getMISession(); |
| CommandFactory factory = mi.getCommandFactory(); |
| MIStackInfoDepth depth = factory.createMIStackInfoDepth(); |
| mi.postCommand(depth); |
| MIStackInfoDepthInfo info = null; |
| try { |
| // Catch the first exception gdb can recover the second time. |
| info = depth.getMIStackInfoDepthInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| stackdepth = info.getDepth(); |
| } catch (MIException e) { |
| // First try fails, retry. gdb patches up the corrupt frame |
| // so retry should give us a frame count that is safe. |
| mi.postCommand(depth); |
| info = depth.getMIStackInfoDepthInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| stackdepth = info.getDepth(); |
| if (stackdepth > 0) { |
| stackdepth--; |
| } |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } finally { |
| currentTarget.setCurrentThread(currentThread, false); |
| } |
| } |
| return stackdepth; |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#getStackFrames() |
| */ |
| public ICDIStackFrame[] getStackFrames(int low, int high) throws CDIException { |
| ICDIStackFrame[] stacks = noStack; |
| Session session = (Session)getTarget().getSession(); |
| Target currentTarget = (Target)session.getCurrentTarget(); |
| ICDIThread currentThread = currentTarget.getCurrentThread(); |
| currentTarget.setCurrentThread(this, false); |
| try { |
| MISession mi = session.getMISession(); |
| CommandFactory factory = mi.getCommandFactory(); |
| MIStackListFrames frames = factory.createMIStackListFrames(low, high); |
| int depth = getStackFrameCount(); |
| mi.postCommand(frames); |
| MIStackListFramesInfo info = frames.getMIStackListFramesInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| MIFrame[] miFrames = info.getMIFrames(); |
| stacks = new StackFrame[miFrames.length]; |
| for (int i = 0; i < stacks.length; i++) { |
| stacks[i] = new StackFrame(this, miFrames[i], depth - miFrames[i].getLevel()); |
| } |
| } catch (MIException e) { |
| //throw new CDIException(e.getMessage()); |
| //System.out.println(e); |
| } catch (CDIException e) { |
| //throw e; |
| //System.out.println(e); |
| } finally { |
| currentTarget.setCurrentThread(currentThread, false); |
| } |
| if (currentFrame == null) { |
| for (int i = 0; i < stacks.length; i++) { |
| StackFrame f = (StackFrame)stacks[i]; |
| if (f.getMIFrame().getLevel() == 0) { |
| currentFrame = stacks[i]; |
| } |
| } |
| } |
| return stacks; |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#setCurrentStackFrame(ICDIStackFrame) |
| */ |
| public void setCurrentStackFrame(ICDIStackFrame stackframe) throws CDIException { |
| setCurrentStackFrame(stackframe, true); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#setCurrentStackFrame(ICDIStackFrame, boolean) |
| */ |
| public void setCurrentStackFrame(ICDIStackFrame stackframe, boolean doUpdate) throws CDIException { |
| int frameLevel = 0; |
| if (stackframe != null) { |
| frameLevel = stackframe.getLevel(); |
| } |
| |
| // Check to see if we are already at this level |
| ICDIStackFrame current = getCurrentStackFrame(); |
| if (current != null && current.getLevel() == frameLevel) { |
| // noop |
| return; |
| } |
| |
| try { |
| Session session = (Session)getTarget().getSession(); |
| MISession mi = session.getMISession(); |
| CommandFactory factory = mi.getCommandFactory(); |
| // Need the GDB/MI view of level which is the reverse, i.e. the highest level is 0 |
| // See comment in StackFrame constructor. |
| int miLevel = getStackFrameCount() - frameLevel; |
| MIStackSelectFrame frame = factory.createMIStackSelectFrame(miLevel); |
| // Set ourself as the current thread first. |
| ((Target)getTarget()).setCurrentThread(this, doUpdate); |
| mi.postCommand(frame); |
| MIInfo info = frame.getMIInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| currentFrame = stackframe; |
| // Resetting stackframe may change the value of |
| // some variables like registers. Call an update() |
| // To generate changeEvents. |
| if (doUpdate) { |
| RegisterManager regMgr = (RegisterManager)session.getRegisterManager(); |
| if (regMgr.isAutoUpdate()) { |
| regMgr.update(); |
| } |
| VariableManager varMgr = (VariableManager)session.getVariableManager(); |
| if (varMgr.isAutoUpdate()) { |
| varMgr.update(); |
| } |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#isSuspended() |
| */ |
| public boolean isSuspended() { |
| return getTarget().isSuspended(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#resume() |
| */ |
| public void resume() throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().resume(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#stepInto() |
| */ |
| public void stepInto() throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().stepInto(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#stepIntoInstruction() |
| */ |
| public void stepIntoInstruction() throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().stepIntoInstruction(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#stepOver() |
| */ |
| public void stepOver() throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().stepOver(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#stepOverInstruction() |
| */ |
| public void stepOverInstruction() throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().stepOverInstruction(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#stepReturn() |
| */ |
| public void stepReturn() throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().stepReturn(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#stepReturn(boolean) |
| */ |
| public void stepReturn(boolean execute) throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().stepReturn(execute); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#runUntil(ICDILocation) |
| */ |
| public void runUntil(ICDILocation location) throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().runUntil(location); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#suspend() |
| */ |
| public void suspend() throws CDIException { |
| getTarget().suspend(); |
| getTarget().setCurrentThread(this); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#jump(org.eclipse.cdt.debug.core.cdi.ICDILocation) |
| */ |
| public void jump(ICDILocation location) throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().jump(location); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#signal() |
| */ |
| public void signal() throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().signal(); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#signal(org.eclipse.cdt.debug.core.cdi.model.ICDISignal) |
| */ |
| public void signal(ICDISignal signal) throws CDIException { |
| getTarget().setCurrentThread(this); |
| getTarget().signal(signal); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.model.ICDIThread#equals(ICDIThread) |
| */ |
| public boolean equals(ICDIThread thread) { |
| if (thread instanceof Thread) { |
| Thread cthread = (Thread) thread; |
| return id == cthread.getId(); |
| } |
| return super.equals(thread); |
| } |
| |
| } |