| /* |
| *(c) Copyright QNX Software Systems Ltd. 2002. |
| * All Rights Reserved. |
| * |
| */ |
| package org.eclipse.cdt.debug.mi.core.cdi; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.cdt.debug.core.cdi.CDIException; |
| import org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager; |
| import org.eclipse.cdt.debug.core.cdi.ICDICatchEvent; |
| import org.eclipse.cdt.debug.core.cdi.ICDICondition; |
| import org.eclipse.cdt.debug.core.cdi.ICDILocation; |
| import org.eclipse.cdt.debug.core.cdi.ICDISharedLibraryManager; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDIBreakpoint; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDICatchpoint; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDILocationBreakpoint; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; |
| import org.eclipse.cdt.debug.core.cdi.model.ICDIWatchpoint; |
| import org.eclipse.cdt.debug.mi.core.MIException; |
| import org.eclipse.cdt.debug.mi.core.MISession; |
| import org.eclipse.cdt.debug.mi.core.cdi.model.Breakpoint; |
| import org.eclipse.cdt.debug.mi.core.cdi.model.Target; |
| import org.eclipse.cdt.debug.mi.core.cdi.model.Watchpoint; |
| import org.eclipse.cdt.debug.mi.core.command.CommandFactory; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakAfter; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakCondition; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakDelete; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakDisable; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakEnable; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakInsert; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakList; |
| import org.eclipse.cdt.debug.mi.core.command.MIBreakWatch; |
| import org.eclipse.cdt.debug.mi.core.event.MIBreakpointChangedEvent; |
| import org.eclipse.cdt.debug.mi.core.event.MIBreakpointCreatedEvent; |
| import org.eclipse.cdt.debug.mi.core.event.MIBreakpointDeletedEvent; |
| import org.eclipse.cdt.debug.mi.core.event.MIEvent; |
| import org.eclipse.cdt.debug.mi.core.output.MIBreakInsertInfo; |
| import org.eclipse.cdt.debug.mi.core.output.MIBreakListInfo; |
| import org.eclipse.cdt.debug.mi.core.output.MIBreakWatchInfo; |
| import org.eclipse.cdt.debug.mi.core.output.MIBreakpoint; |
| import org.eclipse.cdt.debug.mi.core.output.MIInfo; |
| |
| /** |
| * Breakpoint Manager for the CDI interface. |
| */ |
| public class BreakpointManager extends SessionObject implements ICDIBreakpointManager { |
| |
| List breakList; |
| List deferredList; |
| boolean allowInterrupt; |
| boolean autoupdate; |
| |
| public BreakpointManager(Session session) { |
| super(session); |
| breakList = Collections.synchronizedList(new ArrayList()); |
| deferredList = Collections.synchronizedList(new ArrayList()); |
| allowInterrupt = true; |
| autoupdate = false; |
| } |
| |
| public MIBreakpoint[] getMIBreakpoints() throws CDIException { |
| Session s = (Session)getSession(); |
| CommandFactory factory = s.getMISession().getCommandFactory(); |
| MIBreakList breakpointList = factory.createMIBreakList(); |
| try { |
| s.getMISession().postCommand(breakpointList); |
| MIBreakListInfo info = breakpointList.getMIBreakListInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| return info.getMIBreakpoints(); |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } |
| } |
| |
| boolean hasBreakpointChanged(Breakpoint point, MIBreakpoint miBreakpoint) { |
| MIBreakpoint miBreak = point.getMIBreakpoint(); |
| return miBreak.isEnabled() != miBreakpoint.isEnabled() || |
| !miBreak.getCondition().equals(miBreakpoint.getCondition()) || |
| miBreak.getIgnoreCount() != miBreakpoint.getIgnoreCount(); |
| } |
| |
| public Breakpoint getBreakpoint(int number) { |
| Breakpoint[] bkpts = (Breakpoint[]) breakList.toArray(new Breakpoint[0]); |
| for (int i = 0; i < bkpts.length; i++) { |
| MIBreakpoint miBreak = bkpts[i].getMIBreakpoint(); |
| if (miBreak.getNumber() == number) { |
| return bkpts[i]; |
| } |
| } |
| return null; |
| } |
| |
| public Watchpoint getWatchpoint(int number) { |
| return (Watchpoint)getBreakpoint(number); |
| } |
| |
| boolean suspendInferior(ICDITarget target) throws CDIException { |
| boolean shouldRestart = false; |
| // Stop the program |
| if (allowInterrupt) { |
| if (target instanceof Target) { |
| Target ctarget = (Target)target; |
| // Disable events. |
| if (ctarget.isRunning()) { |
| ctarget.suspend(); |
| shouldRestart = true; |
| } |
| } else if (!target.isSuspended()) { |
| target.suspend(); |
| shouldRestart = true; |
| } |
| } |
| return shouldRestart; |
| } |
| |
| void resumeInferior(ICDITarget target, boolean shouldRestart) throws CDIException { |
| if (shouldRestart) { |
| target.resume(); |
| } |
| } |
| |
| public void deleteBreakpoint (int no) { |
| Breakpoint[] points = (Breakpoint[]) breakList.toArray(new Breakpoint[0]); |
| for (int i = 0; i < points.length; i++) { |
| if (points[i].getMIBreakpoint().getNumber() == no) { |
| breakList.remove(points[i]); |
| break; |
| } |
| } |
| } |
| |
| public void enableBreakpoint(ICDIBreakpoint breakpoint) throws CDIException { |
| int number = 0; |
| if (breakpoint instanceof Breakpoint |
| && breakList.contains(breakpoint)) { |
| number = ((Breakpoint) breakpoint).getMIBreakpoint().getNumber(); |
| } else { |
| throw new CDIException("Not a CDT breakpoint"); |
| } |
| boolean state = suspendInferior(breakpoint.getTarget()); |
| Session session = (Session)getSession(); |
| CommandFactory factory = session.getMISession().getCommandFactory(); |
| MIBreakEnable breakEnable = factory.createMIBreakEnable(new int[] { number }); |
| try { |
| session.getMISession().postCommand(breakEnable); |
| MIInfo info = breakEnable.getMIInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } finally { |
| // Resume the program and enable events. |
| resumeInferior(breakpoint.getTarget(), state); |
| } |
| ((Breakpoint) breakpoint).getMIBreakpoint().setEnabled(true); |
| // Fire a changed Event. |
| MISession mi = session.getMISession(); |
| mi.fireEvent(new MIBreakpointChangedEvent(((Breakpoint)breakpoint).getMIBreakpoint().getNumber())); |
| } |
| |
| public void disableBreakpoint(ICDIBreakpoint breakpoint) throws CDIException { |
| int number = 0; |
| if (breakpoint instanceof Breakpoint |
| && breakList.contains(breakpoint)) { |
| number = ((Breakpoint) breakpoint).getMIBreakpoint().getNumber(); |
| } else { |
| throw new CDIException("Not a CDT breakpoint"); |
| } |
| |
| Session session = (Session)getSession(); |
| boolean state = suspendInferior(breakpoint.getTarget()); |
| CommandFactory factory = session.getMISession().getCommandFactory(); |
| MIBreakDisable breakDisable = |
| factory.createMIBreakDisable(new int[] { number }); |
| try { |
| session.getMISession().postCommand(breakDisable); |
| MIInfo info = breakDisable.getMIInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } finally { |
| resumeInferior(breakpoint.getTarget(), state); |
| } |
| ((Breakpoint) breakpoint).getMIBreakpoint().setEnabled(false); |
| // Fire a changed Event. |
| MISession mi = session.getMISession(); |
| mi.fireEvent(new MIBreakpointChangedEvent(((Breakpoint)breakpoint).getMIBreakpoint().getNumber())); |
| } |
| |
| public void setCondition(ICDIBreakpoint breakpoint, ICDICondition condition) throws CDIException { |
| int number = 0; |
| if (breakpoint instanceof Breakpoint |
| && breakList.contains(breakpoint)) { |
| number = ((Breakpoint) breakpoint).getMIBreakpoint().getNumber(); |
| } else { |
| throw new CDIException("Not a CDT breakpoint"); |
| } |
| |
| Session session = (Session)getSession(); |
| boolean state = suspendInferior(breakpoint.getTarget()); |
| CommandFactory factory = session.getMISession().getCommandFactory(); |
| |
| // reset the values to sane states. |
| String exprCond = condition.getExpression(); |
| if (exprCond == null) { |
| exprCond = ""; |
| } |
| int ignoreCount = condition.getIgnoreCount(); |
| if (ignoreCount < 0) { |
| ignoreCount = 0; |
| } |
| |
| try { |
| MIBreakCondition breakCondition = |
| factory.createMIBreakCondition(number, exprCond); |
| session.getMISession().postCommand(breakCondition); |
| MIInfo info = breakCondition.getMIInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| MIBreakAfter breakAfter = |
| factory.createMIBreakAfter(number, ignoreCount); |
| session.getMISession().postCommand(breakAfter); |
| info = breakAfter.getMIInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } finally { |
| resumeInferior(breakpoint.getTarget(), state); |
| } |
| // Fire a changed Event. |
| MISession mi = session.getMISession(); |
| mi.fireEvent(new MIBreakpointChangedEvent(((Breakpoint)breakpoint).getMIBreakpoint().getNumber())); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#update() |
| */ |
| public void update() throws CDIException { |
| MIBreakpoint[] newMIBreakpoints = getMIBreakpoints(); |
| List eventList = new ArrayList(newMIBreakpoints.length); |
| for (int i = 0; i < newMIBreakpoints.length; i++) { |
| int no = newMIBreakpoints[i].getNumber(); |
| Breakpoint bp = getBreakpoint(no); |
| if (bp != null) { |
| if (hasBreakpointChanged(bp, newMIBreakpoints[i])) { |
| // Fire ChangedEvent |
| bp.setMIBreakpoint(newMIBreakpoints[i]); |
| eventList.add(new MIBreakpointChangedEvent(no)); |
| } else { |
| eventList.add(new MIBreakpointCreatedEvent(no)); |
| } |
| } else { |
| // add the new breakpoint and fire CreatedEvent |
| if (newMIBreakpoints[i].isWatchpoint()) { |
| breakList.add(new Watchpoint(this, newMIBreakpoints[i])); |
| } else { |
| breakList.add(new Breakpoint(this, newMIBreakpoints[i])); |
| } |
| eventList.add(new MIBreakpointCreatedEvent(no)); |
| } |
| } |
| // Check if any breakpoint was removed. |
| Breakpoint[] oldBreakpoints = (Breakpoint[]) breakList.toArray(new Breakpoint[0]); |
| for (int i = 0; i < oldBreakpoints.length; i++) { |
| boolean found = false; |
| int no = oldBreakpoints[i].getMIBreakpoint().getNumber(); |
| for (int j = 0; j < newMIBreakpoints.length; j++) { |
| if (no == newMIBreakpoints[j].getNumber()) { |
| found = true; |
| break; |
| } |
| } |
| if (!found) { |
| // Fire destroyed Events. |
| eventList.add(new MIBreakpointDeletedEvent(no)); |
| } |
| } |
| MISession mi = ((Session)getSession()).getMISession(); |
| MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]); |
| mi.fireEvents(events); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#allowProgramInterruption() |
| */ |
| public void allowProgramInterruption(boolean e) { |
| allowInterrupt = e; |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#deleteAllBreakpoints() |
| */ |
| public void deleteAllBreakpoints() throws CDIException { |
| deleteBreakpoints(getBreakpoints()); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#deleteBreakpoint(ICDIBreakpoint) |
| */ |
| public void deleteBreakpoint(ICDIBreakpoint breakpoint) throws CDIException { |
| deleteBreakpoints(new ICDIBreakpoint[] { breakpoint }); |
| } |
| |
| public void deleteFromDeferredList(Breakpoint bkpt) { |
| deferredList.remove(bkpt); |
| } |
| |
| public void addToBreakpointList(Breakpoint bkpt) { |
| breakList.add(bkpt); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#deleteBreakpoints(ICDIBreakpoint[]) |
| */ |
| public void deleteBreakpoints(ICDIBreakpoint[] breakpoints) throws CDIException { |
| int[] numbers = new int[breakpoints.length]; |
| for (int i = 0; i < numbers.length; i++) { |
| if (breakpoints[i] instanceof Breakpoint |
| && breakList.contains(breakpoints[i])) { |
| numbers[i] = |
| ((Breakpoint) breakpoints[i]).getMIBreakpoint().getNumber(); |
| } else { |
| throw new CDIException("Not a CDT breakpoint"); |
| } |
| } |
| Session session = (Session)getSession(); |
| boolean state = suspendInferior(session.getCurrentTarget()); |
| CommandFactory factory = session.getMISession().getCommandFactory(); |
| MIBreakDelete breakDelete = factory.createMIBreakDelete(numbers); |
| try { |
| session.getMISession().postCommand(breakDelete); |
| MIInfo info = breakDelete.getMIInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } finally { |
| resumeInferior(session.getCurrentTarget(), state); |
| } |
| List eventList = new ArrayList(breakpoints.length); |
| for (int i = 0; i < breakpoints.length; i++) { |
| int no = ((Breakpoint)breakpoints[i]).getMIBreakpoint().getNumber(); |
| eventList.add(new MIBreakpointDeletedEvent(no)); |
| } |
| MISession mi = session.getMISession(); |
| MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]); |
| mi.fireEvents(events); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#getBreakpoints() |
| */ |
| public ICDIBreakpoint[] getBreakpoints() throws CDIException { |
| return (ICDIBreakpoint[]) breakList.toArray(new ICDIBreakpoint[0]); |
| } |
| |
| public ICDIBreakpoint[] getDeferredBreakpoints() throws CDIException { |
| return (ICDIBreakpoint[]) deferredList.toArray(new ICDIBreakpoint[0]); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setCatchpoint(int, ICDICatchEvent, String, ICDICondition, boolean) |
| */ |
| public ICDICatchpoint setCatchpoint( int type, ICDICatchEvent event, String expression, |
| ICDICondition condition) throws CDIException { |
| throw new CDIException("Not Supported"); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setLocationBreakpoint(int, ICDILocation, ICDICondition, boolean, String) |
| */ |
| public ICDILocationBreakpoint setLocationBreakpoint(int type, ICDILocation location, |
| ICDICondition condition, String threadId) throws CDIException { |
| return setLocationBreakpoint(type, location, condition, threadId, false); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setLocationBreakpoint(int, ICDILocation, ICDICondition, boolean, String) |
| */ |
| public ICDILocationBreakpoint setLocationBreakpoint(int type, ICDILocation location, |
| ICDICondition condition, String threadId, boolean deferred) throws CDIException { |
| |
| Breakpoint bkpt = new Breakpoint(this, type, location, condition, threadId); |
| try { |
| setLocationBreakpoint(bkpt); |
| breakList.add(bkpt); |
| |
| // Fire a created Event. |
| Session session = (Session)getSession(); |
| MISession mi = session.getMISession(); |
| mi.fireEvent(new MIBreakpointCreatedEvent(bkpt.getMIBreakpoint().getNumber())); |
| } catch (CDIException e) { |
| if (!deferred) { |
| throw e; |
| } else { |
| Session session = (Session)getSession(); |
| ICDISharedLibraryManager sharedMgr = session.getSharedLibraryManager(); |
| if (sharedMgr instanceof SharedLibraryManager) { |
| SharedLibraryManager mgr = (SharedLibraryManager)sharedMgr; |
| if (mgr.isDeferredBreakpoint()) { |
| deferredList.add(bkpt); |
| } else { |
| throw e; |
| } |
| } |
| } |
| } |
| return bkpt; |
| } |
| |
| MIBreakInsert createMIBreakInsert(Breakpoint bkpt) throws CDIException { |
| boolean hardware = bkpt.isHardware(); |
| boolean temporary = bkpt.isTemporary(); |
| String exprCond = null; |
| int ignoreCount = 0; |
| StringBuffer line = new StringBuffer(); |
| |
| if (bkpt.getCondition() != null) { |
| ICDICondition condition = bkpt.getCondition(); |
| exprCond = condition.getExpression(); |
| ignoreCount = condition.getIgnoreCount(); |
| } |
| |
| if (bkpt.getLocation() != null) { |
| ICDILocation location = bkpt.getLocation(); |
| String file = location.getFile(); |
| String function = location.getFunction(); |
| if (file != null && file.length() > 0) { |
| line.append(file).append(':'); |
| if (function != null && function.length() > 0) { |
| line.append(function); |
| } else { |
| line.append(location.getLineNumber()); |
| } |
| } else if (function != null && function.length() > 0) { |
| line.append(function); |
| } else if (location.getLineNumber() != 0) { |
| line.append(location.getLineNumber()); |
| } else { |
| line.append('*').append(location.getAddress()); |
| } |
| } |
| Session session = (Session)getSession(); |
| CommandFactory factory = session.getMISession().getCommandFactory(); |
| return factory.createMIBreakInsert(temporary, hardware, exprCond, ignoreCount, line.toString()); |
| } |
| |
| public void setLocationBreakpoint (Breakpoint bkpt) throws CDIException { |
| Session session = (Session)getSession(); |
| boolean state = suspendInferior(session.getCurrentTarget()); |
| MIBreakInsert breakInsert = createMIBreakInsert(bkpt); |
| MIBreakpoint[] points = null; |
| try { |
| session.getMISession().postCommand(breakInsert); |
| MIBreakInsertInfo info = breakInsert.getMIBreakInsertInfo(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| points = info.getMIBreakpoints(); |
| if (points == null || points.length == 0) { |
| throw new CDIException("Error parsing"); |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } finally { |
| resumeInferior(session.getCurrentTarget(), state); |
| } |
| |
| bkpt.setMIBreakpoint(points[0]); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setWatchpoint(int, int, String, ICDICondition, boolean) |
| */ |
| public ICDIWatchpoint setWatchpoint( int type, int watchType, String expression, |
| ICDICondition condition) throws CDIException { |
| boolean access = ( (watchType & ICDIWatchpoint.WRITE) == ICDIWatchpoint.WRITE && |
| (watchType & ICDIWatchpoint.READ) == ICDIWatchpoint.READ ); |
| boolean read = ( !((watchType & ICDIWatchpoint.WRITE) == ICDIWatchpoint.WRITE) && |
| (watchType & ICDIWatchpoint.READ) == ICDIWatchpoint.READ ); |
| |
| Session session = (Session)getSession(); |
| boolean state = suspendInferior(session.getCurrentTarget()); |
| CommandFactory factory = session.getMISession().getCommandFactory(); |
| MIBreakWatch breakWatch = |
| factory.createMIBreakWatch(access, read, expression); |
| MIBreakpoint[] points = null; |
| try { |
| session.getMISession().postCommand(breakWatch); |
| MIBreakWatchInfo info = breakWatch.getMIBreakWatchInfo(); |
| points = info.getMIBreakpoints(); |
| if (info == null) { |
| throw new CDIException("No answer"); |
| } |
| if (points == null || points.length == 0) { |
| throw new CDIException("Parsing Error"); |
| } |
| } catch (MIException e) { |
| throw new MI2CDIException(e); |
| } finally { |
| resumeInferior(session.getCurrentTarget(), state); |
| } |
| Watchpoint bkpt = new Watchpoint(this, points[0]); |
| breakList.add(bkpt); |
| |
| // Fire a created Event. |
| MISession mi = session.getMISession(); |
| mi.fireEvent(new MIBreakpointCreatedEvent(bkpt.getMIBreakpoint().getNumber())); |
| return bkpt; |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#createCondition(int, String) |
| */ |
| public ICDICondition createCondition(int ignoreCount, String expression) { |
| return new Condition(ignoreCount, expression); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#createLocation(String, String, int) |
| */ |
| public ICDILocation createLocation(String file, String function, int line) { |
| return new Location(file, function, line); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#createLocation(long) |
| */ |
| public ICDILocation createLocation(long address) { |
| return new Location(address); |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#isAutoUpdate() |
| */ |
| public boolean isAutoUpdate() { |
| return autoupdate; |
| } |
| |
| /** |
| * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setAutoUpdate(boolean) |
| */ |
| public void setAutoUpdate(boolean update) { |
| autoupdate = update; |
| } |
| |
| } |