/******************************************************************************* * Copyright (c) 2008, 2010 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.service; import java.util.Hashtable; import org.eclipse.cdt.core.IAddress; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IMemory; import org.eclipse.cdt.dsf.debug.service.IMemorySpaces.IMemorySpaceDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.gdb.internal.memory.GdbMemoryBlock.MemorySpaceDMContext; import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.MIMemory; import org.eclipse.cdt.dsf.service.DsfSession; 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(ImmediateExecutor.getInstance(), 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<String, String>()); requestMonitor.done(); } @Override public void shutdown(final RequestMonitor requestMonitor) { unregister(); super.shutdown(requestMonitor); } @Override protected void readMemoryBlock(IDMContext dmc, IAddress address, long offset, int word_size, int count, DataRequestMonitor<MemoryByte[]> drm) { IDMContext threadOrMemoryDmc = dmc; // A memory context is a container. We have two limitations with GDB here: // 1- Before GDB 7.2, there is no way to specify a process for an MI command, so to work around // that, we need to specify a thread for the process we want to point to. This is important // to support multi-process for targets that have that kind of support before GDB 7.2 // 2- GDB cannot read memory when pointing to a thread that is running. For non-stop mode // we can have some threads running with others stopped, so we need to choose a thread that is // actually stopped. IMIContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class); if(containerCtx != null) { IGDBProcesses procService = getServicesTracker().getService(IGDBProcesses.class); IRunControl runControl = getServicesTracker().getService(IRunControl.class); if (procService != null && runControl != null) { IMIExecutionDMContext[] execCtxs = procService.getExecutionContexts(containerCtx); // Return any thread, as long as it is suspended. This will allow GDB to read the memory // and it will be for the process we care about (since we choose a thread within it). if (execCtxs != null && execCtxs.length > 0) { for (IMIExecutionDMContext execCtx : execCtxs) { if (runControl.isSuspended(execCtx)) { threadOrMemoryDmc = execCtx; // Not so fast, Charlie. The context we were given may have // a memory space qualifier. We need to preserve it. if (dmc instanceof IMemorySpaceDMContext) { threadOrMemoryDmc = new MemorySpaceDMContext(getSession().getId(), ((IMemorySpaceDMContext)dmc).getMemorySpaceId(), threadOrMemoryDmc); } break; } } } } } super.readMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, drm); } @Override protected void writeMemoryBlock(IDMContext dmc, IAddress address, long offset, int word_size, int count, byte[] buffer, RequestMonitor rm) { IDMContext threadOrMemoryDmc = dmc; // A memory context is a container. We have two limitations with GDB here: // 1- Before GDB 7.2, there is no way to specify a process for an MI command, so to work around // that, we need to specify a thread for the process we want to point to. This is important // to support multi-process for targets that have that kind of support before GDB 7.2 // 2- GDB cannot write memory when pointing to a thread that is running. For non-stop mode // we can have some threads running with others stopped, so we need to choose a thread that is // actually stopped. IMIContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class); if(containerCtx != null) { IGDBProcesses procService = getServicesTracker().getService(IGDBProcesses.class); IRunControl runControl = getServicesTracker().getService(IRunControl.class); if (procService != null && runControl != null) { IMIExecutionDMContext[] execCtxs = procService.getExecutionContexts(containerCtx); // Return any thread, as long as it is suspended. This will allow GDB to read the memory // and it will be for the process we care about (since we choose a thread within it). if (execCtxs != null && execCtxs.length > 0) { for (IMIExecutionDMContext execCtx : execCtxs) { if (runControl.isSuspended(execCtx)) { threadOrMemoryDmc = execCtx; // Not so fast, Charlie. The context we were given may have // a memory space qualifier. We need to preserve it. if (dmc instanceof IMemorySpaceDMContext) { threadOrMemoryDmc = new MemorySpaceDMContext(getSession().getId(), ((IMemorySpaceDMContext)dmc).getMemorySpaceId(), threadOrMemoryDmc); } break; } } } } } super.writeMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, buffer, rm); } }