/******************************************************************************* * Copyright (c) 2011, 2016 Wind River Systems, Inc. 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.internal.debug.ui.commands; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IMemoryBlockManager; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.memory.IMemoryRendering; import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; import org.eclipse.debug.ui.memory.IMemoryRenderingManager; import org.eclipse.debug.ui.memory.IMemoryRenderingSite; import org.eclipse.debug.ui.memory.IMemoryRenderingType; import org.eclipse.swt.widgets.Display; import org.eclipse.tcf.internal.debug.ui.Activator; import org.eclipse.tcf.internal.debug.ui.model.TCFModel; import org.eclipse.tcf.internal.debug.ui.model.TCFModelProxy; import org.eclipse.tcf.internal.debug.ui.model.TCFNode; import org.eclipse.tcf.internal.debug.ui.model.TCFNodeExpression; import org.eclipse.tcf.internal.debug.ui.model.TCFNodeRegister; import org.eclipse.tcf.internal.debug.ui.model.TCFNumberFormat; import org.eclipse.tcf.protocol.IChannel; import org.eclipse.tcf.protocol.JSON; import org.eclipse.tcf.services.IExpressions; import org.eclipse.tcf.services.IRegisters; import org.eclipse.tcf.util.TCFDataCache; import org.eclipse.tcf.util.TCFTask; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPage; public class ViewMemoryCommand extends AbstractActionDelegate { private static class Block { TCFNode node; BigInteger addr; long size; } private final Runnable on_value_changed = new Runnable() { @Override public void run() { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { selectionChanged(); } }); } }; private Block getBlockInfo(final TCFNode node) { try { return new TCFTask<Block>(node.getChannel()) { public void run() { try { TCFModel model = node.getModel(); TCFNode mem_node = node; BigInteger addr = null; long size = -1; if (node instanceof TCFNodeExpression && ((TCFNodeExpression)node).isEnabled()) { TCFDataCache<IExpressions.Value> val_cache = ((TCFNodeExpression)node).getValue(); if (!val_cache.validate(on_value_changed)) { /* Don't wait until the value is evaluated - * it can take long time if the expression contains a function call. */ done(null); return; } IExpressions.Value val_data = val_cache.getData(); if (val_data != null) { addr = JSON.toBigInteger(val_data.getAddress()); if (addr != null) { byte[] bytes = val_data.getValue(); if (bytes != null) size = bytes.length; } if (addr == null) { String id = val_data.getRegisterID(); if (val_data.getRegisterID() != null) { if (!model.createNode(id, this)) return; TCFNodeRegister reg_node = (TCFNodeRegister)model.getNode(id); if (reg_node != null) { TCFDataCache<IRegisters.RegistersContext> reg_cache = reg_node.getContext(); if (!reg_cache.validate(this)) return; IRegisters.RegistersContext reg_data = reg_cache.getData(); if (reg_data != null) { String mem_id = reg_data.getMemoryContext(); if (mem_id != null) { if (!model.createNode(mem_id, this)) return; addr = JSON.toBigInteger(reg_data.getMemoryAddress()); mem_node = model.getNode(mem_id); } } } } } if (addr == null) { @SuppressWarnings("unchecked") List<Map<String,Object>> pieces = (List<Map<String,Object>>)val_data.getProperties().get(IExpressions.VAL_PIECES); if (pieces != null) { for (Map<String,Object> props : pieces) { addr = JSON.toBigInteger((Number)props.get("Address")); if (addr != null) { Number n = (Number)props.get("Size"); if (n != null) size = n.longValue(); break; } } } } if (addr == null) { byte[] bytes = val_data.getValue(); if (bytes != null && bytes.length > 0) { addr = TCFNumberFormat.toBigInteger(bytes, val_data.isBigEndian(), false); } } } } else if (node instanceof TCFNodeRegister) { TCFNodeRegister reg_node = (TCFNodeRegister)node; TCFDataCache<IRegisters.RegistersContext> reg_cache = reg_node.getContext(); if (!reg_cache.validate(this)) return; IRegisters.RegistersContext reg_data = reg_cache.getData(); if (reg_data != null) { String mem_id = reg_data.getMemoryContext(); if (mem_id != null) { if (!model.createNode(mem_id, this)) return; addr = JSON.toBigInteger(reg_data.getMemoryAddress()); mem_node = model.getNode(mem_id); } if (addr == null) { TCFDataCache<byte[]> val_cache = reg_node.getValue(); if (!val_cache.validate(this)) return; byte[] bytes = val_cache.getData(); if (bytes != null && bytes.length > 0) { addr = TCFNumberFormat.toBigInteger(bytes, reg_data.isBigEndian(), false); } } } } Block b = null; if (addr != null && mem_node != null) { b = new Block(); b.node = mem_node; b.addr = addr; b.size = size; } done(b); } catch (Exception x) { error(x); } } }.get(); } catch (Exception x) { if (node.getChannel().getState() != IChannel.STATE_OPEN) return null; Activator.log("Cannot get memory address", x); return null; } } private void createRenderingInContainer(IViewPart view, IMemoryBlock mb, IMemoryRenderingType type, String pane) { try { if (view instanceof IMemoryRenderingSite) { IMemoryRendering rendering = type.createRendering(); IMemoryRenderingContainer container = ((IMemoryRenderingSite)view).getContainer(pane); rendering.init(container, mb); container.addMemoryRendering(rendering); } } catch (CoreException x) { Activator.log(x); } } private void addDefaultRenderings(IViewPart view, IMemoryBlock memoryBlock) { IMemoryRenderingManager manager = DebugUITools.getMemoryRenderingManager(); IMemoryRenderingType primary_type = manager.getPrimaryRenderingType(memoryBlock); IMemoryRenderingType default_types[] = manager.getDefaultRenderingTypes(memoryBlock); // create primary rendering if (primary_type != null) { createRenderingInContainer(view, memoryBlock, primary_type, IDebugUIConstants.ID_RENDERING_VIEW_PANE_1); } else if (default_types.length > 0) { primary_type = default_types[0]; createRenderingInContainer(view, memoryBlock, default_types[0], IDebugUIConstants.ID_RENDERING_VIEW_PANE_1); } for (IMemoryRenderingType type : default_types) { if (!primary_type.getId().equals(type.getId())) { createRenderingInContainer(view, memoryBlock, type, IDebugUIConstants.ID_RENDERING_VIEW_PANE_2); } } } @Override protected void run() { try { IWorkbenchPage page = getWindow().getActivePage(); IViewPart view = page.showView(IDebugUIConstants.ID_MEMORY_VIEW, null, IWorkbenchPage.VIEW_ACTIVATE); ArrayList<IMemoryBlock> list = new ArrayList<IMemoryBlock>(); for (TCFNode node : getSelectedNodes()) { final Block b = getBlockInfo(node); if (b != null) { IMemoryBlockRetrievalExtension mem_retrieval = (IMemoryBlockRetrievalExtension) b.node.getAdapter(IMemoryBlockRetrievalExtension.class); if (mem_retrieval != null) { list.add(mem_retrieval.getMemoryBlock(b.addr.longValue(), b.size)); new TCFTask<Boolean>(node.getChannel()) { @Override public void run() { for (TCFModelProxy p : b.node.getModel().getModelProxies()) { IPresentationContext c = p.getPresentationContext(); if (c.getWindow() != getWindow()) continue; if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(c.getId())) continue; p.setSelection(b.node); } } }; } } } IMemoryBlockManager manager = DebugPlugin.getDefault().getMemoryBlockManager(); for (IMemoryBlock mb : list) { IMemoryBlock[] mb_array = new IMemoryBlock[] { mb }; manager.addMemoryBlocks(mb_array); addDefaultRenderings(view, mb); } } catch (Exception x) { Activator.log("Cannot open memory view", x); } } @Override protected void selectionChanged() { int cnt = 0; for (TCFNode node : getSelectedNodes()) { Block b = getBlockInfo(node); if (b != null) { IMemoryBlockRetrievalExtension mem_retrieval = (IMemoryBlockRetrievalExtension) b.node.getAdapter(IMemoryBlockRetrievalExtension.class); if (mem_retrieval != null) cnt++; } } setEnabled(cnt > 0); } }