/******************************************************************************* * Copyright (c) 2011 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.tm.internal.tcf.debug.ui.adapters; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; import org.eclipse.tm.internal.tcf.debug.ui.Activator; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext.MemoryRegion; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; import org.eclipse.tm.tcf.protocol.JSON; import org.eclipse.tm.tcf.services.IRunControl; import org.eclipse.tm.tcf.services.IStackTrace; import org.eclipse.tm.tcf.util.TCFDataCache; import org.eclipse.tm.tcf.util.TCFTask; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.PropertyDescriptor; /** * Adapts TCFNode to IPropertySource. */ public class TCFNodePropertySource implements IPropertySource { private final TCFNode fNode; private final Map<String, Object> fProperties = new HashMap<String, Object>(); private IPropertyDescriptor[] fDescriptors; public TCFNodePropertySource(TCFNode node) { fNode = node; } public Object getEditableValue() { return null; } public IPropertyDescriptor[] getPropertyDescriptors() { if (fDescriptors == null) { try { final List<IPropertyDescriptor> descriptors = new ArrayList<IPropertyDescriptor>(); fDescriptors = new TCFTask<IPropertyDescriptor[]>(fNode.getChannel()) { public void run() { if (fNode instanceof TCFNodeExecContext) { getExecContextDescriptors((TCFNodeExecContext) fNode); } else if (fNode instanceof TCFNodeStackFrame) { getFrameDescriptors((TCFNodeStackFrame) fNode); } else { done(descriptors.toArray(new IPropertyDescriptor[descriptors.size()])); } } private void getFrameDescriptors(TCFNodeStackFrame frameNode) { TCFDataCache<IStackTrace.StackTraceContext> ctx_cache = frameNode.getStackTraceContext(); TCFDataCache<TCFSourceRef> line_info_cache = frameNode.getLineInfo(); if (!validateAll(ctx_cache, line_info_cache)) return; IStackTrace.StackTraceContext ctx = ctx_cache.getData(); if (ctx != null) { Map<String, Object> props = ctx.getProperties(); for (String key : props.keySet()) { Object value = props.get(key); if (value instanceof Number) { value = toHexAddrString((Number) value); } addDescriptor("Context", key, value); } } TCFSourceRef sourceRef = line_info_cache.getData(); if (sourceRef != null) { if (sourceRef.area != null) { addDescriptor("Source", "Directory", sourceRef.area.directory); addDescriptor("Source", "File", sourceRef.area.file); addDescriptor("Source", "Line", sourceRef.area.start_line); } if (sourceRef.error != null) { addDescriptor("Source", "Error", sourceRef.error); } } done(descriptors.toArray(new IPropertyDescriptor[descriptors.size()])); } private void getExecContextDescriptors(TCFNodeExecContext exeNode) { TCFDataCache<IRunControl.RunControlContext> ctx_cache = exeNode.getRunContext(); TCFDataCache<TCFContextState> state_cache = exeNode.getState(); TCFDataCache<MemoryRegion[]> mem_map_cache = exeNode.getMemoryMap(); if (!validateAll(ctx_cache, state_cache, mem_map_cache)) return; IRunControl.RunControlContext ctx = ctx_cache.getData(); if (ctx != null) { Map<String, Object> props = ctx.getProperties(); for (String key : props.keySet()) { Object value = props.get(key); if (value instanceof Number) { value = toHexAddrString((Number) value); } addDescriptor("Context", key, value); } } TCFContextState state = state_cache.getData(); if (state != null) { addDescriptor("State", "Suspended", state.is_suspended); if (state.is_suspended) { addDescriptor("State", "Suspend reason", state.suspend_reason); addDescriptor("State", "PC", toHexAddrString(new BigInteger(state.suspend_pc))); } addDescriptor("State", "Active", !exeNode.isNotActive()); } MemoryRegion[] mem_map = mem_map_cache.getData(); if (mem_map != null && mem_map.length > 0) { int idx = 0; for (MemoryRegion region : mem_map) { Map<String, Object> props = region.region.getProperties(); for (String key : props.keySet()) { Object value = props.get(key); if (value instanceof Number) { value = toHexAddrString((Number) value); } addDescriptor("MemoryRegion["+idx+']', key, value); } idx++; } } done(descriptors.toArray(new IPropertyDescriptor[descriptors.size()])); } private void addDescriptor(String category, String key, Object value) { String id = category + '.' + key; PropertyDescriptor desc = new PropertyDescriptor(id, key); desc.setCategory(category); descriptors.add(desc); fProperties.put(id, value); } boolean validateAll(TCFDataCache<?> ... caches) { TCFDataCache<?> pending = null; for (TCFDataCache<?> cache : caches) { if (!cache.validate()) { pending = cache; } } if (pending != null) { pending.wait(this); return false; } return true; } }.get(5, TimeUnit.SECONDS); } catch (Exception e) { Activator.log("Error retrieving property data", e); fDescriptors = new IPropertyDescriptor[0]; } } return fDescriptors; } public Object getPropertyValue(final Object id) { return fProperties.get(id); } public boolean isPropertySet(Object id) { return false; } public void resetPropertyValue(Object id) { } public void setPropertyValue(Object id, Object value) { } private static String toHexAddrString(Number num) { BigInteger n = JSON.toBigInteger(num); String s = n.toString(16); int sz = s.length() > 8 ? 16 : 8; int l = sz - s.length(); if (l < 0) l = 0; if (l > 16) l = 16; return "0x0000000000000000".substring(0, 2 + l) + s; } }