1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 489513 - Show registers in the traditional memory render

Change-Id: I9ddbbeb9c8345f006004d9d2982a778d28c6d68c
This commit is contained in:
Alvaro Sanchez-Leon 2016-03-13 18:07:16 -04:00 committed by Gerrit Code Review @ Eclipse.org
parent 6bdca5f4a2
commit b2db3a489c
2 changed files with 241 additions and 1 deletions

View file

@ -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.IRegisters.IRegisterChangedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; 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.internal.memory.GdbMemoryAddressInfoVariablesRetrieval;
import org.eclipse.cdt.dsf.gdb.memory.IGdbMemoryAddressInfoTypeRetrieval; import org.eclipse.cdt.dsf.gdb.memory.IGdbMemoryAddressInfoTypeRetrieval;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
@ -47,7 +48,7 @@ public class GdbMemoryBlockAddressInfoRetrieval implements IMemoryBlockAddressIn
} }
protected IGdbMemoryAddressInfoTypeRetrieval[] resolveMemoryAddressInfoProviders() { protected IGdbMemoryAddressInfoTypeRetrieval[] resolveMemoryAddressInfoProviders() {
return new IGdbMemoryAddressInfoTypeRetrieval[] {new GdbMemoryAddressInfoVariablesRetrieval(fSession)}; return new IGdbMemoryAddressInfoTypeRetrieval[] {new GdbMemoryAddressInfoVariablesRetrieval(fSession), new GdbMemoryAddressInfoRegistersRetrieval(fSession)};
} }
@Override @Override

View file

@ -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<IMemoryBlockAddressInfoItem[]> 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<IRegisterDMContext[]>(executor, rm) {
@Override
protected void handleSuccess() {
final IRegisterDMContext[] registers = getData();
if (registers != null && registers.length != 0) {
// Resolve register data
getRegistersData(service, registers,
new DataRequestMonitor<IRegisterDMData[]>(fSession.getExecutor(), rm) {
@Override
protected void handleSuccess() {
final IRegisterDMData[] regBaseData = getData();
// Resolve register values
getRegisterValues(service, registers,
new DataRequestMonitor<FormattedValueDMData[]>(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<IMemoryBlockAddressInfoItem> items = new ArrayList<IMemoryBlockAddressInfoItem>();
// 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> V resolveService(Class<V> 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<IRegisterDMData[]> 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<IRegisterDMData>(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<FormattedValueDMData[]> 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<FormattedValueDMData>(fSession.getExecutor(), countingRm) {
@Override
protected void handleCompleted() {
datas[index] = getData();
if (!isSuccess()) {
countingRm.setStatus(getStatus());
}
countingRm.done();
}
});
}
countingRm.setDoneCount(regDMCs.length);
}
}