From 4edaf1587bbe80033d639fd4992e1b3aeb785c15 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Thu, 9 Oct 2008 19:21:24 +0000 Subject: [PATCH] [248636] Adding --thread option to the MI memory commands for GDB 7.0. This change was done in provisional classes to allow for changes, but required the use of a GDBMemory service. --- .../provisional/service/GDBMemory_7_0.java | 103 ++++++++++++++++++ .../provisional/service/GDBProcesses_7_0.java | 23 +++- .../service/GdbDebugServicesFactory.java | 4 + .../provisional/service/IGDBProcesses.java | 27 +++++ .../org/eclipse/dd/mi/service/MIMemory.java | 26 ++++- 5 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBMemory_7_0.java create mode 100644 plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/IGDBProcesses.java diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBMemory_7_0.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBMemory_7_0.java new file mode 100644 index 00000000000..6ec9aaeddf7 --- /dev/null +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBMemory_7_0.java @@ -0,0 +1,103 @@ +package org.eclipse.dd.gdb.internal.provisional.service; + +import java.util.Hashtable; + +import org.eclipse.cdt.core.IAddress; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.DMContexts; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.service.IMemory; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.mi.service.IMIContainerDMContext; +import org.eclipse.dd.mi.service.IMIExecutionDMContext; +import org.eclipse.dd.mi.service.MIMemory; +import org.eclipse.debug.core.model.MemoryByte; + +public class GDBMemory_7_0 extends MIMemory { + + public GDBMemory_7_0(DsfSession session) { + super(session); + } + + @Override + public void initialize(final RequestMonitor requestMonitor) { + super.initialize( + new RequestMonitor(getExecutor(), requestMonitor) { + @Override + public void handleSuccess() { + doInitialize(requestMonitor); + }}); + } + + private void doInitialize(final RequestMonitor requestMonitor) { + register(new String[] { MIMemory.class.getName(), IMemory.class.getName(), GDBMemory_7_0.class.getName()}, + new Hashtable()); + + setMemoryCache(new GDBMemoryCache()); + + requestMonitor.done(); + } + + @Override + public void shutdown(final RequestMonitor requestMonitor) { + unregister(); + super.shutdown(requestMonitor); + } + + protected class GDBMemoryCache extends MIMemoryCache { + @Override + protected void readMemoryBlock(IDMContext dmc, IAddress address, final long offset, + final int word_size, final int count, final DataRequestMonitor drm) + { + IDMContext threadOrMemoryDmc = dmc; + + IMIContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class); + if(containerCtx != null) { + IGDBProcesses procService = getServicesTracker().getService(IGDBProcesses.class); + + if (procService != null) { + IMIExecutionDMContext[] execCtxs = procService.getExecutionContexts(containerCtx); + // Return any thread... let's take the first one. + if (execCtxs != null && execCtxs.length > 0) { + threadOrMemoryDmc = execCtxs[0]; + } + } + } + + super.readMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, drm); + } + + /** + * @param memoryDMC + * @param address + * @param offset + * @param word_size + * @param count + * @param buffer + * @param rm + */ + @Override + protected void writeMemoryBlock(final IDMContext dmc, final IAddress address, final long offset, + final int word_size, final int count, final byte[] buffer, final RequestMonitor rm) + { + IDMContext threadOrMemoryDmc = dmc; + + IMIContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class); + if(containerCtx != null) { + IGDBProcesses procService = getServicesTracker().getService(IGDBProcesses.class); + + if (procService != null) { + IMIExecutionDMContext[] execCtxs = procService.getExecutionContexts(containerCtx); + // Return any thread... let's take the first one. + if (execCtxs != null && execCtxs.length > 0) { + threadOrMemoryDmc = execCtxs[0]; + } + } + } + + super.writeMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, buffer, rm); + } + } + +} diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses_7_0.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses_7_0.java index 0bc5abe4120..9b05640479c 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses_7_0.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses_7_0.java @@ -10,9 +10,11 @@ *******************************************************************************/ package org.eclipse.dd.gdb.internal.provisional.service; +import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IStatus; @@ -75,7 +77,7 @@ import org.osgi.framework.BundleContext; * */ public class GDBProcesses_7_0 extends AbstractDsfService - implements IMIProcesses, ICachingService, IEventListener { + implements IGDBProcesses, ICachingService, IEventListener { // Below is the context hierarchy that is implemented between the // MIProcesses service and the MIRunControl service for the MI @@ -393,6 +395,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService // Register this service. register(new String[] { IProcesses.class.getName(), IMIProcesses.class.getName(), + IGDBProcesses.class.getName(), GDBProcesses_7_0.class.getName() }, new Hashtable()); @@ -448,6 +451,24 @@ public class GDBProcesses_7_0 extends AbstractDsfService return createContainerContext(processDmc, groupId); } + public IMIExecutionDMContext[] getExecutionContexts(IMIContainerDMContext containerDmc) { + String groupId = containerDmc.getGroupId(); + List execDmcList = new ArrayList(); + Iterator> iterator = fThreadToGroupMap.entrySet().iterator(); + while (iterator.hasNext()){ + Map.Entry entry = iterator.next(); + if (entry.getValue().equals(groupId)) { + String threadId = entry.getKey(); + IProcessDMContext procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class); + IMIExecutionDMContext execDmc = createExecutionContext(containerDmc, + createThreadContext(procDmc, threadId), + threadId); + execDmcList.add(execDmc); + } + } + return execDmcList.toArray(new IMIExecutionDMContext[0]); + } + /** * This method obtains the model data for a given IThreadDMContext object * which can represent a thread or a process. diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GdbDebugServicesFactory.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GdbDebugServicesFactory.java index dbd3331d45e..93989b1966b 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GdbDebugServicesFactory.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GdbDebugServicesFactory.java @@ -92,6 +92,10 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { @Override protected IMemory createMemoryService(DsfSession session) { + if ("6.8".compareTo(fVersion) < 0) { //$NON-NLS-1$ + return new GDBMemory_7_0(session); + } + return new MIMemory(session); } diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/IGDBProcesses.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/IGDBProcesses.java new file mode 100644 index 00000000000..8ce8fb758c3 --- /dev/null +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/IGDBProcesses.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2008 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.dd.gdb.internal.provisional.service; + +import org.eclipse.dd.mi.service.IMIContainerDMContext; +import org.eclipse.dd.mi.service.IMIExecutionDMContext; +import org.eclipse.dd.mi.service.IMIProcesses; + +public interface IGDBProcesses extends IMIProcesses { + /** + * Get a list of all execution contexts belonging to a container. This call is synchronous, + * unlike the call to getProcessesBeingDebugged(). However, some services may not be able + * to fulfill this request synchronously and will have to rely on getProcessesBeingDebugged(). + * + * @param containerDmc The container for which we want to get the execution contexts + */ + IMIExecutionDMContext[] getExecutionContexts(IMIContainerDMContext containerDmc); + +} diff --git a/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIMemory.java b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIMemory.java index 6acccc41c80..8126bf67202 100644 --- a/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIMemory.java +++ b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIMemory.java @@ -116,7 +116,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer register(new String[] { MIMemory.class.getName(), IMemory.class.getName() }, new Hashtable()); // Create the memory requests cache - fMemoryCache = new MIMemoryCache(); + setMemoryCache(new MIMemoryCache()); // Register as service event listener getSession().addServiceEventListener(this, null); @@ -149,6 +149,15 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer return MIPlugin.getBundleContext(); } + /** + * This method resets the memory cache. It allows an overriding class to provide + * its own overridden memory cache class. + * + * @since 1.1 + */ + protected void setMemoryCache(MIMemoryCache cache) { fMemoryCache = cache; } + + /////////////////////////////////////////////////////////////////////////// // IMemory /////////////////////////////////////////////////////////////////////////// @@ -440,7 +449,12 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer // MIMemoryCache /////////////////////////////////////////////////////////////////////////// - private class MIMemoryCache { + /** + * This class can now be overridden. + * + * @since 1.1 + */ + protected class MIMemoryCache { // Back-end commands cache private CommandCache fCommandCache; @@ -848,7 +862,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer * @param count * @param drm */ - private void readMemoryBlock(IMemoryDMContext memoryDMC, IAddress address, final long offset, + protected void readMemoryBlock(IDMContext dmc, IAddress address, final long offset, final int word_size, final int count, final DataRequestMonitor drm) { /* To simplify the parsing of the MI result, we request the output to @@ -860,7 +874,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer Character asChar = null; fCommandCache.execute( - new MIDataReadMemory(memoryDMC, offset, address.toString(), mode, word_size, nb_rows, nb_cols, asChar), + new MIDataReadMemory(dmc, offset, address.toString(), mode, word_size, nb_rows, nb_cols, asChar), new DataRequestMonitor(getExecutor(), drm) { @Override protected void handleSuccess() { @@ -890,7 +904,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer * @param buffer * @param rm */ - private void writeMemoryBlock(final IMemoryDMContext memoryDMC, final IAddress address, final long offset, + protected void writeMemoryBlock(final IDMContext dmc, final IAddress address, final long offset, final int word_size, final int count, final byte[] buffer, final RequestMonitor rm) { // Each byte is written individually (GDB power...) @@ -906,7 +920,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer for (int i = 0; i < count; i++) { String value = new Byte(buffer[i]).toString(); fCommandCache.execute( - new MIDataWriteMemory(memoryDMC, offset + i, baseAddress, format, word_size, value), + new MIDataWriteMemory(dmc, offset + i, baseAddress, format, word_size, value), new DataRequestMonitor(getExecutor(), countingRM) ); }