/******************************************************************************* * Copyright (c) 2000, 2005 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 *******************************************************************************/ package org.eclipse.cdt.debug.mi.core.cdi.model; import java.math.BigInteger; import java.util.HashMap; import org.eclipse.cdt.debug.core.cdi.CDIException; import org.eclipse.cdt.debug.core.cdi.ICDILocator; import org.eclipse.cdt.debug.core.cdi.model.ICDIArgument; import org.eclipse.cdt.debug.core.cdi.model.ICDIArgumentDescriptor; import org.eclipse.cdt.debug.core.cdi.model.ICDILocalVariable; import org.eclipse.cdt.debug.core.cdi.model.ICDILocalVariableDescriptor; import org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame; import org.eclipse.cdt.debug.core.cdi.model.ICDIThread; import org.eclipse.cdt.debug.core.cdi.model.ICDIValue; import org.eclipse.cdt.debug.core.cdi.model.type.ICDIType; import org.eclipse.cdt.debug.mi.core.MIException; import org.eclipse.cdt.debug.mi.core.MIFormat; import org.eclipse.cdt.debug.mi.core.MISession; import org.eclipse.cdt.debug.mi.core.cdi.CdiResources; import org.eclipse.cdt.debug.mi.core.cdi.Locator; import org.eclipse.cdt.debug.mi.core.cdi.MI2CDIException; 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.MIExecFinish; import org.eclipse.cdt.debug.mi.core.command.MIExecReturn; import org.eclipse.cdt.debug.mi.core.output.MIFrame; import org.eclipse.cdt.debug.mi.core.output.MIInfo; /** */ public class StackFrame extends CObject implements ICDIStackFrame { MIFrame frame; Thread cthread; int level; ICDIArgumentDescriptor[] argDescs; ICDILocalVariableDescriptor[] localDescs; Locator fLocator; /** * */ private HashMap fTypeCache; /* * GDB/MI does not keep the stack level, from what we expect. In gdb, the highest stack is level 0 and lower stack as the highest level: -stack-list-frames ^done,stack=[frame={level="0 ",addr="0x0804845b",func="main",file="hello.c",line="24"}, frame={level="1 ",addr="0x42017499",func="__libc_start_main",from="/lib/i686/libc.so.6"}] -stack-list-frames ^done,stack=[frame={level="0 ",addr="0x08048556",func="main2",file="hello.c",line="58"}, frame={level="1 ",addr="0x08048501",func="main",file="hello.c",line="41"}, frame={level="2 ",addr="0x42017499",func="__libc_start_main",from="/lib/i686/libc.so.6"}] This is of no use to us since the level is always "0". The level is necessary for example when doing recursive calls to make a distinction between frames. So in CDT this reverse the hidghest frame will have the highest number. In CDT: stack=[frame={level="2 ",addr="0x0804845b",func="main",file="hello.c",line="24"}, frame={level="1 ",addr="0x42017499",func="__libc_start_main",from="/lib/i686/libc.so.6"}] stack=[frame={level="3 ",addr="0x08048556",func="main2",file="hello.c",line="58"}, frame={level="2 ",addr="0x08048501",func="main",file="hello.c",line="41"}, frame={level="1 ",addr="0x42017499",func="__libc_start_main",from="/lib/i686/libc.so.6"}] */ public StackFrame(Thread thread, MIFrame f, int l) { super((Target)thread.getTarget()); cthread = thread; frame = f; level = l; fTypeCache = new HashMap(); } public MIFrame getMIFrame() { return frame; } public ICDIType getFromTypeCache(String typeName) { return (ICDIType)fTypeCache.get(typeName); } public void addToTypeCache(String typeName, ICDIType typeDefinition) { fTypeCache.put(typeName, typeDefinition); } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#getThread() */ public ICDIThread getThread() { return cthread; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#getArgumentDescriptors() */ public ICDIArgumentDescriptor[] getArgumentDescriptors() throws CDIException { if (argDescs == null) { Session session = (Session)getTarget().getSession(); VariableManager mgr = session.getVariableManager(); argDescs = mgr.getArgumentDescriptors(this); } return argDescs; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#getLocalVariableDescriptors() */ public ICDILocalVariableDescriptor[] getLocalVariableDescriptors() throws CDIException { if (localDescs == null) { Session session = (Session)getTarget().getSession(); VariableManager mgr = session.getVariableManager(); localDescs = mgr.getLocalVariableDescriptors(this); } return localDescs; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#createArgument(org.eclipse.cdt.debug.core.cdi.model.ICDIArgumentDescriptor) */ public ICDIArgument createArgument(ICDIArgumentDescriptor varDesc) throws CDIException { if (varDesc instanceof ArgumentDescriptor) { Session session = (Session)getTarget().getSession(); VariableManager mgr = session.getVariableManager(); return mgr.createArgument((ArgumentDescriptor)varDesc); } return null; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#createLocalVariable(org.eclipse.cdt.debug.core.cdi.model.ICDILocalVariableDescriptor) */ public ICDILocalVariable createLocalVariable(ICDILocalVariableDescriptor varDesc) throws CDIException { if (varDesc instanceof ArgumentDescriptor) { return createArgument((ICDIArgumentDescriptor)varDesc); } else if (varDesc instanceof LocalVariableDescriptor) { Session session = (Session)getTarget().getSession(); VariableManager mgr = session.getVariableManager(); return mgr.createLocalVariable((LocalVariableDescriptor)varDesc); } return null; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#getLocation() */ public ICDILocator getLocator() { BigInteger addr = BigInteger.ZERO; if (frame != null) { if (fLocator == null) { String a = frame.getAddress(); if (a != null) { addr = MIFormat.getBigInteger(a); } fLocator = new Locator(frame.getFile(), frame.getFunction(), frame.getLine(), addr); } return fLocator; } return new Locator("", "", 0, addr); //$NON-NLS-1$ //$NON-NLS-2$ } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#getLevel() */ public int getLevel() { return level; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame#equals(ICDIStackFrame) */ public boolean equals(ICDIStackFrame stackframe) { if (stackframe instanceof StackFrame) { StackFrame stack = (StackFrame)stackframe; boolean equal = cthread != null && cthread.equals(stack.getThread()) && getLevel() == stack.getLevel(); if (equal) { ICDILocator otherLocator = stack.getLocator(); ICDILocator myLocator = getLocator(); if (Locator.equalString(myLocator.getFile(), otherLocator.getFile())) { if (Locator.equalString(myLocator.getFunction(), otherLocator.getFunction())) { return true; } } } } return super.equals(stackframe); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIExecuteStepReturn#stepReturn() */ public void stepReturn() throws CDIException { finish(); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIExecuteStepReturn#stepReturn(org.eclipse.cdt.debug.core.cdi.model.ICDIValue) */ public void stepReturn(ICDIValue value) throws CDIException { execReturn(value.toString()); } /** */ protected void finish() throws CDIException { ((Thread)getThread()).setCurrentStackFrame(this, false); Target target = (Target)getTarget(); MISession miSession = target.getMISession(); CommandFactory factory = miSession.getCommandFactory(); MIExecFinish finish = factory.createMIExecFinish(); try { miSession.postCommand(finish); MIInfo info = finish.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.model.Target.Target_not_responding")); //$NON-NLS-1$ } } catch (MIException e) { throw new MI2CDIException(e); } } /** */ protected void execReturn(String value) throws CDIException { ((Thread)getThread()).setCurrentStackFrame(this, false); Target target = (Target)getTarget(); MISession miSession = target.getMISession(); CommandFactory factory = miSession.getCommandFactory(); MIExecReturn ret; if (value == null) { ret = factory.createMIExecReturn(); } else { ret = factory.createMIExecReturn(value); } try { miSession.postCommand(ret); MIInfo info = ret.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.model.Target.Target_not_responding")); //$NON-NLS-1$ } } catch (MIException e) { throw new MI2CDIException(e); } } }