1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-06 17:26:01 +02:00

[274135] Changes to support GDB HEAD, to lead to the proper support of GDB 7.0

This commit is contained in:
Marc Khouzam 2009-05-06 17:50:13 +00:00
parent f9f6f4d46a
commit 2d2e01d6f4
4 changed files with 154 additions and 96 deletions

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.dsf.gdb.service; package org.eclipse.cdt.dsf.gdb.service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Iterator; import java.util.Iterator;
@ -341,12 +342,21 @@ public class GDBProcesses_7_0 extends AbstractDsfService
private Map<String, String> fThreadToGroupMap = new HashMap<String, String>(); private Map<String, String> fThreadToGroupMap = new HashMap<String, String>();
private IGDBControl fCommandControl; private IGDBControl fCommandControl;
private IGDBBackend fBackend;
// A cache for commands about the threadGroups // A cache for commands about the threadGroups
private CommandCache fContainerCommandCache; private CommandCache fContainerCommandCache;
//A cache for commands about the threads //A cache for commands about the threads
private CommandCache fThreadCommandCache; private CommandCache fThreadCommandCache;
// A temporary cache to avoid using -list-thread-groups --available more than once at the same time.
// We cannot cache this command because it lists all available processes, which can
// change at any time. However, it is inefficient to send more than one of this command at
// the same time. This cache will help us avoid that. The idea is that we cache the command,
// but as soon as it returns, we clear the cache. So the cache will only trigger for those
// overlapping situations.
private CommandCache fListThreadGroupsAvailableCache;
// A map of process id to process names. It is filled when we get all the processes that are running // A map of process id to process names. It is filled when we get all the processes that are running
private Map<String, String> fProcessNames = new HashMap<String, String>(); private Map<String, String> fProcessNames = new HashMap<String, String>();
@ -384,10 +394,15 @@ public class GDBProcesses_7_0 extends AbstractDsfService
private void doInitialize(RequestMonitor requestMonitor) { private void doInitialize(RequestMonitor requestMonitor) {
fCommandControl = getServicesTracker().getService(IGDBControl.class); fCommandControl = getServicesTracker().getService(IGDBControl.class);
fBackend = getServicesTracker().getService(IGDBBackend.class);
fContainerCommandCache = new CommandCache(getSession(), fCommandControl); fContainerCommandCache = new CommandCache(getSession(), fCommandControl);
fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true); fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true);
fThreadCommandCache = new CommandCache(getSession(), fCommandControl); fThreadCommandCache = new CommandCache(getSession(), fCommandControl);
fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true); fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true);
fListThreadGroupsAvailableCache = new CommandCache(getSession(), fCommandControl);
fListThreadGroupsAvailableCache.setContextAvailable(fCommandControl.getContext(), true);
getSession().addServiceEventListener(this, null); getSession().addServiceEventListener(this, null);
fCommandControl.addEventListener(this); fCommandControl.addEventListener(this);
@ -447,6 +462,21 @@ public class GDBProcesses_7_0 extends AbstractDsfService
public IMIContainerDMContext createContainerContextFromThreadId(ICommandControlDMContext controlDmc, String threadId) { public IMIContainerDMContext createContainerContextFromThreadId(ICommandControlDMContext controlDmc, String threadId) {
String groupId = fThreadToGroupMap.get(threadId); String groupId = fThreadToGroupMap.get(threadId);
if (groupId == null) {
// this can happen if the threadId was 'all'
// In such a case, we choose the first process we find
// This works when we run a single process
// but will break for multi-process!!!
if (fThreadToGroupMap.isEmpty()) {
groupId = MIProcesses.UNIQUE_GROUP_ID;
} else {
Collection<String> values = fThreadToGroupMap.values();
for (String value : values) {
groupId = value;
break;
}
}
}
IProcessDMContext processDmc = createProcessContext(controlDmc, groupId); IProcessDMContext processDmc = createProcessContext(controlDmc, groupId);
return createContainerContext(processDmc, groupId); return createContainerContext(processDmc, groupId);
} }
@ -471,42 +501,58 @@ public class GDBProcesses_7_0 extends AbstractDsfService
public void getExecutionData(IThreadDMContext dmc, final DataRequestMonitor<IThreadDMData> rm) { public void getExecutionData(IThreadDMContext dmc, final DataRequestMonitor<IThreadDMData> rm) {
if (dmc instanceof IMIProcessDMContext) { if (dmc instanceof IMIProcessDMContext) {
final String id = ((IMIProcessDMContext)dmc).getProcId(); if (fBackend.getSessionType() == SessionType.CORE) {
String name = fProcessNames.get(id); // For the Core session, the process is no longer running.
if (name == null) { // Therefore, we cannot get its name with the -list-thread-groups command
// We don't have the name yet. Maybe we didn't fetch names yet, // Instead, we take it from the binary we are using.
// or maybe this is a new process String name = fBackend.getProgramPath().lastSegment();
// This is not very efficient, but GDB does not provide a way to get the name // Also, the pid we get from GDB is 1, which is not correct.
// of a single process. // I haven't found a good way to get the pid yet, so let's not show it.
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); rm.setData(new MIThreadDMData(name, null));
fCommandControl.queueCommand( rm.done();
new MIListThreadGroups(controlDmc, true), } else {
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { final String id = ((IMIProcessDMContext)dmc).getProcId();
@Override String name = fProcessNames.get(id);
protected void handleCompleted() { if (name == null) {
String name = null; // We don't have the name yet. Maybe we didn't fetch names yet,
if (isSuccess()) { // or maybe this is a new process
for (IThreadGroupInfo groupInfo : getData().getGroupList()) { // This is not very efficient, but GDB does not provide a way to get the name
fProcessNames.put(groupInfo.getPid(), groupInfo.getName()); // of a single process.
if (groupInfo.getPid().equals(id)) { ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
name = groupInfo.getName(); fListThreadGroupsAvailableCache.execute(
new MIListThreadGroups(controlDmc, true),
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
@Override
protected void handleCompleted() {
// We cannot actually cache this command since the process
// list may change. But this cache allows to avoid overlapping
// sending of this command.
fListThreadGroupsAvailableCache.reset();
String name = null;
if (isSuccess()) {
for (IThreadGroupInfo groupInfo : getData().getGroupList()) {
fProcessNames.put(groupInfo.getPid(), groupInfo.getName());
if (groupInfo.getPid().equals(id)) {
name = groupInfo.getName();
}
} }
} }
}
if (name == null) {
// We still don't have the name... weird.
// Don't go into an infinite loop by trying again, just give up
name = "Unknown name"; //$NON-NLS-1$
}
rm.setData(new MIThreadDMData(name, id));
rm.done();
}
});
} else { if (name == null) {
rm.setData(new MIThreadDMData(name, id)); // We still don't have the name... weird.
rm.done(); // Don't go into an infinite loop by trying again, just give up
name = "Unknown name"; //$NON-NLS-1$
}
rm.setData(new MIThreadDMData(name, id));
rm.done();
}
});
} else {
rm.setData(new MIThreadDMData(name, id));
rm.done();
}
} }
} else if (dmc instanceof MIThreadDMC) { } else if (dmc instanceof MIThreadDMC) {
final MIThreadDMC threadDmc = (MIThreadDMC)dmc; final MIThreadDMC threadDmc = (MIThreadDMC)dmc;
@ -554,15 +600,28 @@ public class GDBProcesses_7_0 extends AbstractDsfService
rm.done(); rm.done();
} }
public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) { private boolean doIsDebuggerAttachSupported() {
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class); IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
rm.setData(backend.getIsAttachSession()); if (backend != null) {
return backend.getIsAttachSession();
}
return false;
}
public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
rm.setData(doIsDebuggerAttachSupported());
rm.done(); rm.done();
} }
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) { public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
if (procCtx instanceof IMIProcessDMContext) { if (procCtx instanceof IMIProcessDMContext) {
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class); if (!doIsDebuggerAttachSupported()) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
rm.done();
return;
}
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
fCommandControl.queueCommand( fCommandControl.queueCommand(
new MITargetAttach(controlDmc, ((IMIProcessDMContext)procCtx).getProcId()), new MITargetAttach(controlDmc, ((IMIProcessDMContext)procCtx).getProcId()),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) { new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@ -580,19 +639,33 @@ public class GDBProcesses_7_0 extends AbstractDsfService
rm.done(); rm.done();
} }
} }
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) { private boolean doCanDetachDebuggerFromProcess() {
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class); IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
rm.setData(backend.getIsAttachSession() && fCommandControl.isConnected()); if (backend != null) {
return backend.getIsAttachSession() && fCommandControl.isConnected();
}
return false;
}
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
rm.setData(doCanDetachDebuggerFromProcess());
rm.done(); rm.done();
} }
public void detachDebuggerFromProcess(final IDMContext dmc, final RequestMonitor rm) { public void detachDebuggerFromProcess(final IDMContext dmc, final RequestMonitor rm) {
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc, IMIProcessDMContext.class); IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc, IMIProcessDMContext.class);
if (controlDmc != null && procDmc != null) { if (controlDmc != null && procDmc != null) {
fCommandControl.queueCommand( if (!doCanDetachDebuggerFromProcess()) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Detach not supported.", null)); //$NON-NLS-1$
rm.done();
return;
}
fCommandControl.queueCommand(
new MITargetDetach(controlDmc, procDmc.getProcId()), new MITargetDetach(controlDmc, procDmc.getProcId()),
new DataRequestMonitor<MIInfo>(getExecutor(), rm)); new DataRequestMonitor<MIInfo>(getExecutor(), rm));
} else { } else {
@ -619,38 +692,29 @@ public class GDBProcesses_7_0 extends AbstractDsfService
} }
public void getProcessesBeingDebugged(final IDMContext dmc, final DataRequestMonitor<IDMContext[]> rm) { public void getProcessesBeingDebugged(final IDMContext dmc, final DataRequestMonitor<IDMContext[]> rm) {
// MIInferiorProcess inferiorProcess = fCommandControl.getInferiorProcess(); final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
// if (fCommandControl.isConnected() && final IMIContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class);
// inferiorProcess != null && if (containerDmc != null) {
// inferiorProcess.getState() != MIInferiorProcess.State.TERMINATED) { fThreadCommandCache.execute(
new MIListThreadGroups(controlDmc, containerDmc.getGroupId()),
final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
final IMIContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class); @Override
if (containerDmc != null) { protected void handleSuccess() {
fThreadCommandCache.execute( rm.setData(makeExecutionDMCs(containerDmc, getData().getThreadInfo().getThreadList()));
new MIListThreadGroups(controlDmc, containerDmc.getGroupId()), rm.done();
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { }
@Override });
protected void handleSuccess() { } else {
rm.setData(makeExecutionDMCs(containerDmc, getData().getThreadInfo().getThreadList())); fContainerCommandCache.execute(
rm.done(); new MIListThreadGroups(controlDmc),
} new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
}); @Override
} else { protected void handleSuccess() {
fContainerCommandCache.execute( rm.setData(makeContainerDMCs(controlDmc, getData().getGroupList()));
new MIListThreadGroups(controlDmc), rm.done();
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { }
@Override });
protected void handleSuccess() { }
rm.setData(makeContainerDMCs(controlDmc, getData().getGroupList()));
rm.done();
}
});
}
// } else {
// rm.setData(new IDMContext[0]);
// rm.done();
// }
} }
private IExecutionDMContext[] makeExecutionDMCs(IContainerDMContext containerDmc, MIThread[] threadInfos) { private IExecutionDMContext[] makeExecutionDMCs(IContainerDMContext containerDmc, MIThread[] threadInfos) {
@ -693,11 +757,16 @@ public class GDBProcesses_7_0 extends AbstractDsfService
if (controlDmc != null) { if (controlDmc != null) {
// Don't cache this command since the list can change at any time. // Don't cache this command since the list can change at any time.
fCommandControl.queueCommand( fListThreadGroupsAvailableCache.execute(
new MIListThreadGroups(controlDmc, true), new MIListThreadGroups(controlDmc, true),
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
// We cannot actually cache this command since the process
// list may change. But this cache allows to avoid overlapping
// sending of this command.
fListThreadGroupsAvailableCache.reset();
if (isSuccess()) { if (isSuccess()) {
for (IThreadGroupInfo groupInfo : getData().getGroupList()) { for (IThreadGroupInfo groupInfo : getData().getGroupList()) {
fProcessNames.put(groupInfo.getPid(), groupInfo.getName()); fProcessNames.put(groupInfo.getPid(), groupInfo.getName());
@ -737,12 +806,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
} }
public void terminate(IThreadDMContext thread, RequestMonitor rm) { public void terminate(IThreadDMContext thread, RequestMonitor rm) {
if (thread instanceof IMIProcessDMContext) { fCommandControl.terminate(rm);
fCommandControl.terminate(rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
rm.done();
}
} }
@DsfServiceEventHandler @DsfServiceEventHandler
@ -757,7 +821,6 @@ public class GDBProcesses_7_0 extends AbstractDsfService
IProcessDMContext procDmc = e.getDMContext(); IProcessDMContext procDmc = e.getDMContext();
IMIContainerDMContext containerDmc = e.getGroupId() != null ? createContainerContext(procDmc, e.getGroupId()) : null; IMIContainerDMContext containerDmc = e.getGroupId() != null ? createContainerContext(procDmc, e.getGroupId()) : null;
getSession().dispatchEvent(new ContainerExitedDMEvent(containerDmc), getProperties()); getSession().dispatchEvent(new ContainerExitedDMEvent(containerDmc), getProperties());
} }
@DsfServiceEventHandler @DsfServiceEventHandler
@ -777,8 +840,8 @@ public class GDBProcesses_7_0 extends AbstractDsfService
public void eventDispatched(ISuspendedDMEvent e) { public void eventDispatched(ISuspendedDMEvent e) {
if (e instanceof IContainerSuspendedDMEvent) { if (e instanceof IContainerSuspendedDMEvent) {
// This will happen in all-stop mode // This will happen in all-stop mode
fContainerCommandCache.setContextAvailable(e.getDMContext(), true); fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true);
fThreadCommandCache.setContextAvailable(e.getDMContext(), true); fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true);
} else { } else {
// This will happen in non-stop mode // This will happen in non-stop mode
} }
@ -843,13 +906,6 @@ public class GDBProcesses_7_0 extends AbstractDsfService
} }
} }
// Until GDB is officially supporting multi-process, we may not get
// a groupId. In this case, we are running single process and we'll
// need its groupId
if (groupId == null) {
groupId = MIProcesses.UNIQUE_GROUP_ID;
}
if ("thread-created".equals(miEvent)) { //$NON-NLS-1$ if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
// Update the thread to groupId map with the new groupId // Update the thread to groupId map with the new groupId
fThreadToGroupMap.put(threadId, groupId); fThreadToGroupMap.put(threadId, groupId);

View file

@ -42,7 +42,7 @@ import org.eclipse.debug.core.ILaunchConfiguration;
public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
// This should eventually be "7.0" once GDB 7.0 is released // This should eventually be "7.0" once GDB 7.0 is released
private static final String GDB_7_0_VERSION = "6.8.50.20081118"; //$NON-NLS-1$ private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$
private final String fVersion; private final String fVersion;
@ -123,10 +123,7 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
@Override @Override
protected IProcesses createProcessesService(DsfSession session) { protected IProcesses createProcessesService(DsfSession session) {
// Multi-process is not part of GDB HEAD yet, if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
// but is part of this very specific build.
// We'll need to change this when 7.0 is ready
if (fVersion.startsWith("6.8.50.20090218")) { //$NON-NLS-1$
return new GDBProcesses_7_0(session); return new GDBProcesses_7_0(session);
} }
return new GDBProcesses(session); return new GDBProcesses(session);

View file

@ -289,7 +289,7 @@ public class MIRunControlEventProcessor_7_0
} }
IExecutionDMContext execDmc = containerDmc; IExecutionDMContext execDmc = containerDmc;
if (threadId != null) { if (threadId != null && !threadId.equals("all")) { //$NON-NLS-1$
IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId); IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId); execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId);
} }

View file

@ -26,7 +26,8 @@ import org.eclipse.cdt.dsf.concurrent.Immutable;
* {id="162",type="process",description="name: JIM_TcpSetupHandlerProcess, type 555505, locked: N, system: N, state: Idle"}, * {id="162",type="process",description="name: JIM_TcpSetupHandlerProcess, type 555505, locked: N, system: N, state: Idle"},
* {id="165",type="process",description="name: JUnitProcess2_PT, type 1094608, locked: N, system: N, state: Idle"}, * {id="165",type="process",description="name: JUnitProcess2_PT, type 1094608, locked: N, system: N, state: Idle"},
* {id="166",type="process",description="name: JUnitProcess_PT, type 1094605, locked: N, system: N, state: Idle"}] * {id="166",type="process",description="name: JUnitProcess_PT, type 1094605, locked: N, system: N, state: Idle"}]
* *
* {id="3602",type="process",description="/usr/sbin/dhcdbd --system",user="root"}
* -list-thread-groups: * -list-thread-groups:
* ^done,groups=[{id="162",type="process",pid="162"}] * ^done,groups=[{id="162",type="process",pid="162"}]
* *
@ -66,6 +67,10 @@ public class MIListThreadGroupsInfo extends MIInfo {
Matcher matcher = pattern.matcher(desc); Matcher matcher = pattern.matcher(desc);
if (matcher.find()) { if (matcher.find()) {
name = matcher.group(1); name = matcher.group(1);
} else {
// If we didn't get the form "name: " then we expect to have the form
// "/usr/sbin/dhcdbd --system"
name = desc.split("\\s", 2)[0]; //$NON-NLS-1$
} }
return name; return name;