mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-03 14:25:37 +02:00
[309234] DSF not as helpful as CDI on SEGV
This commit is contained in:
parent
959e7d3658
commit
f8d7eee520
7 changed files with 161 additions and 23 deletions
|
@ -76,7 +76,9 @@ public class ThreadVMNode extends AbstractThreadVMNode
|
|||
IGdbLaunchVMConstants.PROP_OS_ID,
|
||||
ILaunchVMConstants.PROP_IS_SUSPENDED,
|
||||
ExecutionContextLabelText.PROP_STATE_CHANGE_REASON_KNOWN,
|
||||
ILaunchVMConstants.PROP_STATE_CHANGE_REASON }),
|
||||
ILaunchVMConstants.PROP_STATE_CHANGE_REASON,
|
||||
ExecutionContextLabelText.PROP_STATE_CHANGE_DETAILS_KNOWN,
|
||||
ILaunchVMConstants.PROP_STATE_CHANGE_DETAILS}),
|
||||
new LabelText(MessagesForGdbLaunchVM.ThreadVMNode_No_columns__Error__label, new String[0]),
|
||||
new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING)) {
|
||||
{ setPropertyNames(new String[] { ILaunchVMConstants.PROP_IS_SUSPENDED }); }
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
# {6} - 0=running/1=suspended
|
||||
# {7} - state change reason available, 0=not available/1=available
|
||||
# {8} - state change reason
|
||||
ThreadVMNode_No_columns__text_format={0,choice,0#Thread|1#{1}}{2,choice,0#|1# [{3}]}{4,choice,0#|1# {5}} ({6,choice,0#Running|1#Suspended}{7,choice,0#|1# : {8}})
|
||||
# {9} - state change details available, 0=not available/1=available
|
||||
# {10}- state change details
|
||||
ThreadVMNode_No_columns__text_format={0,choice,0#Thread|1#{1}}{2,choice,0#|1# [{3}]}{4,choice,0#|1# {5}} ({6,choice,0#Running|1#Suspended}{7,choice,0#|1# : {8}}{9,choice,0#|1# : {10}})
|
||||
|
||||
ThreadVMNode_No_columns__Error__label=<unavailable>
|
||||
|
||||
|
|
|
@ -93,12 +93,16 @@ import org.osgi.framework.BundleContext;
|
|||
public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, ICachingService
|
||||
{
|
||||
@Immutable
|
||||
private static class ExecutionData implements IExecutionDMData {
|
||||
private static class ExecutionData implements IExecutionDMData2 {
|
||||
private final StateChangeReason fReason;
|
||||
ExecutionData(StateChangeReason reason) {
|
||||
private final String fDetails;
|
||||
|
||||
ExecutionData(StateChangeReason reason, String details) {
|
||||
fReason = reason;
|
||||
fDetails = details;
|
||||
}
|
||||
public StateChangeReason getStateChangeReason() { return fReason; }
|
||||
public String getDetails() { return fDetails; }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,6 +157,23 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
return StateChangeReason.USER_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDetails() {
|
||||
MIStoppedEvent event = getMIEvent();
|
||||
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||
return ((MICatchpointHitEvent)event).getReason();
|
||||
} else if (event instanceof MISharedLibEvent) {
|
||||
return ((MISharedLibEvent)event).getLibrary();
|
||||
} else if (event instanceof MISignalEvent) {
|
||||
return ((MISignalEvent)event).getName() + ':' + ((MISignalEvent)event).getMeaning();
|
||||
} else if (event instanceof MIWatchpointTriggerEvent) {
|
||||
return ((MIWatchpointTriggerEvent)event).getExpression();
|
||||
} else if (event instanceof MIErrorEvent) {
|
||||
return ((MIErrorEvent)event).getMessage();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,7 +248,19 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
boolean fSuspended = false;
|
||||
boolean fResumePending = false;
|
||||
boolean fStepping = false;
|
||||
|
||||
/**
|
||||
* What caused the state change. E.g., a signal was thrown.
|
||||
*/
|
||||
StateChangeReason fStateChangeReason;
|
||||
|
||||
/**
|
||||
* Further detail on what caused the state change. E.g., the specific signal
|
||||
* that was throw was a SIGINT. The exact string comes from gdb in the mi
|
||||
* event. May be null, as not all types of state change have additional
|
||||
* detail of interest.
|
||||
*/
|
||||
String fStateChangeDetails;
|
||||
}
|
||||
|
||||
private static class RunToLineActiveOperation {
|
||||
|
@ -783,7 +816,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
}
|
||||
|
||||
if (dmc instanceof IMIExecutionDMContext) {
|
||||
rm.setData(new ExecutionData(threadState.fSuspended ? threadState.fStateChangeReason : null));
|
||||
rm.setData(new ExecutionData(threadState.fSuspended ? threadState.fStateChangeReason : null, threadState.fStateChangeDetails));
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
|
||||
"Given context: " + dmc + " is not a recognized execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
@ -817,6 +850,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
threadState.fSuspended = false;
|
||||
threadState.fResumePending = false;
|
||||
threadState.fStateChangeReason = reason;
|
||||
threadState.fStateChangeDetails = null; // we have no details of interest for a resume
|
||||
threadState.fStepping = isStepping;
|
||||
}
|
||||
|
||||
|
@ -831,6 +865,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
threadState.fResumePending = false;
|
||||
threadState.fStepping = false;
|
||||
threadState.fStateChangeReason = reason;
|
||||
threadState.fStateChangeDetails = event.getDetails();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -130,12 +130,15 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
}
|
||||
|
||||
@Immutable
|
||||
private static class ExecutionData implements IExecutionDMData {
|
||||
private static class ExecutionData implements IExecutionDMData2 {
|
||||
private final StateChangeReason fReason;
|
||||
ExecutionData(StateChangeReason reason) {
|
||||
private final String fDetails;
|
||||
ExecutionData(StateChangeReason reason, String details) {
|
||||
fReason = reason;
|
||||
fDetails = details;
|
||||
}
|
||||
public StateChangeReason getStateChangeReason() { return fReason; }
|
||||
public String getDetails() { return fDetails; }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,6 +193,26 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
return StateChangeReason.USER_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
public String getDetails() {
|
||||
MIStoppedEvent event = getMIEvent();
|
||||
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||
return ((MICatchpointHitEvent)event).getReason();
|
||||
} else if (event instanceof MISharedLibEvent) {
|
||||
return ((MISharedLibEvent)event).getLibrary();
|
||||
} else if (event instanceof MISignalEvent) {
|
||||
return ((MISignalEvent)event).getName() + ':' + ((MISignalEvent)event).getMeaning();
|
||||
} else if (event instanceof MIWatchpointTriggerEvent) {
|
||||
return ((MIWatchpointTriggerEvent)event).getExpression();
|
||||
} else if (event instanceof MIErrorEvent) {
|
||||
return ((MIErrorEvent)event).getMessage();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -324,7 +347,20 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
private boolean fStepping = false;
|
||||
private boolean fTerminated = false;
|
||||
|
||||
|
||||
/**
|
||||
* What caused the state change. E.g., a signal was thrown.
|
||||
*/
|
||||
private StateChangeReason fStateChangeReason;
|
||||
|
||||
/**
|
||||
* Further detail on what caused the state change. E.g., the specific signal
|
||||
* that was throw was a SIGINT. The exact string comes from gdb in the mi
|
||||
* event. May be null, as not all types of state change have additional
|
||||
* detail of interest.
|
||||
*/
|
||||
private String fStateChangeDetails;
|
||||
|
||||
private IExecutionDMContext fStateChangeTriggeringContext;
|
||||
/**
|
||||
* Indicates that the next MIRunning event should be silenced.
|
||||
|
@ -526,6 +562,7 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
fSuspended = false;
|
||||
fResumePending = false;
|
||||
fStateChangeReason = e.getReason();
|
||||
fStateChangeDetails = null; // we have no details of interest for a resume
|
||||
fMICommandCache.setContextAvailable(e.getDMContext(), false);
|
||||
//fStateChangeTriggeringContext = e.getTriggeringContext();
|
||||
if (e.getReason().equals(StateChangeReason.STEP)) {
|
||||
|
@ -544,6 +581,7 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
fMICommandCache.setContextAvailable(e.getDMContext(), true);
|
||||
fMICommandCache.reset();
|
||||
fStateChangeReason = e.getReason();
|
||||
fStateChangeDetails = e.getDetails();
|
||||
fStateChangeTriggeringContext = e.getTriggeringContexts().length != 0
|
||||
? e.getTriggeringContexts()[0] : null;
|
||||
fSuspended = true;
|
||||
|
@ -793,10 +831,12 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
|
||||
public void getExecutionData(IExecutionDMContext dmc, DataRequestMonitor<IExecutionDMData> rm){
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
rm.setData( new ExecutionData(fStateChangeReason) );
|
||||
rm.setData( new ExecutionData(fStateChangeReason, fStateChangeDetails) );
|
||||
} else if (dmc instanceof IMIExecutionDMContext) {
|
||||
StateChangeReason reason = dmc.equals(fStateChangeTriggeringContext) ? fStateChangeReason : StateChangeReason.CONTAINER;
|
||||
rm.setData(new ExecutionData(reason));
|
||||
boolean thisThreadCausedStateChange = dmc.equals(fStateChangeTriggeringContext);
|
||||
StateChangeReason reason = thisThreadCausedStateChange ? fStateChangeReason : StateChangeReason.CONTAINER;
|
||||
String details = thisThreadCausedStateChange ? fStateChangeDetails : null;
|
||||
rm.setData(new ExecutionData(reason, details));
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Given context: " + dmc + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
|
|
@ -68,12 +68,22 @@ public class MIBreakpointHitEvent extends MIStoppedEvent {
|
|||
}
|
||||
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
|
||||
|
||||
for (MIStreamRecord streamRecord : miStreamRecords) {
|
||||
String log = streamRecord.getString();
|
||||
if (log.startsWith("Catchpoint ")) { //$NON-NLS-1$
|
||||
return new MICatchpointHitEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), bkptno);
|
||||
}
|
||||
}
|
||||
// We might be here because of a catchpoint hit; in gdb >= 7.0,
|
||||
// catchpoints are reported as breakpoints. Unfortunately, there's
|
||||
// nothing in the stopped event indicating it's a catchpoint, and unlike
|
||||
// gdb < 7.0, there are no stream records that reveal it's a catchpoint.
|
||||
// The only way to determine it's a catchpoint is to map the gdb breakpoint
|
||||
// number back to the CBreakpoint (platform) instance, and that *will* reveal
|
||||
// whether it's a catchpoint or not, and even which kind of catchpoint
|
||||
// TODO:
|
||||
/*
|
||||
CBreakpoint cbkpt = FromSomewhere.getCBreakpointForGdbBreakpoint(bkptno); <== this method doesn't exist yet
|
||||
if (cbkpt instanceof CEventBreakpoint) {
|
||||
String eventTypeID = ((CEventBreakpoint)cbkpt).getEventType();
|
||||
String gdbKeyword = GdbCatchpoints.eventToGdbCatchpointKeyword(eventTypeID)
|
||||
return MICatchpointHitEvent.parse(stoppedEvent.getDMContext(), token, results, gdbKeyword);
|
||||
}
|
||||
*/
|
||||
|
||||
return new MIBreakpointHitEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), bkptno);
|
||||
}
|
||||
|
|
|
@ -12,9 +12,25 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIStreamRecord;
|
|||
*/
|
||||
public class MICatchpointHitEvent extends MIBreakpointHitEvent {
|
||||
|
||||
/**
|
||||
* See {@link #getReason()}
|
||||
*/
|
||||
private String fReason;
|
||||
|
||||
protected MICatchpointHitEvent(IExecutionDMContext ctx, int token,
|
||||
MIResult[] results, MIFrame frame, int bkptno) {
|
||||
MIResult[] results, MIFrame frame, int bkptno, String reason) {
|
||||
super(ctx, token, results, frame, bkptno);
|
||||
fReason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event the cachpoint caught. E.g., a C++ exception was thrown.
|
||||
* This string comes either from gdb when the catchpoint is hit, or it's the
|
||||
* gdb catchpoint keyword ('catch', 'throw', 'fork', etc) that was used to
|
||||
* set the catchpoint (to be done for gdb >= 7.0)
|
||||
*/
|
||||
public String getReason() {
|
||||
return fReason;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,9 +47,27 @@ public class MICatchpointHitEvent extends MIBreakpointHitEvent {
|
|||
StringTokenizer tokenizer = new StringTokenizer(streamRecord.getString());
|
||||
tokenizer.nextToken(); // "Catchpoint"
|
||||
try {
|
||||
int bkptNumber = Integer.parseInt(tokenizer.nextToken()); // "1" (e.g.,)
|
||||
int bkptNumber = Integer.parseInt(tokenizer.nextToken()); // "1"
|
||||
StringBuilder reason = new StringBuilder();
|
||||
boolean first = true;
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
if (!first) {
|
||||
reason.append(" "); //$NON-NLS-1$ ok; technically, the delim could be any whitespace, but we know it's s a space char
|
||||
}
|
||||
reason.append(tokenizer.nextElement());
|
||||
first = false;
|
||||
}
|
||||
|
||||
// remove the parentheses
|
||||
if (reason.charAt(0) == '(') {
|
||||
reason.deleteCharAt(0);
|
||||
}
|
||||
if (reason.charAt(reason.length()-1) == ')') {
|
||||
reason.deleteCharAt(reason.length()-1);
|
||||
}
|
||||
|
||||
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
|
||||
return new MICatchpointHitEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), bkptNumber);
|
||||
return new MICatchpointHitEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), bkptNumber, reason.toString());
|
||||
}
|
||||
catch (NumberFormatException exc) {
|
||||
assert false : "unexpected catchpoint stream record format: " + streamRecord.getString(); //$NON-NLS-1$
|
||||
|
|
|
@ -23,13 +23,28 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
|
|||
@Immutable
|
||||
public class MISharedLibEvent extends MIStoppedEvent {
|
||||
|
||||
protected MISharedLibEvent(IExecutionDMContext ctx, int token, MIResult[] results, MIFrame frame) {
|
||||
/** See {@link #getLibrary()} */
|
||||
private String fLibrary;
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
protected MISharedLibEvent(IExecutionDMContext ctx, int token, MIResult[] results, MIFrame frame, String library) {
|
||||
super(ctx, token, results, frame);
|
||||
fLibrary = library;
|
||||
}
|
||||
|
||||
/** The library that was loaded, as reported by gdb.
|
||||
* @since 3.0*/
|
||||
public String getLibrary() {
|
||||
return fLibrary;
|
||||
}
|
||||
|
||||
public static MIStoppedEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
|
||||
{
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
public static MIStoppedEvent parse(IExecutionDMContext dmc, int token, MIResult[] results, String library) {
|
||||
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
|
||||
return new MISharedLibEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());
|
||||
return new MISharedLibEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), library);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue