From e52031c676b9f9ef37cd795149b8ff6e5a088c31 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 7 Jun 2016 15:05:52 -0400 Subject: [PATCH] Bug 495623: Use new flags in =record-change from upcoming GDB release With the next GDB (probably named 7.12), we are provided with the type of record that was started. =record-started,thread-group="i1",method="btrace",format="bts" =record-started,thread-group="i1",method="btrace",format="pt" =record-started,thread-group="i1",method="full" We make use of this information in GDBRunControl_7_10 to avoid sending an 'info record' command. Note that because MI adds fields in a backwards-compatible way, it was much simpler to modify GDBRunControl_7_10 instead of creating a new GDBRunControl_7_12 (whose name may even be wrong if GDB's next version is not actually 7.12). Change-Id: I869b3c0ff648d5e38081e06a7063613bbb9266dc --- .../dsf/gdb/service/GDBRunControl_7_10.java | 101 +++++++++++++++--- 1 file changed, 86 insertions(+), 15 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_10.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_10.java index f8c83128efd..e2664323f3b 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_10.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_10.java @@ -21,10 +21,13 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.IMICommandControl; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoRecordInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIConst; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MINotifyAsyncOutput; import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord; import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; +import org.eclipse.cdt.dsf.mi.service.command.output.MIResult; +import org.eclipse.cdt.dsf.mi.service.command.output.MIValue; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -71,6 +74,18 @@ public class GDBRunControl_7_10 extends GDBRunControl_7_6 implements IReverseRun requestMonitor.done(); } + /** @since 5.1 */ + protected void setReverseTraceMethod(ReverseDebugMethod traceMethod) { + if (fReverseTraceMethod != traceMethod) { + boolean enabled = false; + fReverseTraceMethod = traceMethod; + if (fReverseTraceMethod != ReverseDebugMethod.OFF) { + enabled = true; + } + setReverseModeEnabled(enabled); + } + } + @Override public void getReverseTraceMethod(ICommandControlDMContext context, DataRequestMonitor rm) { rm.setData(fReverseTraceMethod); @@ -151,27 +166,83 @@ public class GDBRunControl_7_10 extends GDBRunControl_7_6 implements IReverseRun if ("record-started".equals(asyncClass) || //$NON-NLS-1$ "record-stopped".equals(asyncClass)) { //$NON-NLS-1$ if ("record-stopped".equals(asyncClass)) { //$NON-NLS-1$ - fReverseTraceMethod = ReverseDebugMethod.OFF; - setReverseModeEnabled(false); + setReverseTraceMethod(ReverseDebugMethod.OFF); } else { - getConnection().queueCommand( - fCommandFactory.createCLIInfoRecord(getConnection().getContext()), - new DataRequestMonitor(getExecutor(), null) { - @Override - public void handleCompleted() { - if (isSuccess()) { - fReverseTraceMethod = getData().getReverseMethod(); - } else { - // Use a default value in case of error - fReverseTraceMethod = ReverseDebugMethod.SOFTWARE; + // With GDB 7.12, we are provided with the type of record + // that was started. + ReverseDebugMethod newMethod = getTraceMethodFromOutput(notifyOutput); + if (newMethod != null) { + setReverseTraceMethod(newMethod); + } else { + // Don't know what the new method is. Let's ask GDB + getConnection().queueCommand( + fCommandFactory.createCLIInfoRecord(getConnection().getContext()), + new DataRequestMonitor(getExecutor(), null) { + @Override + public void handleCompleted() { + if (isSuccess()) { + setReverseTraceMethod(getData().getReverseMethod()); + } else { + // Use a default value in case of error + setReverseTraceMethod(ReverseDebugMethod.SOFTWARE); + } } - setReverseModeEnabled(true); - } - }); + }); + } } } } } } } + + /** + * @return The ReverseDebugMethod as specified by the =record-started event. + * Returns null if the event does provide that information (GDB < 7.12) + */ + private ReverseDebugMethod getTraceMethodFromOutput(MINotifyAsyncOutput notifyOutput) { + // With GDB 7.12, we are provided with the type of record + // that was started. + // =record-started,thread-group="i1",method="btrace",format="bts" + // =record-started,thread-group="i1",method="btrace",format="pt" + // =record-started,thread-group="i1",method="full" + + String methodStr = ""; //$NON-NLS-1$ + String formatStr = ""; //$NON-NLS-1$ + MIResult[] results = notifyOutput.getMIResults(); + for (int i = 0; i < results.length; i++) { + String var = results[i].getVariable(); + MIValue val = results[i].getMIValue(); + if (var.equals("method")) { //$NON-NLS-1$ + if (val instanceof MIConst) { + methodStr = ((MIConst)val).getString(); + } + } else if (var.equals("format")) { //$NON-NLS-1$ + if (val instanceof MIConst) { + formatStr = ((MIConst)val).getString(); + } + } + } + + if (methodStr.equals("full")) { //$NON-NLS-1$ + assert formatStr.isEmpty() : "Unexpected format string for full method in =record-started: " + formatStr; //$NON-NLS-1$ + return ReverseDebugMethod.SOFTWARE; + } + + if (methodStr.equals("btrace")){ //$NON-NLS-1$ + if (formatStr.equals("bts")) { //$NON-NLS-1$ + return ReverseDebugMethod.BRANCH_TRACE; + } else if (formatStr.equals("pt")) { //$NON-NLS-1$ + return ReverseDebugMethod.PROCESSOR_TRACE; + } else { + assert false : "Unexpected format string for bts method in =record-started: " + formatStr; //$NON-NLS-1$ + } + } + + // No "method" field matching what we expect, so this must be GDB that does not provide that field + assert methodStr.isEmpty() : "Unexpected trace method in =record-started: " + methodStr; //$NON-NLS-1$ + assert formatStr.isEmpty() : "Unexpected format string in =record-started: " + formatStr; //$NON-NLS-1$ + + return null; + } }