mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 532297: Cache registers per version of GDB
Change-Id: I2da702830f01035b99dc61fcdfb9e7a43fcc8d55
This commit is contained in:
parent
b4ac2d3ebf
commit
9537e51cf3
3 changed files with 74 additions and 108 deletions
|
@ -16,13 +16,16 @@
|
|||
package org.eclipse.cdt.tests.dsf.gdb.framework;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
@ -74,6 +77,7 @@ import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataListRegisterNamesInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.DefaultTimeouts.ETimeout;
|
||||
|
@ -100,11 +104,18 @@ public class SyncUtil {
|
|||
|
||||
private static ISourceLookup fSourceLookup;
|
||||
|
||||
// Static list of register names as obtained directly from GDB.
|
||||
// We make it static, key'ed on each version of gdb, so it does not
|
||||
// get re-set for every test.
|
||||
// Each version of GDB can expose the set of register differently
|
||||
private static Map<String, List<String>> fRegisterNames = new HashMap<>();
|
||||
|
||||
// Initialize some common things, once the session has been established
|
||||
public static void initialize(DsfSession session) throws Exception {
|
||||
fSession = session;
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
DsfServicesTracker tracker = new DsfServicesTracker(
|
||||
|
@ -857,6 +868,49 @@ public class SyncUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registers directly from GDB (without using the registers service)
|
||||
* @param gdbVersion
|
||||
* @param context
|
||||
* @return
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static List<String> getRegistersFromGdb(String gdbVersion, IDMContext context) throws Throwable {
|
||||
if (!fRegisterNames.containsKey(gdbVersion)) {
|
||||
// The tests must run on different machines, so the set of registers can change.
|
||||
// To deal with this we ask GDB for the list of registers.
|
||||
// Note that we send an MI Command in this code and do not use the IRegister service;
|
||||
// this is because we want to test the service later, comparing it to what we find
|
||||
// by asking GDB directly.
|
||||
Query<MIDataListRegisterNamesInfo> query = new Query<MIDataListRegisterNamesInfo>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<MIDataListRegisterNamesInfo> rm) {
|
||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(context, IContainerDMContext.class);
|
||||
fGdbControl.queueCommand(
|
||||
fGdbControl.getCommandFactory().createMIDataListRegisterNames(containerDmc), rm);
|
||||
}
|
||||
};
|
||||
fSession.getExecutor().execute(query);
|
||||
|
||||
MIDataListRegisterNamesInfo data = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
|
||||
String[] names = data.getRegisterNames();
|
||||
|
||||
// Remove registers with empty names since the service also
|
||||
// remove them. I don't know why GDB returns such empty names.
|
||||
List<String> registerNames = new LinkedList<String>();
|
||||
for (String name : names) {
|
||||
if (!name.isEmpty()) {
|
||||
registerNames.add(name);
|
||||
}
|
||||
}
|
||||
assertNotEquals(
|
||||
"Test does not make sense, and has probably completely failed, as there are no register names",
|
||||
Collections.emptyList(), registerNames);
|
||||
fRegisterNames.put(gdbVersion, registerNames);
|
||||
}
|
||||
return fRegisterNames.get(gdbVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from memory.
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
|
@ -37,22 +38,18 @@ import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContex
|
|||
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.IRegisters2;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.ClassAccessor.MIExpressionDMCAccessor;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExpressions;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIRegisters.MIRegisterDMC;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataListRegisterNamesInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseParametrizedTestCase;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
@ -106,53 +103,12 @@ public class GDBPatternMatchingExpressionsTest extends BaseParametrizedTestCase
|
|||
//**************************************************************************************
|
||||
// Utility methods
|
||||
//**************************************************************************************
|
||||
|
||||
// Static list of register names as obtained directly from GDB.
|
||||
// We make it static so it does not get re-set for every test
|
||||
protected static List<String> fRegisterNames = null;
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeGlobals() {
|
||||
// In case we run multiple GDB versions of this test
|
||||
// in the same suite, we need to re-initialize the registers
|
||||
// as they may change between GDB versions.
|
||||
fRegisterNames = null;
|
||||
}
|
||||
|
||||
protected List<String> get_X86_REGS() throws Throwable {
|
||||
|
||||
if (fRegisterNames == null) {
|
||||
// The tests must run on different machines, so the set of registers can change.
|
||||
// To deal with this we ask GDB for the list of registers.
|
||||
// Note that we send an MI Command in this code and do not use the IRegister service;
|
||||
// this is because we want to test the service later, comparing it to what we find
|
||||
// by asking GDB directly.
|
||||
final IContainerDMContext container = SyncUtil.getContainerContext();
|
||||
Query<MIDataListRegisterNamesInfo> query = new Query<MIDataListRegisterNamesInfo>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<MIDataListRegisterNamesInfo> rm) {
|
||||
IMICommandControl controlService = fServicesTracker.getService(IMICommandControl.class);
|
||||
controlService.queueCommand(
|
||||
controlService.getCommandFactory().createMIDataListRegisterNames(container), rm);
|
||||
}
|
||||
};
|
||||
fSession.getExecutor().execute(query);
|
||||
|
||||
MIDataListRegisterNamesInfo data = query.get();
|
||||
String[] names = data.getRegisterNames();
|
||||
|
||||
// Remove registers with empty names since the service also
|
||||
// remove them. I don't know why GDB returns such empty names.
|
||||
fRegisterNames = new LinkedList<String>();
|
||||
for (String name : names) {
|
||||
if (!name.isEmpty()) {
|
||||
// Add the '$' prefix
|
||||
fRegisterNames.add("$"+name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return a copy since it will be modified by each test
|
||||
return new LinkedList<String>(fRegisterNames);
|
||||
/**
|
||||
* Return a new, mutable list with '$' prefixed on each register
|
||||
*/
|
||||
protected List<String> getRegistersFromGdb() throws Throwable {
|
||||
List<String> registersFromGdb = SyncUtil.getRegistersFromGdb(getGdbVersion(), SyncUtil.getContainerContext());
|
||||
return registersFromGdb.stream().map(n -> "$" + n).collect(Collectors.toCollection(LinkedList::new));
|
||||
}
|
||||
|
||||
final static String[] fAllVariables = new String[] { "firstarg", "firstvar", "ptrvar", "secondarg", "secondvar", "var", "var2" };
|
||||
|
@ -343,7 +299,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseParametrizedTestCase
|
|||
public void testMatchAllRegs() throws Throwable {
|
||||
final String exprString = "$*";
|
||||
final String exprString2 = "=$*";
|
||||
List<String> regList = get_X86_REGS();
|
||||
List<String> regList = getRegistersFromGdb();
|
||||
Collections.sort(regList);
|
||||
final String[] children = regList.toArray(new String[0]);
|
||||
|
||||
|
@ -1060,7 +1016,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseParametrizedTestCase
|
|||
@Test
|
||||
public void testGroupAllRegsAllLocals() throws Throwable {
|
||||
final String exprString = "$*; *";
|
||||
List<String> list = get_X86_REGS();
|
||||
List<String> list = getRegistersFromGdb();
|
||||
Collections.sort(list);
|
||||
list.addAll(Arrays.asList(fAllVariables));
|
||||
final String[] children = list.toArray(new String[list.size()]);
|
||||
|
@ -1083,7 +1039,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseParametrizedTestCase
|
|||
@Test
|
||||
public void testGroupAllLocalsAllRegs() throws Throwable {
|
||||
final String exprString = "*; $*";
|
||||
List<String> list = get_X86_REGS();
|
||||
List<String> list = getRegistersFromGdb();
|
||||
Collections.sort(list);
|
||||
list.addAll(0, Arrays.asList(fAllVariables));
|
||||
final String[] children = list.toArray(new String[list.size()]);
|
||||
|
@ -1123,7 +1079,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseParametrizedTestCase
|
|||
@Test
|
||||
public void testGroupOneLocalAllReg() throws Throwable {
|
||||
final String exprString = "firstvar; $*";
|
||||
List<String> list = get_X86_REGS();
|
||||
List<String> list = getRegistersFromGdb();
|
||||
Collections.sort(list);
|
||||
list.addAll(0, Arrays.asList(new String[] { "firstvar" }));
|
||||
final String[] children = list.toArray(new String[list.size()]);
|
||||
|
@ -1205,7 +1161,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseParametrizedTestCase
|
|||
@Test
|
||||
public void testSortedAllReg() throws Throwable {
|
||||
final String exprString = "$*";
|
||||
List<String> regList = get_X86_REGS();
|
||||
List<String> regList = getRegistersFromGdb();
|
||||
Collections.sort(regList);
|
||||
final String[] children = regList.toArray(new String[0]);
|
||||
|
||||
|
@ -1250,7 +1206,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseParametrizedTestCase
|
|||
@Test
|
||||
public void testSeparatlySorted() throws Throwable {
|
||||
final String exprString = "$*; *";
|
||||
List<String> list = get_X86_REGS();
|
||||
List<String> list = getRegistersFromGdb();
|
||||
Collections.sort(list);
|
||||
List<String> localsList = Arrays.asList(fAllVariables);
|
||||
Collections.sort(localsList);
|
||||
|
|
|
@ -24,7 +24,6 @@ import static org.junit.Assert.fail;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -57,65 +56,22 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
|||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBRegisters;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIRegisters.MIRegisterDMC;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataListRegisterNamesInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseParametrizedTestCase;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceEventWaitor;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class MIRegistersTest extends BaseParametrizedTestCase {
|
||||
// Static list of register names as obtained directly from GDB.
|
||||
// We make it static it does not get re-set for every test
|
||||
protected static List<String> fRegisterNames = null;
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeGlobals() {
|
||||
// In case we run multiple GDB versions of this test
|
||||
// in the same suite, we need to re-initialize the registers
|
||||
// as they may change between GDB versions.
|
||||
fRegisterNames = null;
|
||||
}
|
||||
|
||||
protected List<String> get_X86_REGS() throws Throwable {
|
||||
if (fRegisterNames == null) {
|
||||
// The tests must run on different machines, so the set of registers can change.
|
||||
// To deal with this we ask GDB for the list of registers.
|
||||
// Note that we send an MI Command in this code and do not use the IRegister service;
|
||||
// this is because we want to test the service later, comparing it to what we find
|
||||
// by asking GDB directly.
|
||||
Query<MIDataListRegisterNamesInfo> query = new Query<MIDataListRegisterNamesInfo>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<MIDataListRegisterNamesInfo> rm) {
|
||||
IMICommandControl controlService = fServicesTracker.getService(IMICommandControl.class);
|
||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(fCompositeDmc, IContainerDMContext.class);
|
||||
controlService.queueCommand(controlService.getCommandFactory().createMIDataListRegisterNames(containerDmc), rm);
|
||||
}
|
||||
};
|
||||
fSession.getExecutor().execute(query);
|
||||
|
||||
MIDataListRegisterNamesInfo data = query.get();
|
||||
String[] names = data.getRegisterNames();
|
||||
|
||||
// Remove registers with empty names since the service also
|
||||
// remove them. I don't know why GDB returns such empty names.
|
||||
fRegisterNames = new LinkedList<String>();
|
||||
for (String name : names) {
|
||||
if (!name.isEmpty()) {
|
||||
fRegisterNames.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fRegisterNames;
|
||||
protected List<String> getRegistersFromGdb() throws Throwable {
|
||||
return SyncUtil.getRegistersFromGdb(getGdbVersion(), fCompositeDmc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -214,7 +170,7 @@ public class MIRegistersTest extends BaseParametrizedTestCase {
|
|||
|
||||
IRegisterDMContext[] regContexts = queryRegisters.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
|
||||
|
||||
assertEquals("Wrong number of registers", get_X86_REGS().size(), regContexts.length);
|
||||
assertEquals("Wrong number of registers", getRegistersFromGdb().size(), regContexts.length);
|
||||
|
||||
return regContexts;
|
||||
}
|
||||
|
@ -242,7 +198,7 @@ public class MIRegistersTest extends BaseParametrizedTestCase {
|
|||
*/
|
||||
private IRegisterDMContext[] getTargetRegisters(final IFrameDMContext frameDmc) throws Throwable {
|
||||
IRegisterDMContext[] regContexts = getRegisters(new CompositeDMContext(new IDMContext[] { fCompositeDmc, frameDmc}));
|
||||
assertEquals("Wrong number of registers", get_X86_REGS().size(), regContexts.length);
|
||||
assertEquals("Wrong number of registers", getRegistersFromGdb().size(), regContexts.length);
|
||||
|
||||
return regContexts;
|
||||
}
|
||||
|
@ -265,7 +221,7 @@ public class MIRegistersTest extends BaseParametrizedTestCase {
|
|||
MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
|
||||
IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
|
||||
final IRegisterDMContext[] regDMCs = getAllRegisters(frameDmc);
|
||||
assertEquals("Wrong number of registers", get_X86_REGS().size(), regDMCs.length);
|
||||
assertEquals("Wrong number of registers", getRegistersFromGdb().size(), regDMCs.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -273,7 +229,7 @@ public class MIRegistersTest extends BaseParametrizedTestCase {
|
|||
MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
|
||||
IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
|
||||
final IRegisterDMContext[] regDMCs = getAllRegisters(frameDmc);
|
||||
List<String> regNames = get_X86_REGS();
|
||||
List<String> regNames = getRegistersFromGdb();
|
||||
|
||||
IRegisterDMData[] datas = getRegistersData(regDMCs);
|
||||
|
||||
|
@ -547,7 +503,7 @@ public class MIRegistersTest extends BaseParametrizedTestCase {
|
|||
}
|
||||
|
||||
private String resolveStackPointerName() throws Throwable {
|
||||
List<String> regNames = get_X86_REGS();
|
||||
List<String> regNames = getRegistersFromGdb();
|
||||
|
||||
// for 64 bits
|
||||
String sp_name = "rsp";
|
||||
|
|
Loading…
Add table
Reference in a new issue