Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 39bc2b3708133b43e47266dede99f3cda8838675 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                
                                                                




                                                                        


                                                                                 
                                                   

                            
                     




                                                                                    
                                                                           
                                                                                    
                                                                                  
                                              
                                    
                                                               
                                                            
                                                       



                                                
                                               
                                               
                                            
 

                                                
                         
                                   
                                                     
                                                          
                                                       

                                                                                  
                                                   
 
                                                                                                 
                          
                                 
                                                       
                                                            
                                                         



                                                                                        



                                          



                                                                                     


                                          





                                                                                 
                                                                                 




                                          

                                                                                                                        
                                                                                                      




                             


                                                             


                                                                      
                                
                                                        

                                




                                                                                                               
                                                                




                                                   




                                                                                                                

                                                        
                                        





                                                                                   
                                        





                                                                    
                                                          
                                                                                           
                                                                                                               
                                                            
                                        


                                                                                 













                                                                                                       










                                                                             











                                                                                  
                                                         












                                                                              

     
                             
                                           

                        
 
                                   

                                 
 

                    


                                      
                                
                                
                                




                             
                                  
                                  
                                  
     
 



                                                     


                                                                               
 

                                                  
     
 

                                           

                                                                          
                                                                     

                    
 



                                 







                                                                                  
             




                                                                         
         

                                        
         








                                                                           
         


                                    
                    
     
 
             
                                                                      


                                                                            
     
 
             
                                                                   


                                                                                               
                                   

              
                                                                                                
                                                          
                                                     











                                                                                   



                                                                                







                                                                               

                  




                                                     


                                                                                    



                                                                                    
                 
             
                                                                                    
         
                    
     
 


                                                                         

                                                                                                               







                                                                                     





                                                          

























                                                                                                             






                                                            


















                                                                                                                      

                                       

     
                                  
                          
                                


                        


                                     
                                    
                                    
                                    
                              
     
 
                               

                                

     

                                           
                              
     
 



                                     
                                

     
             








                                                       
/*******************************************************************************
 * Copyright (c) 2007, 2010 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.model;

import java.math.BigInteger;
import java.util.Map;

import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.swt.graphics.RGB;
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.ImageCache;
import org.eclipse.tm.tcf.protocol.IToken;
import org.eclipse.tm.tcf.protocol.Protocol;
import org.eclipse.tm.tcf.services.ILineNumbers;
import org.eclipse.tm.tcf.services.IMemory;
import org.eclipse.tm.tcf.services.IRunControl;
import org.eclipse.tm.tcf.services.IStackTrace;
import org.eclipse.tm.tcf.util.TCFDataCache;

public class TCFNodeStackFrame extends TCFNode {

    private int frame_no;
    private final boolean emulated;
    private final TCFChildrenRegisters children_regs;
    private final TCFChildrenLocalVariables children_vars;
    private final TCFChildrenExpressions children_exps;
    private final TCFDataCache<IStackTrace.StackTraceContext> stack_trace_context;
    private final TCFDataCache<TCFSourceRef> line_info;
    private final TCFDataCache<BigInteger> address;

    TCFNodeStackFrame(final TCFNodeExecContext parent, final String id, final boolean emulated) {
        super(parent, id);
        this.emulated = emulated;
        children_regs = new TCFChildrenRegisters(this);
        children_vars = new TCFChildrenLocalVariables(this);
        children_exps = new TCFChildrenExpressions(this);
        stack_trace_context = new TCFDataCache<IStackTrace.StackTraceContext>(channel) {
            @Override
            protected boolean startDataRetrieval() {
                assert command == null;
                if (emulated) {
                    set(null, null, null);
                    return true;
                }
                TCFDataCache<TCFContextState> parent_state_cache = parent.getState();
                if (!parent_state_cache.validate(this)) return false;
                TCFContextState parent_state_data = parent_state_cache.getData();
                if (parent_state_data == null || !parent_state_data.is_suspended) {
                    set(null, null, null);
                    return true;
                }
                TCFChildrenStackTrace stack_trace_cache = parent.getStackTrace();
                if (!stack_trace_cache.validate(this)) return false;
                if (frame_no < 0) {
                    set(null, null, null);
                    return true;
                }
                IStackTrace st = model.getLaunch().getService(IStackTrace.class);
                if (st == null) {
                    assert frame_no == 0;
                    set(null, null, null);
                    return true;
                }
                command = st.getContext(new String[]{ id }, new IStackTrace.DoneGetContext() {
                    public void doneGetContext(IToken token, Exception error, IStackTrace.StackTraceContext[] context) {
                        set(token, error, context == null || context.length == 0 ? null : context[0]);
                    }
                });
                return false;
            }
        };
        line_info = new TCFDataCache<TCFSourceRef>(channel) {
            @Override
            protected boolean startDataRetrieval() {
                if (!stack_trace_context.validate(this)) return false;
                if (!address.validate(this)) return false;
                BigInteger n = address.getData();
                if (n == null) {
                    set(null, address.getError(), null);
                    return true;
                }
                IMemory.MemoryContext mem_ctx = null;
                TCFNode p = parent;
                while (p != null) {
                    if (p instanceof TCFNodeExecContext) {
                        TCFDataCache<IMemory.MemoryContext> cache = ((TCFNodeExecContext)p).getMemoryContext();
                        if (!cache.validate(this)) return false;
                        mem_ctx = cache.getData();
                        if (mem_ctx != null) break;
                    }
                    p = p.parent;
                }
                if (p == null) {
                    set(null, null, null);
                    return true;
                }
                final Map<BigInteger,TCFSourceRef> line_info_cache = ((TCFNodeExecContext)p).getLineInfoCache();
                TCFSourceRef l = line_info_cache.get(n);
                if (l != null) {
                    l.context = mem_ctx;
                    set(null, null, l);
                    return true;
                }
                ILineNumbers ln = model.getLaunch().getService(ILineNumbers.class);
                if (ln == null) {
                    l = new TCFSourceRef();
                    l.context = mem_ctx;
                    l.address = n;
                    set(null, null, l);
                    return true;
                }
                final BigInteger n0 = n;
                final BigInteger n1 = n0.add(BigInteger.valueOf(1));
                final IMemory.MemoryContext ctx = mem_ctx;
                command = ln.mapToSource(p.id, n0, n1, new ILineNumbers.DoneMapToSource() {
                    public void doneMapToSource(IToken token, Exception error, ILineNumbers.CodeArea[] areas) {
                        TCFSourceRef l = new TCFSourceRef();
                        l.context = ctx;
                        l.address = n0;
                        if (error == null && areas != null && areas.length > 0) {
                            for (ILineNumbers.CodeArea area : areas) {
                                BigInteger a0 = toBigInteger(area.start_address);
                                BigInteger a1 = toBigInteger(area.end_address);
                                if (n0.compareTo(a0) >= 0 && n0.compareTo(a1) < 0) {
                                    if (l.area == null || area.start_line < l.area.start_line) {
                                        if (area.start_address != a0 || area.end_address != a1) {
                                            area = new ILineNumbers.CodeArea(area.directory, area.file,
                                                    area.start_line, area.start_column,
                                                    area.end_line, area.end_column,
                                                    a0, a1, area.isa,
                                                    area.is_statement, area.basic_block,
                                                    area.prologue_end, area.epilogue_begin);
                                        }
                                        l.area = area;
                                    }
                                }
                            }
                        }
                        l.error = error;
                        set(token, null, l);
                        if (error == null) line_info_cache.put(l.address, l);
                    }
                });
                return false;
            }
        };
        address = new TCFDataCache<BigInteger>(channel) {
            @Override
            protected boolean startDataRetrieval() {
                if (!stack_trace_context.validate(this)) return false;
                IStackTrace.StackTraceContext ctx = stack_trace_context.getData();
                if (ctx != null) {
                    Number n = ctx.getInstructionAddress();
                    if (n instanceof BigInteger) {
                        set(null, null, (BigInteger)n);
                        return true;
                    }
                    if (n != null) {
                        set(null, null, toBigInteger(n));
                        return true;
                    }
                }
                if (frame_no == 0) {
                    TCFDataCache<BigInteger> addr_cache = parent.getAddress();
                    if (!addr_cache.validate(this)) return false;
                    set(null, addr_cache.getError(), addr_cache.getData());
                    return true;
                }
                set(null, stack_trace_context.getError(), null);
                return true;
            }
        };
    }

    public int getFrameNo() {
        assert Protocol.isDispatchThread();
        return frame_no;
    }

    void setFrameNo(int frame_no) {
        this.frame_no = frame_no;
    }

    @Override
    void dispose() {
        stack_trace_context.dispose();
        line_info.dispose();
        address.dispose();
        children_regs.dispose();
        children_vars.dispose();
        children_exps.dispose();
        super.dispose();
    }

    @Override
    void dispose(String id) {
        children_regs.dispose(id);
        children_vars.dispose(id);
        children_exps.dispose(id);
    }

    public TCFDataCache<TCFSourceRef> getLineInfo() {
        return line_info;
    }

    public TCFDataCache<IStackTrace.StackTraceContext> getStackTraceContext() {
        return stack_trace_context;
    }

    public TCFDataCache<BigInteger> getAddress() {
        return address;
    }

    public BigInteger getReturnAddress() {
        assert Protocol.isDispatchThread();
        if (!stack_trace_context.isValid()) return null;
        IStackTrace.StackTraceContext ctx = stack_trace_context.getData();
        if (ctx != null) return toBigInteger(ctx.getReturnAddress());
        return null;
    }

    public boolean isEmulated() {
        return emulated;
    }

    private TCFChildren getChildren(IPresentationContext ctx) {
        String id = ctx.getId();
        if (IDebugUIConstants.ID_REGISTER_VIEW.equals(id)) return children_regs;
        if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(id)) return children_vars;
        if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(id)) return children_exps;
        return null;
    }

    @Override
    protected boolean getData(IHasChildrenUpdate result, Runnable done) {
        TCFChildren c = getChildren(result.getPresentationContext());
        if (c != null) {
            if (!c.validate(done)) return false;
            result.setHasChilren(c.size() > 0);
        }
        else {
            result.setHasChilren(false);
        }
        return true;
    }

    @Override
    protected boolean getData(IChildrenCountUpdate result, Runnable done) {
        TCFChildren c = getChildren(result.getPresentationContext());
        if (c != null) {
            if (!c.validate(done)) return false;
            result.setChildCount(c.size());
        }
        else {
            result.setChildCount(0);
        }
        return true;
    }

    @Override
    protected boolean getData(IChildrenUpdate result, Runnable done) {
        TCFChildren children = getChildren(result.getPresentationContext());
        if (children == null) return true;
        return children.getData(result, done);
    }

    @Override
    protected boolean getData(ILabelUpdate result, Runnable done) {
        TCFChildrenStackTrace stack_trace_cache = ((TCFNodeExecContext)parent).getStackTrace();
        if (!stack_trace_cache.validate(done)) return false;
        if (stack_trace_cache.getData().get(id) == null) {
            result.setLabel("", 0);
        }
        else {
            TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)parent).getState();
            if (!state_cache.validate(done)) return false;
            Throwable error = state_cache.getError();
            if (error == null) error = stack_trace_cache.getError();
            if (error == null) {
                TCFDataCache<?> pending = null;
                if (!stack_trace_context.validate()) pending = stack_trace_context;
                if (!line_info.validate()) pending = line_info;
                if (pending != null) {
                    pending.wait(done);
                    return false;
                }
                if (error == null) error = stack_trace_context.getError();
                if (error == null) error = line_info.getError();
            }
            TCFContextState state_data = state_cache.getData();
            String image_name =  state_data != null && state_data.is_suspended ?
                    ImageCache.IMG_STACK_FRAME_SUSPENDED :
                    ImageCache.IMG_STACK_FRAME_RUNNING;
            if (error != null) {
                if (state_data == null || state_data.is_suspended) {
                    result.setForeground(new RGB(255, 0, 0), 0);
                    result.setLabel(TCFModel.getErrorMessage(error, false), 0);
                }
                else {
                    result.setLabel("...", 0);
                }
            }
            else {
                TCFSourceRef l = line_info.getData();
                if (l == null) {
                    result.setLabel("...", 0);
                }
                else {
                    String module = getModuleName(l.address, done);
                    if (module == null) return false;
                    String label = makeHexAddrString(l.context, l.address) + module;
                    if (l.area != null && l.area.file != null) {
                        label += ": " + l.area.file + ", line " + l.area.start_line;
                    }
                    result.setLabel(label, 0);
                }
            }
            result.setImageDescriptor(ImageCache.getImageDescriptor(image_name), 0);
        }
        return true;
    }

    @Override
    protected boolean getData(IViewerInputUpdate result, Runnable done) {
        result.setInputElement(result.getElement());
        String id = result.getPresentationContext().getId();
        if (IDebugUIConstants.ID_REGISTER_VIEW.equals(id) || IDebugUIConstants.ID_EXPRESSION_VIEW.equals(id)) {
            TCFNodeExecContext exe = (TCFNodeExecContext)parent;
            TCFChildrenStackTrace stack_trace_cache = exe.getStackTrace();
            if (!stack_trace_cache.validate(done)) return false;
            if (stack_trace_cache.getTopFrame() == this) result.setInputElement(exe);
        }
        return true;
    }

    private BigInteger toBigInteger(Number n) {
        if (n == null) return null;
        if (n instanceof BigInteger) return (BigInteger)n;
        return new BigInteger(n.toString());
    }

    private String getModuleName(BigInteger pc, Runnable done) {
        TCFDataCache<IRunControl.RunControlContext> parent_dc = ((TCFNodeExecContext)parent).getRunContext();
        if (!parent_dc.validate(done)) return null;
        IRunControl.RunControlContext parent_ctx = parent_dc.getData();
        if (parent_ctx == null) return "";
        String prs_id = parent_ctx.getProcessID();
        if (prs_id == null) return "";
        TCFNodeExecContext prs_node = (TCFNodeExecContext)model.getNode(prs_id);
        TCFDataCache<TCFNodeExecContext.MemoryRegion[]> map_dc = prs_node.getMemoryMap();
        if (!map_dc.validate(done)) return null;
        TCFNodeExecContext.MemoryRegion[] map = map_dc.getData();
        if (map == null) return "";
        for (TCFNodeExecContext.MemoryRegion r : map) {
            String fnm = r.region.getFileName();
            if (fnm != null && r.contains(pc)) {
                fnm = fnm.replace('\\', '/');
                int x = fnm.lastIndexOf('/');
                if (x >= 0) fnm = fnm.substring(x + 1);
                return " [" + fnm + "]";
            }
        }
        return "";
    }

    private String makeHexAddrString(IMemory.MemoryContext m, BigInteger n) {
        String s = n.toString(16);
        int sz = (m != null ? m.getAddressSize() : 4) * 2;
        int l = sz - s.length();
        if (l < 0) l = 0;
        if (l > 16) l = 16;
        return "0x0000000000000000".substring(0, 2 + l) + s;
    }

    private void postAllChangedDelta() {
        for (TCFModelProxy p : model.getModelProxies()) {
            int flags = 0;
            String id = p.getPresentationContext().getId();
            if (IDebugUIConstants.ID_DEBUG_VIEW.equals(id)) flags |= IModelDelta.STATE;
            if (getChildren(p.getPresentationContext()) != null && p.getInput() == this) flags |= IModelDelta.CONTENT;
            if (flags != 0) p.addDelta(this, flags);
        }
    }

    private void postStateChangedDelta() {
        for (TCFModelProxy p : model.getModelProxies()) {
            String id = p.getPresentationContext().getId();
            if (IDebugUIConstants.ID_DEBUG_VIEW.equals(id)) {
                p.addDelta(this, IModelDelta.STATE);
            }
        }
    }

    void onExpressionAddedOrRemoved() {
        children_exps.reset();
    }

    void onSourceMappingChange() {
        line_info.reset();
        postStateChangedDelta();
    }

    void onSuspended() {
        stack_trace_context.cancel();
        line_info.cancel();
        address.cancel();
        children_regs.onSuspended();
        children_vars.onSuspended();
        children_exps.onSuspended();
        postAllChangedDelta();
    }

    void onMemoryMapChanged() {
        line_info.reset();
        postStateChangedDelta();
    }

    void onRegistersChanged() {
        children_regs.onRegistersChanged();
        postAllChangedDelta();
    }

    void onRegisterValueChanged() {
        stack_trace_context.cancel();
        line_info.cancel();
        address.cancel();
        postStateChangedDelta();
    }

    @Override
    public int compareTo(TCFNode n) {
        if (n instanceof TCFNodeStackFrame) {
            TCFNodeStackFrame f = (TCFNodeStackFrame)n;
            if (frame_no < f.frame_no) return -1;
            if (frame_no > f.frame_no) return +1;
        }
        return id.compareTo(n.id);
    }
}

Back to the top