/******************************************************************************* * Copyright (c) 2000, 2010 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 * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.debug.mi.core.cdi; import java.io.File; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.cdt.debug.core.cdi.CDIException; import org.eclipse.cdt.debug.core.cdi.ICDIAddressLocation; import org.eclipse.cdt.debug.core.cdi.ICDICondition; import org.eclipse.cdt.debug.core.cdi.ICDIFunctionLocation; import org.eclipse.cdt.debug.core.cdi.ICDILineLocation; import org.eclipse.cdt.debug.core.cdi.ICDILocator; import org.eclipse.cdt.debug.core.cdi.model.ICDIAddressBreakpoint; import org.eclipse.cdt.debug.core.cdi.model.ICDIBreakpoint; import org.eclipse.cdt.debug.core.cdi.model.ICDIEventBreakpoint; import org.eclipse.cdt.debug.core.cdi.model.ICDIExceptionpoint; import org.eclipse.cdt.debug.core.cdi.model.ICDIFunctionBreakpoint; import org.eclipse.cdt.debug.core.cdi.model.ICDILineBreakpoint; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.cdt.debug.core.cdi.model.ICDIWatchpoint; import org.eclipse.cdt.debug.core.model.ICBreakpointType; import org.eclipse.cdt.debug.mi.core.MIException; import org.eclipse.cdt.debug.mi.core.MIFormat; import org.eclipse.cdt.debug.mi.core.MIPlugin; import org.eclipse.cdt.debug.mi.core.MISession; import org.eclipse.cdt.debug.mi.core.cdi.model.AddressBreakpoint; import org.eclipse.cdt.debug.mi.core.cdi.model.AddressLocation; import org.eclipse.cdt.debug.mi.core.cdi.model.Breakpoint; import org.eclipse.cdt.debug.mi.core.cdi.model.EventBreakpoint; import org.eclipse.cdt.debug.mi.core.cdi.model.Exceptionpoint; import org.eclipse.cdt.debug.mi.core.cdi.model.FunctionBreakpoint; import org.eclipse.cdt.debug.mi.core.cdi.model.FunctionLocation; import org.eclipse.cdt.debug.mi.core.cdi.model.LineBreakpoint; import org.eclipse.cdt.debug.mi.core.cdi.model.LocationBreakpoint; 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.CLICatch; 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.command.MIGDBSetBreakpointPending; 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.CLICatchInfo; 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 Manager { public static ICDIBreakpoint[] EMPTY_BREAKPOINTS = {}; Map breakMap; Map deferredMap; boolean allowInterrupt; public BreakpointManager(Session session) { super(session, false); breakMap = Collections.synchronizedMap(new HashMap()); deferredMap = Collections.synchronizedMap(new HashMap()); allowInterrupt = true; } synchronized List getBreakpointsList(ICDITarget target) { List bList = (List)breakMap.get(target); if (bList == null) { bList = Collections.synchronizedList(new ArrayList()); breakMap.put(target, bList); } return bList; } MIBreakpoint[] getAllMIBreakpoints(MISession miSession) throws CDIException { CommandFactory factory = miSession.getCommandFactory(); MIBreakList breakpointList = factory.createMIBreakList(); try { miSession.postCommand(breakpointList); MIBreakListInfo info = breakpointList.getMIBreakListInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } return info.getMIBreakpoints(); } catch (MIException e) { throw new MI2CDIException(e); } } boolean hasBreakpointChanged(MIBreakpoint miBreak, MIBreakpoint miBreakpoint) { return miBreak.isEnabled() != miBreakpoint.isEnabled() || !miBreak.getCondition().equals(miBreakpoint.getCondition()) || miBreak.getIgnoreCount() != miBreakpoint.getIgnoreCount(); } public Watchpoint getWatchpoint(MISession miSession, int number) { return (Watchpoint)getBreakpoint(miSession, number); } public Breakpoint getBreakpoint(MISession miSession, int number) { Session session = (Session)getSession(); Target target = session.getTarget(miSession); if (target != null) { return getBreakpoint(target, number); } return null; } public Breakpoint getBreakpoint(Target target, int number) { List bList = (List)breakMap.get(target); if (bList != null) { Breakpoint[] bkpts = (Breakpoint[]) bList.toArray(new Breakpoint[0]); for (int i = 0; i < bkpts.length; i++) { MIBreakpoint[] miBreakpoints = bkpts[i].getMIBreakpoints(); for (int j = 0; j < miBreakpoints.length; j++) { if (miBreakpoints[j].getNumber() == number) { return bkpts[i]; } } } } return null; } boolean suspendInferior(Target target) throws CDIException { boolean shouldRestart = false; // Stop the program if (allowInterrupt && target.isRunning()) { // Disable events. ((EventManager) getSession().getEventManager()).allowProcessingEvents(false); target.suspend(); shouldRestart = true; } return shouldRestart; } void resumeInferior(Target target, boolean shouldRestart) throws CDIException { ((EventManager) getSession().getEventManager()).allowProcessingEvents(true); if (shouldRestart) { target.resume(); } } public void deleteBreakpoint(MISession miSession, int no) { Session session = (Session)getSession(); Target target = session.getTarget(miSession); if (target != null) { deleteBreakpoint(target, no); } } /** * Use in the event classes, the breakpoint is not remove from the list * It is only done in DestroyedEvent class. Since we need to keep the breakpoint * type around. * @param target * @param no */ void deleteBreakpoint (Target target, int no) { List bList = (List)breakMap.get(target); if (bList != null) { Breakpoint[] points = (Breakpoint[]) bList.toArray(new Breakpoint[0]); for (int i = 0; i < points.length; i++) { MIBreakpoint[] miBreakpoints = points[i].getMIBreakpoints(); for (int j = 0; j < miBreakpoints.length; j++) { if (miBreakpoints[j].getNumber() == no) { bList.remove(points[i]); break; } } } } } /** * Call through the Breakpoint class Breakpoint.setEnabled(boolean) * * @param breakpoint * @throws CDIException */ public void enableBreakpoint(Breakpoint breakpoint) throws CDIException { Target target = (Target)breakpoint.getTarget(); // Check if the breakpoint is in the deffered list List dList = (List)deferredMap.get(target); if (dList != null) { if (dList.contains(breakpoint)) { breakpoint.setEnabled0(true); return; // bail out here, our work is done. } } List bList = (List)breakMap.get(target); if (bList == null) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } if (!bList.contains(breakpoint)) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } MIBreakpoint[] miBreakpoints = breakpoint.getMIBreakpoints(); if (miBreakpoints == null || miBreakpoints.length == 0) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } int[] numbers = new int[miBreakpoints.length]; for (int i = 0; i < miBreakpoints.length; i++) { numbers[i] = miBreakpoints[i].getNumber(); } boolean restart = false; MISession miSession = target.getMISession(); CommandFactory factory = miSession.getCommandFactory(); MIBreakEnable breakEnable = factory.createMIBreakEnable(numbers); try { restart = suspendInferior(target); miSession.postCommand(breakEnable); MIInfo info = breakEnable.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } for (int i = 0; i < miBreakpoints.length; i++) { miBreakpoints[i].setEnabled(true); } breakpoint.setEnabled0(true); } catch (MIException e) { throw new MI2CDIException(e); } finally { try { // Resume the program and enable events. resumeInferior(target, restart); } finally { // Fire a changed Event. miSession.fireEvent(new MIBreakpointChangedEvent(miSession, numbers[0])); } } } /** * Call through the Breakpoint class. Breakpoint.disable * * @param breakpoint * @throws CDIException */ public void disableBreakpoint(Breakpoint breakpoint) throws CDIException { Target target = (Target)breakpoint.getTarget(); // Check if the breakpoint is in the deffered list List dList = (List)deferredMap.get(target); if (dList != null) { if (dList.contains(breakpoint)) { breakpoint.setEnabled0(false); return; // bail out here, our work is done. } } List bList = (List)breakMap.get(target); if (bList == null) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } if (!bList.contains(breakpoint)) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } MIBreakpoint[] miBreakpoints = breakpoint.getMIBreakpoints(); if (miBreakpoints == null || miBreakpoints.length == 0) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } int[] numbers = new int[miBreakpoints.length]; for (int i = 0; i < miBreakpoints.length; i++) { numbers[i] = miBreakpoints[i].getNumber(); } boolean restart = false; MISession miSession = target.getMISession(); CommandFactory factory = miSession.getCommandFactory(); MIBreakDisable breakDisable = factory.createMIBreakDisable(numbers); try { restart = suspendInferior(target); miSession.postCommand(breakDisable); MIInfo info = breakDisable.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } for (int i = 0; i < miBreakpoints.length; i++) { miBreakpoints[i].setEnabled(false); } breakpoint.setEnabled0(false); } catch (MIException e) { throw new MI2CDIException(e); } finally { try { resumeInferior(target, restart); } finally { // Fire a changed Event. miSession.fireEvent(new MIBreakpointChangedEvent(miSession, numbers[0])); } } } /** * Use by the Breakpoint class, Breakpoint.setCondition(Condition cond) * In this case we will not try to change the condition with -break-condition. * Since condition may contains new thread-id it is simpler to remove the breakpoints * and make a new breakpoints with the new conditions. * @param breakpoint * @param newCondition * @throws CDIException */ public void setCondition(Breakpoint breakpoint, ICDICondition newCondition) throws CDIException { Target target = (Target)breakpoint.getTarget(); // Check if the breakpoint is in the deffered list List dList = (List)deferredMap.get(target); if (dList != null) { if (dList.contains(breakpoint)) { breakpoint.setCondition0(newCondition); return; // bail out here, our work is done. } } List bList = (List)breakMap.get(target); if (bList == null) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } if (!bList.contains(breakpoint)) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } MIBreakpoint[] miBreakpoints = breakpoint.getMIBreakpoints(); deleteMIBreakpoints(target, miBreakpoints); ICDICondition oldCondition = breakpoint.getCondition(); boolean success = false; try { breakpoint.setCondition0(newCondition); if (breakpoint instanceof LocationBreakpoint) { setLocationBreakpoint((LocationBreakpoint)breakpoint); } else if (breakpoint instanceof Watchpoint) { setWatchpoint((Watchpoint)breakpoint, false); } else { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } success = true; } finally { if (!success) { breakpoint.setCondition0(oldCondition); if (breakpoint instanceof LocationBreakpoint) { setLocationBreakpoint((LocationBreakpoint)breakpoint); } else if (breakpoint instanceof Watchpoint) { setWatchpoint((Watchpoint)breakpoint, false); } } } // Fire a changed Event. miBreakpoints = breakpoint.getMIBreakpoints(); if (miBreakpoints != null && miBreakpoints.length > 0) { MISession miSession = target.getMISession(); miSession.fireEvent(new MIBreakpointChangedEvent(miSession, miBreakpoints[0].getNumber())); } } public void update(Target target) throws CDIException { update(target, null); } /** * Pass the event that causes this update * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=135250 */ public void update(Target target, MIEvent event) throws CDIException { MISession miSession = target.getMISession(); MIBreakpoint[] allMIBreakpoints = getAllMIBreakpoints(miSession); List bList = getBreakpointsList(target); List eventList = new ArrayList(allMIBreakpoints.length); for (int i = 0; i < allMIBreakpoints.length; i++) { MIBreakpoint miBreakpoint = allMIBreakpoints[i]; int no = miBreakpoint.getNumber(); Breakpoint bp = getBreakpoint(target, no); if (bp != null) { MIBreakpoint[] miBps = bp.getMIBreakpoints(); for (int j = 0; j < miBps.length; j++) { if (miBps[j].getNumber() == no) { if (hasBreakpointChanged(miBps[j], miBreakpoint)) { miBps[j] = miBreakpoint; bp.setEnabled0(miBreakpoint.isEnabled()); // FIXME: We have a problem if the thread id change. ICDICondition oldCond = bp.getCondition(); String[] tids = oldCond.getThreadIds(); Condition newCondition = new Condition(miBreakpoint.getIgnoreCount(), miBreakpoint.getCondition(), tids); bp.setCondition0(newCondition); // Fire ChangedEvent eventList.add(new MIBreakpointChangedEvent(miSession, no)); } } } } else { // add the new breakpoint and fire CreatedEvent int type = ICBreakpointType.REGULAR; if (miBreakpoint.isHardware()) { type = ICBreakpointType.HARDWARE; } else if (miBreakpoint.isTemporary()) { type = ICBreakpointType.TEMPORARY; } String[] tids = null; String tid = miBreakpoint.getThreadId(); if (tid != null && tid.length() > 0) { tids = new String[] { tid }; } Condition condition = new Condition(miBreakpoint.getIgnoreCount(), miBreakpoint.getCondition(), tids); if (miBreakpoint.isWatchpoint()) { int watchType = 0; if (miBreakpoint.isAccessWatchpoint() || miBreakpoint.isReadWatchpoint()) { watchType |= ICDIWatchpoint.READ; } if (miBreakpoint.isAccessWatchpoint() || miBreakpoint.isWriteWatchpoint()) { watchType |= ICDIWatchpoint.WRITE; } Watchpoint wpoint = new Watchpoint(target, miBreakpoint.getWhat(), type, watchType, condition, miBreakpoint.isEnabled()); wpoint.setMIBreakpoints(new MIBreakpoint[] {miBreakpoint}); bList.add(wpoint); } else { int hint = MIBreakpointChangedEvent.HINT_NONE; if (event instanceof MIBreakpointChangedEvent) { hint = ((MIBreakpointChangedEvent)event).getHint(); } String function = miBreakpoint.getFunction(); String file = miBreakpoint.getFile(); int line = miBreakpoint.getLine(); String addr = miBreakpoint.getAddress(); boolean enabled = miBreakpoint.isEnabled(); Breakpoint newBreakpoint = null; if (hint == MIBreakpointChangedEvent.HINT_NEW_LINE_BREAKPOINT || (hint == MIBreakpointChangedEvent.HINT_NONE && file != null && file.length() > 0 && line > 0)) { LineLocation location = createLineLocation (miBreakpoint.getFile(), miBreakpoint.getLine()); newBreakpoint = new LineBreakpoint(target, type, location, condition, enabled); } else if ((hint == MIBreakpointChangedEvent.HINT_NEW_FUNCTION_BREAKPOINT || hint == MIBreakpointChangedEvent.HINT_NONE) && function != null && function.length() > 0) { FunctionLocation location = createFunctionLocation(file, function); newBreakpoint = new FunctionBreakpoint(target, type, location, condition, enabled); } else if (hint == MIBreakpointChangedEvent.HINT_NEW_EVENTBREAKPOINT || EventBreakpoint.getEventTypeFromMI(miBreakpoint)!=null) { String ctype = EventBreakpoint.getEventTypeFromMI(miBreakpoint); if (ctype != null) { newBreakpoint = new EventBreakpoint(target, ctype, EventBreakpoint .getEventArgumentFromMI(miBreakpoint), condition, enabled); } else { MIPlugin.log("Unsupported event breakpoint: "+miBreakpoint.getWhat()); //$NON-NLS-1$ log entry not for users } } else if (addr != null && addr.length() > 0) { BigInteger big = MIFormat.getBigInteger(addr); AddressLocation location = createAddressLocation(big); newBreakpoint = new AddressBreakpoint(target, type, location, condition, enabled); } if (newBreakpoint != null) { newBreakpoint.setMIBreakpoints(new MIBreakpoint[] { miBreakpoint }); bList.add(newBreakpoint); } } eventList.add(new MIBreakpointCreatedEvent(miSession, no)); } } // Check if any breakpoint was removed. Breakpoint[] oldBreakpoints = (Breakpoint[]) bList.toArray(new Breakpoint[0]); for (int i = 0; i < oldBreakpoints.length; i++) { boolean found = false; MIBreakpoint[] miBreakpoints = oldBreakpoints[i].getMIBreakpoints(); for (int j = 0; j < miBreakpoints.length; j++) { int no = miBreakpoints[j].getNumber(); for (int k = 0; k < allMIBreakpoints.length; k++) { if (no == allMIBreakpoints[k].getNumber()) { found = true; break; } } if (!found) { // Fire destroyed Events. eventList.add(new MIBreakpointDeletedEvent(miSession, no)); } } } MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]); miSession.fireEvents(events); } /** * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#allowProgramInterruption() */ public void allowProgramInterruption(boolean e) { allowInterrupt = e; } public void deleteFromDeferredList(Breakpoint bkpt) { List dList = (List)deferredMap.get(bkpt.getTarget()); if (dList != null) { dList.remove(bkpt); } } /** * Use by the EventManager when checking for deferred breapoints. * @param bkpt */ public void addToBreakpointList(Breakpoint bkpt) { List bList = getBreakpointsList(bkpt.getTarget()); bList.add(bkpt); } public void deleteAllBreakpoints(Target target) throws CDIException { List bList = (List)breakMap.get(target); if (bList != null) { ICDIBreakpoint[] bps = new ICDIBreakpoint[bList.size()]; bList.toArray(bps); deleteBreakpoints(target, bps); } } /** * @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#deleteBreakpoint(ICDIBreakpoint) */ public void deleteBreakpoint(ICDIBreakpoint breakpoint) throws CDIException { deleteBreakpoints((Target)breakpoint.getTarget(), new ICDIBreakpoint[] { breakpoint }); } public void deleteBreakpoints(Target target, ICDIBreakpoint[] breakpoints) throws CDIException { List bList = (List)breakMap.get(target); List dList = (List)deferredMap.get(target); // Do the sanity check first, we will accept all or none if (bList == null) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } for (int i = 0; i < breakpoints.length; i++) { if (!(breakpoints[i] instanceof Breakpoint && (bList.contains(breakpoints[i]) || (dList != null && dList.contains(breakpoints[i]))))) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Not_a_CDT_breakpoint")); //$NON-NLS-1$ } } MISession miSession = target.getMISession(); List eventList = new ArrayList(breakpoints.length); for (int i = 0; i < breakpoints.length; i++) { if (!(dList != null && dList.remove(breakpoints[i]))) { MIBreakpoint[] miBreakpoints = ((Breakpoint)breakpoints[i]).getMIBreakpoints(); if (miBreakpoints.length > 0) { deleteMIBreakpoints(target, miBreakpoints); eventList.add(new MIBreakpointDeletedEvent(miSession, miBreakpoints[0].getNumber())); } } } MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]); miSession.fireEvents(events); } void deleteMIBreakpoints(Target target, MIBreakpoint[] miBreakpoints) throws CDIException { MISession miSession = target.getMISession(); int[] numbers = new int[miBreakpoints.length]; for (int i = 0; i < miBreakpoints.length; ++i) { numbers[i] = miBreakpoints[i].getNumber(); } boolean restart = false; try { restart = suspendInferior(target); deleteMIBreakpoints(miSession, numbers); } finally { resumeInferior(target, restart); } } void deleteMIBreakpoints(MISession miSession, int[] numbers) throws CDIException { CommandFactory factory = miSession.getCommandFactory(); MIBreakDelete breakDelete = factory.createMIBreakDelete(numbers); try { miSession.postCommand(breakDelete); MIInfo info = breakDelete.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } catch (MIException e) { throw new MI2CDIException(e); } } public ICDIBreakpoint[] getBreakpoints(Target target) throws CDIException { List list = (List)breakMap.get(target); if (list != null) { ICDIBreakpoint[] bps = new ICDIBreakpoint[list.size()]; list.toArray(bps); return bps; } return EMPTY_BREAKPOINTS; } public ICDIBreakpoint[] getDeferredBreakpoints(Target target) throws CDIException { List dlist = (List)deferredMap.get(target); if (dlist != null) { ICDIBreakpoint[] bps = new ICDIBreakpoint[dlist.size()]; dlist.toArray(bps); return bps; } return EMPTY_BREAKPOINTS; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIBreakpointManagement#setLineBreakpoint(int, org.eclipse.cdt.debug.core.cdi.ICDILineLocation, org.eclipse.cdt.debug.core.cdi.ICDICondition, boolean) */ public ICDILineBreakpoint setLineBreakpoint(Target target, int type, ICDILineLocation location, ICDICondition condition, boolean deferred, boolean enabled) throws CDIException { LineBreakpoint bkpt = new LineBreakpoint(target, type, location, condition, enabled); setNewLocationBreakpoint(bkpt, deferred); return bkpt; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIBreakpointManagement#setFunctionBreakpoint(int, org.eclipse.cdt.debug.core.cdi.ICDIFunctionLocation, org.eclipse.cdt.debug.core.cdi.ICDICondition, boolean) */ public ICDIFunctionBreakpoint setFunctionBreakpoint(Target target, int type, ICDIFunctionLocation location, ICDICondition condition, boolean deferred, boolean enabled) throws CDIException { FunctionBreakpoint bkpt = new FunctionBreakpoint(target, type, location, condition, enabled); setNewLocationBreakpoint(bkpt, deferred); return bkpt; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIBreakpointManagement#setAddressBreakpoint(int, org.eclipse.cdt.debug.core.cdi.ICDIAddressLocation, org.eclipse.cdt.debug.core.cdi.ICDICondition, boolean) */ public ICDIAddressBreakpoint setAddressBreakpoint(Target target, int type, ICDIAddressLocation location, ICDICondition condition, boolean deferred, boolean enabled) throws CDIException { AddressBreakpoint bkpt = new AddressBreakpoint(target, type, location, condition, enabled); setNewLocationBreakpoint(bkpt, deferred); return bkpt; } protected void setNewLocationBreakpoint(LocationBreakpoint bkpt, boolean deferred) throws CDIException { Target target = (Target)bkpt.getTarget(); MISession miSession = target.getMISession(); try { setLocationBreakpoint(bkpt); List blist = getBreakpointsList(target); blist.add(bkpt); // Fire a created Event. MIBreakpoint[] miBreakpoints = bkpt.getMIBreakpoints(); if (miBreakpoints != null && miBreakpoints.length > 0) { miSession.fireEvent(new MIBreakpointCreatedEvent(miSession, miBreakpoints[0].getNumber())); } } catch (CDIException e) { if (!deferred) { throw e; } Session session = (Session)target.getSession(); SharedLibraryManager sharedMgr = session.getSharedLibraryManager(); if (sharedMgr.isDeferredBreakpoint(target)) { addDeferredBreakpoint(bkpt); } else { throw e; } } } private void addDeferredBreakpoint(Breakpoint breakpoint) { Target target = (Target)breakpoint.getTarget(); List dList = (List)deferredMap.get(target); if (dList == null) { dList = Collections.synchronizedList(new ArrayList()); deferredMap.put(target, dList); } dList.add(breakpoint); } public void setLocationBreakpoint (LocationBreakpoint bkpt) throws CDIException { Target target = (Target)bkpt.getTarget(); MISession miSession = target.getMISession(); MIBreakInsert[] breakInserts = createMIBreakInsert(bkpt, miSession.isBreakpointsWithFullName()); List pointList = new ArrayList(); boolean restart = false; try { restart = suspendInferior(target); CommandFactory factory = miSession.getCommandFactory(); boolean enable = bkpt.isEnabled(); for (int i = 0; i < breakInserts.length; i++) { miSession.postCommand(breakInserts[i]); MIBreakInsertInfo info = breakInserts[i].getMIBreakInsertInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } MIBreakpoint[] points = info.getMIBreakpoints(); if (points == null || points.length == 0) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Parsing_Error")); //$NON-NLS-1$ } // Set if (bkpt.getFile() != null && bkpt.getFile().length() > 0) { for (int j = 0; j < points.length; j++) { points[j].setFile(bkpt.getFile()); } } if (bkpt.getLineNumber()>0) { for (int j = 0; j < points.length; j++) { if (points[j].getLine() == 0) points[j].setLine(bkpt.getLineNumber()); } } // Make sure that if the breakpoint was disable we create them disable. if (!enable) { int[] numbers = new int[points.length]; for (int j = 0; j < points.length; j++) { numbers[j] = points[j].getNumber(); } MIBreakDisable breakDisable = factory.createMIBreakDisable(numbers); try { miSession.postCommand(breakDisable); MIInfo disableInfo = breakDisable.getMIInfo(); if (disableInfo == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } catch (MIException e) { throw new MI2CDIException(e); } } pointList.addAll(Arrays.asList(points)); } } catch (MIException e) { try { // Things did not go well remove all the breakpoints we've set before. MIBreakpoint[] allPoints = (MIBreakpoint[]) pointList.toArray(new MIBreakpoint[pointList.size()]); if (allPoints != null && allPoints.length > 0) { deleteMIBreakpoints(target, allPoints); } } catch (CDIException cdie) { // ignore this one; } throw new MI2CDIException(e); } finally { resumeInferior(target, restart); } MIBreakpoint[] allPoints = (MIBreakpoint[]) pointList.toArray(new MIBreakpoint[pointList.size()]); bkpt.setMIBreakpoints(allPoints); } public void setWatchpoint(Watchpoint bkpt) throws CDIException { setWatchpoint(bkpt, true); } private void setWatchpoint(Watchpoint watchpoint, boolean isNew) throws CDIException { Target target = (Target)watchpoint.getTarget(); boolean access = watchpoint.isReadType() && watchpoint.isWriteType(); boolean read = ! watchpoint.isWriteType() && watchpoint.isReadType(); String expression = watchpoint.getDerivedExpression(); boolean enable = watchpoint.isEnabled(); MISession miSession = target.getMISession(); CommandFactory factory = miSession.getCommandFactory(); MIBreakWatch breakWatch = factory.createMIBreakWatch(access, read, expression); MIBreakpoint[] points = null; boolean restart = false; try { restart = suspendInferior(target); miSession.postCommand(breakWatch); MIBreakWatchInfo winfo = breakWatch.getMIBreakWatchInfo(); if (winfo == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } points = winfo.getMIBreakpoints(); if (points == null || points.length == 0) { throw new CDIException(CdiResources.getString("cdi.BreakpointManager.Parsing_Error")); //$NON-NLS-1$ } int no = points[0].getNumber(); // Put the condition now. String exprCond = null; int ignoreCount = 0; ICDICondition condition = watchpoint.getCondition(); if (condition != null) { exprCond = condition.getExpression(); ignoreCount = condition.getIgnoreCount(); } if (exprCond != null && exprCond.length() > 0) { MIBreakCondition breakCondition = factory.createMIBreakCondition(no, exprCond); miSession.postCommand(breakCondition); MIInfo info = breakCondition.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } if (ignoreCount > 0) { MIBreakAfter breakAfter = factory.createMIBreakAfter(no, ignoreCount); miSession.postCommand(breakAfter); MIInfo info = breakAfter.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } if (!enable) { int[] numbers = new int[1]; numbers[0] = no; MIBreakDisable breakDisable = factory.createMIBreakDisable(numbers); try { miSession.postCommand(breakDisable); MIInfo disableInfo = breakDisable.getMIInfo(); if (disableInfo == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } catch (MIException e) { throw new MI2CDIException(e); } } // how to deal with threads ??? } catch (MIException e) { throw new MI2CDIException(e); } finally { resumeInferior(target, restart); } watchpoint.setMIBreakpoints(points); if (isNew) { List bList = getBreakpointsList(target); bList.add(watchpoint); // Fire a created Event. MIBreakpoint[] miBreakpoints = watchpoint.getMIBreakpoints(); if (miBreakpoints != null && miBreakpoints.length > 0) { miSession.fireEvent(new MIBreakpointCreatedEvent(miSession, miBreakpoints[0].getNumber())); } } } Breakpoint[] exceptionBps = new Breakpoint[2]; final int EXCEPTION_THROW_IDX = 0; final int EXCEPTION_CATCH_IDX = 1; final static String[] EXCEPTION_FUNCS = new String[] {"__cxa_throw", "__cxa_begin_catch"}; //$NON-NLS-1$ //$NON-NLS-2$ public ICDIExceptionpoint setExceptionpoint(Target target, String clazz, boolean stopOnThrow, boolean stopOnCatch, boolean enabled) throws CDIException { if (!stopOnThrow && !stopOnCatch) { throw new CDIException("Must suspend on throw or catch"); //$NON-NLS-1$ } MIBreakpoint[] miBreakpoints = null; if (stopOnThrow) { synchronized(exceptionBps) { int id = EXCEPTION_THROW_IDX; if (exceptionBps[EXCEPTION_THROW_IDX] == null) { FunctionLocation location = new FunctionLocation(null, EXCEPTION_FUNCS[id]); FunctionBreakpoint bp = new FunctionBreakpoint(target, ICBreakpointType.REGULAR, location, null, enabled); setLocationBreakpoint(bp); exceptionBps[id] = bp; miBreakpoints = bp.getMIBreakpoints(); } } } if (stopOnCatch) { synchronized(exceptionBps) { int id = EXCEPTION_THROW_IDX; if (exceptionBps[id] == null) { FunctionLocation location = new FunctionLocation(null, EXCEPTION_FUNCS[id]); FunctionBreakpoint bp = new FunctionBreakpoint(target, ICBreakpointType.REGULAR, location, null, enabled); setLocationBreakpoint(bp); exceptionBps[id] = bp; if (miBreakpoints != null) { MIBreakpoint[] mibp = bp.getMIBreakpoints(); MIBreakpoint[] temp = new MIBreakpoint[miBreakpoints.length + mibp.length]; System.arraycopy(miBreakpoints, 0, temp, 0, miBreakpoints.length); System.arraycopy(mibp, 0, temp, miBreakpoints.length, mibp.length); } else { miBreakpoints = bp.getMIBreakpoints(); } } } } Exceptionpoint excp = new Exceptionpoint(target, clazz, stopOnThrow, stopOnCatch, null, enabled); if (miBreakpoints != null && miBreakpoints.length > 0) { excp.setMIBreakpoints(miBreakpoints); List blist = getBreakpointsList(target); blist.add(excp); // Fire a created Event. MISession miSession = target.getMISession(); miSession.fireEvent(new MIBreakpointCreatedEvent(miSession, miBreakpoints[0].getNumber())); } return excp; } /** * Call -gdb-set breakpoint pending set * @param target * @param set * @throws CDIException */ public void setBreakpointPending(Target target, boolean set) throws CDIException { MISession miSession = target.getMISession(); CommandFactory factory = miSession.getCommandFactory(); MIGDBSetBreakpointPending bpp = factory.createMIGDBSetBreakpointPending(set); try { miSession.postCommand(bpp); MIInfo info = bpp.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } catch (MIException e) { throw new MI2CDIException(e); } } public Condition createCondition(int ignoreCount, String expression, String[] tids) { return new Condition(ignoreCount, expression, tids); } public LineLocation createLineLocation(String file, int line) { return new LineLocation(file, line); } public FunctionLocation createFunctionLocation(String file, String function) { return new FunctionLocation(file, function); } public AddressLocation createAddressLocation(BigInteger address) { return new AddressLocation(address); } MIBreakInsert[] createMIBreakInsert(LocationBreakpoint bkpt) throws CDIException { return createMIBreakInsert(bkpt, false); } MIBreakInsert[] createMIBreakInsert(LocationBreakpoint bkpt, boolean fullPath) throws CDIException { boolean hardware = bkpt.isHardware(); boolean temporary = bkpt.isTemporary(); String exprCond = null; int ignoreCount = 0; String[] threadIds = null; StringBuffer line = new StringBuffer(); if (bkpt.getCondition() != null) { ICDICondition condition = bkpt.getCondition(); exprCond = condition.getExpression(); ignoreCount = condition.getIgnoreCount(); threadIds = condition.getThreadIds(); } if (bkpt.getLocator() != null) { ICDILocator locator = bkpt.getLocator(); String file = locator.getFile(); if (file != null) { if (fullPath==false) { file = new File(file).getName(); } } String function = locator.getFunction(); int no = locator.getLineNumber(); if (bkpt instanceof LineBreakpoint) { if (file != null && file.length() > 0) { line.append(file).append(':'); } line.append(no); } else if (bkpt instanceof FunctionBreakpoint) { if (function != null && function.length() > 0) { // if the function contains :: assume the user // knows the exact funciton int colon = function.indexOf("::"); //$NON-NLS-1$ if (colon != -1) { line.append(function); } else { if (file != null && file.length() > 0) { line.append(file).append(':'); } // GDB does not seem to accept function arguments when // we use file name: // (gdb) break file.c:Test(int) // Will fail, altought it can accept this // (gdb) break file.c:main // so fall back to the line number or // just the name of the function if lineno is invalid. int paren = function.indexOf('('); if (paren != -1) { if (no <= 0) { String func = function.substring(0, paren); line.append(func); } else { line.append(no); } } else { line.append(function); } } } else { // ??? if (file != null && file.length() > 0) { line.append(file).append(':'); } if (no > 0) { line.append(no); } } } else if (bkpt instanceof AddressBreakpoint) { line.append('*').append(locator.getAddress()); } else { // ??? if (file != null && file.length() > 0) { line.append(file).append(':'); } line.append(no); } } MIBreakInsert[] miBreakInserts; MISession miSession = ((Target)bkpt.getTarget()).getMISession(); CommandFactory factory = miSession.getCommandFactory(); if (threadIds == null || threadIds.length == 0) { MIBreakInsert bi = factory.createMIBreakInsert(temporary, hardware, exprCond, ignoreCount, line.toString(), 0); miBreakInserts = new MIBreakInsert[] { bi } ; } else { List list = new ArrayList(threadIds.length); for (int i = 0; i < threadIds.length; i++) { String threadId = threadIds[i]; int tid = 0; if (threadId != null && threadId.length() > 0) { try { tid = Integer.parseInt(threadId); list.add(factory.createMIBreakInsert(temporary, hardware, exprCond, ignoreCount, line.toString(), tid)); } catch (NumberFormatException e) { } } } miBreakInserts = (MIBreakInsert[]) list.toArray(new MIBreakInsert[list.size()]); } return miBreakInserts; } public ICDIEventBreakpoint setEventBreakpoint(Target target, String type, String arg, ICDICondition condition, boolean enabled) throws CDIException { EventBreakpoint eventBkpt = new EventBreakpoint(target,type,arg,condition,enabled); setEventBreakpoint(eventBkpt); return eventBkpt; } public void setEventBreakpoint(EventBreakpoint eventBkpt) throws CDIException { Target target = (Target) eventBkpt.getTarget(); MISession miSession = target.getMISession(); CommandFactory factory = miSession.getCommandFactory(); CLICatch breakCatch = factory.createCLICatch(eventBkpt.getGdbEvent(), eventBkpt .getGdbArg()); eventBkpt.setMIBreakpoints(new MIBreakpoint[0]); // initialize boolean restart = false; try { restart = suspendInferior(target); miSession.postCommand(breakCatch); int no; try { CLICatchInfo cinfo = (CLICatchInfo) breakCatch.getMIInfo(); if (cinfo == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } MIBreakpoint[] points = cinfo.getMIBreakpoints(); if (points == null || points.length == 0) { throw new CDIException(CdiResources .getString("cdi.BreakpointManager.Parsing_Error")); //$NON-NLS-1$ } no = points[0].getNumber(); eventBkpt.setMIBreakpoints(points); } catch (MIException e) { if (!eventBkpt.isDeferred()) { throw e; } addDeferredBreakpoint(eventBkpt); return; } // Put the condition now. String exprCond = null; int ignoreCount = 0; ICDICondition condition = eventBkpt.getCondition(); if (condition != null) { exprCond = condition.getExpression(); ignoreCount = condition.getIgnoreCount(); } if (exprCond != null && exprCond.length() > 0) { MIBreakCondition breakCondition = factory.createMIBreakCondition(no, exprCond); miSession.postCommand(breakCondition); MIInfo info = breakCondition.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } if (ignoreCount > 0) { MIBreakAfter breakAfter = factory.createMIBreakAfter(no, ignoreCount); miSession.postCommand(breakAfter); MIInfo info = breakAfter.getMIInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } } // how to deal with threads ??? } catch (MIException e) { throw new MI2CDIException(e); } finally { resumeInferior(target, restart); } List bList = getBreakpointsList(target); bList.add(eventBkpt); // Fire a created Event. MIBreakpoint[] miBreakpoints = eventBkpt.getMIBreakpoints(); if (miBreakpoints != null && miBreakpoints.length > 0) { miSession.fireEvent(new MIBreakpointCreatedEvent(miSession, miBreakpoints[0] .getNumber())); } } }