diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/memory/GdbMemoryBlockAddressInfoRetrieval.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/memory/GdbMemoryBlockAddressInfoRetrieval.java index f126ebb1f43..04845fbe0e1 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/memory/GdbMemoryBlockAddressInfoRetrieval.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/memory/GdbMemoryBlockAddressInfoRetrieval.java @@ -24,6 +24,7 @@ import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionChangedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterChangedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; +import org.eclipse.cdt.dsf.gdb.internal.memory.GdbMemoryAddressInfoRegistersRetrieval; import org.eclipse.cdt.dsf.gdb.internal.memory.GdbMemoryAddressInfoVariablesRetrieval; import org.eclipse.cdt.dsf.gdb.memory.IGdbMemoryAddressInfoTypeRetrieval; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; @@ -47,7 +48,7 @@ public class GdbMemoryBlockAddressInfoRetrieval implements IMemoryBlockAddressIn } protected IGdbMemoryAddressInfoTypeRetrieval[] resolveMemoryAddressInfoProviders() { - return new IGdbMemoryAddressInfoTypeRetrieval[] {new GdbMemoryAddressInfoVariablesRetrieval(fSession)}; + return new IGdbMemoryAddressInfoTypeRetrieval[] {new GdbMemoryAddressInfoVariablesRetrieval(fSession), new GdbMemoryAddressInfoRegistersRetrieval(fSession)}; } @Override diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryAddressInfoRegistersRetrieval.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryAddressInfoRegistersRetrieval.java new file mode 100644 index 00000000000..9c380b899f2 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryAddressInfoRegistersRetrieval.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson 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: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.memory; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.debug.core.model.IMemoryBlockAddressInfoRetrieval.IMemoryBlockAddressInfoItem; +import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; +import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext; +import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData; +import org.eclipse.cdt.dsf.debug.service.IRegisters2; +import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.memory.IGdbMemoryAddressInfoTypeRetrieval; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.model.IMemoryBlock; + +public class GdbMemoryAddressInfoRegistersRetrieval implements IGdbMemoryAddressInfoTypeRetrieval { + + private final static String REGISTERS_INFO_TYPE = "Registers"; //$NON-NLS-1$ + private final DsfSession fSession; + + public GdbMemoryAddressInfoRegistersRetrieval(DsfSession session) { + fSession = session; + } + + @Override + public void itemsRequest(final IDMContext context, final IMemoryBlock memBlock, final DataRequestMonitor rm) { + if (fSession == null || fSession.getExecutor() == null) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Initialization problem, invalid session")); //$NON-NLS-1$ + return; + } + + final DsfExecutor executor = fSession.getExecutor(); + IFrameDMContext frameCtx = DMContexts.getAncestorOfType(context, IFrameDMContext.class); + final IRegisters2 service = resolveService(IRegisters2.class); + + if (frameCtx != null && service != null) { + // Getting all available register contexts + service.getRegisters(frameCtx, new DataRequestMonitor(executor, rm) { + @Override + protected void handleSuccess() { + final IRegisterDMContext[] registers = getData(); + if (registers != null && registers.length != 0) { + // Resolve register data + getRegistersData(service, registers, + new DataRequestMonitor(fSession.getExecutor(), rm) { + @Override + protected void handleSuccess() { + final IRegisterDMData[] regBaseData = getData(); + // Resolve register values + getRegisterValues(service, registers, + new DataRequestMonitor(fSession.getExecutor(), + rm) { + @Override + protected void handleSuccess() { + // Extract the register information needed to build the requested data items + FormattedValueDMData[] regFormattedData = getData(); + String[] regNames = extractRegNames(regBaseData); + String[] regValues = extractValues(regFormattedData); + + // Consolidate the Register information in a container class + IMemoryBlockAddressInfoItem[] regDataContainers = createRegisterDataContainers( + registers, regNames, regValues); + + // Filter or arrange data as needed + regDataContainers = normalizeRegisterData(regDataContainers, memBlock); + + rm.setData(regDataContainers); + rm.done(); + } + }); + + }; + }); + } else { + // no valid registers + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, + "Successful request of register contexts but no registers received")); //$NON-NLS-1$ + } + } + }); + } else { + rm.done(new Status(IStatus.INFO, GdbPlugin.PLUGIN_ID, + "Unable to resolve registers for the currently selected context")); //$NON-NLS-1$ + } + } + + protected IMemoryBlockAddressInfoItem[] normalizeRegisterData(IMemoryBlockAddressInfoItem[] regDataContainers, IMemoryBlock memBlock) { +// // The information provided may be applicable per memory space +// String memSpaceId = ""; //$NON-NLS-1$ +// if (memBlock instanceof IMemorySpaceAwareMemoryBlock) { +// memSpaceId = ((IMemorySpaceAwareMemoryBlock) memBlock).getMemorySpaceID(); +// } + + List items = new ArrayList(); + // Remove all items with value zero + for (IMemoryBlockAddressInfoItem item : regDataContainers) { + if (item.getAddress().intValue() != 0) { + items.add(item); + } + } + + // Add any other filter, value adjustments etc. + + return items.toArray(new IMemoryBlockAddressInfoItem[items.size()]); + } + + @Override + public String getInfoType() { + return REGISTERS_INFO_TYPE; + } + + private class MemoryBlockAddressRegisterItem extends MemoryBlockAddressInfoItem { + public MemoryBlockAddressRegisterItem(String name, String value) { + super(name, value); + } + + @Override + public String getInfoType() { + return REGISTERS_INFO_TYPE; + } + } + + private IMemoryBlockAddressInfoItem[] createRegisterDataContainers(IRegisterDMContext[] regContext, String[] names, + String[] values) { + // Expecting the three building arrays to be of the same length + assert (regContext.length > 0 && regContext.length == names.length && regContext.length == values.length); + IMemoryBlockAddressInfoItem[] regContainers = new IMemoryBlockAddressInfoItem[regContext.length]; + for (int i = 0; i < regContext.length; i++) { + regContainers[i] = new MemoryBlockAddressRegisterItem(names[i], values[i]); + } + + return regContainers; + } + + private String[] extractRegNames(IRegisterDMData[] regData) { + String[] names = new String[regData.length]; + for (int i = 0; i < regData.length; i++) { + names[i] = regData[i].getName(); + } + return names; + } + + private String[] extractValues(FormattedValueDMData[] regValues) { + String[] values = new String[regValues.length]; + for (int i = 0; i < regValues.length; i++) { + values[i] = regValues[i].getEditableValue(); + } + return values; + } + + private V resolveService(Class type) { + V service = null; + if (fSession != null) { + DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getDefault().getBundle().getBundleContext(), + fSession.getId()); + service = tracker.getService(type); + tracker.dispose(); + } + return service; + } + + private void getRegistersData(final IRegisters2 service, final IRegisterDMContext[] regDMCs, + final DataRequestMonitor rm) { + final IRegisterDMData[] datas = new IRegisterDMData[regDMCs.length]; + rm.setData(datas); + final CountingRequestMonitor countingRm = new CountingRequestMonitor(fSession.getExecutor(), rm); + for (int i = 0; i < regDMCs.length; i++) { + final int index = i; + service.getRegisterData(regDMCs[index], + new DataRequestMonitor(fSession.getExecutor(), countingRm) { + @Override + protected void handleCompleted() { + datas[index] = getData(); + if (!isSuccess()) { + countingRm.setStatus(getStatus()); + } + countingRm.done(); + } + }); + } + + countingRm.setDoneCount(regDMCs.length); + } + + private FormattedValueDMContext[] getFormatContexts(IRegisters2 service, IRegisterDMContext[] regDMCs) { + FormattedValueDMContext[] datas = new FormattedValueDMContext[regDMCs.length]; + for (int i = 0; i < regDMCs.length; i++) { + datas[i] = service.getFormattedValueContext(regDMCs[i], IFormattedValues.HEX_FORMAT); + } + + return datas; + } + + private void getRegisterValues(final IRegisters2 service, final IRegisterDMContext[] regDMCs, + final DataRequestMonitor rm) { + FormattedValueDMContext[] fmtContexts = getFormatContexts(service, regDMCs); + + final FormattedValueDMData[] datas = new FormattedValueDMData[regDMCs.length]; + rm.setData(datas); + final CountingRequestMonitor countingRm = new CountingRequestMonitor(fSession.getExecutor(), rm); + for (int i = 0; i < regDMCs.length; i++) { + final int index = i; + service.getFormattedExpressionValue(fmtContexts[index], + new DataRequestMonitor(fSession.getExecutor(), countingRm) { + @Override + protected void handleCompleted() { + datas[index] = getData(); + if (!isSuccess()) { + countingRm.setStatus(getStatus()); + } + countingRm.done(); + } + }); + } + + countingRm.setDoneCount(regDMCs.length); + } +}