CDT源代码框架分析改造(四) 添加断点流程分析,添加获取跟踪点编号。

入口类 ToggleMethodTracepointAction

创建一个FunctionBreakpoint

CDIDebugModel.createFunctionBreakpoint(location, getResource(), function, -1, -1, -1, true, 0, "", true, true, false); 

CDIDebugModle中创建。该类时一个debugmodel类,其中大部分是创建方法,在CDT中类型前面以CDI开头的。都属于

Debug。跟CDT的桥梁类。

 

 

    /**
     * @param sourceHandle
     * @param resource
     * @param function
     * @param charStart
     * @param charEnd
     * @param lineNumber
     * @param enabled
     * @param ignoreCount
     * @param condition
     * @param register
     * @param type
     * @param temporary
     * @return
     * @throws CoreException
     */
    public static ICFunctionBreakpoint createFunctionBreakpoint( String sourceHandle, IResource resource, String function, int charStart, int charEnd, int lineNumber, boolean enabled, int ignoreCount, String condition, boolean register, boolean isGlobal, boolean temporary ) throws CoreException {
        HashMap attributes = new HashMap(10);
        
//        attributes.put(IBreakpoint.ID, getPluginIdentifier());
        attributes.put(IBreakpoint.ID, getPluginIdentifier());
        attributes.put(IMarker.CHAR_START, new Integer(charStart));
        attributes.put(IMarker.CHAR_END, new Integer(charEnd));
        attributes.put(IMarker.LINE_NUMBER, new Integer(lineNumber));
        attributes.put(ICLineBreakpoint.FUNCTION, function);
        attributes.put(IBreakpoint.ENABLED, Boolean.valueOf(enabled));
        attributes.put(ICBreakpoint.IGNORE_COUNT, new Integer(ignoreCount));
        attributes.put(ICBreakpoint.CONDITION, condition);
        attributes.put(ICBreakpoint.SOURCE_HANDLE, sourceHandle);
        attributes.put(ICBreakpoint.TEMPORARY, new Boolean(temporary));
        attributes.put(ICBreakpoint.TEMPORARY, new Boolean(temporary));
        attributes.put(ICBreakpoint.TEMPORARY, new Boolean(temporary));

        attributes.put(ICFunctionBreakpoint.FUNCTION_BREAKPOINT_ID, getFunctionBreakpointId());

        attributes.put(ICBreakpoint.TYPE, isGlobal?ICBreakpoint.GLOBAL_BREAKPOINT:ICBreakpoint.LOCAL_BREAKPOINT);
  
        attributes.put(ICBreakpoint.BREAKPOINT_ID, getBreakpointID());
        return new CFunctionBreakpoint(resource, attributes, register);
    }

 

FunctionBreakpoint就是debug层的断点对象。其父类为CBreakpoint对象,在父类的构造函数中中,通知BreakpointManager创建断点。

 

Class    CBreakpoint{
...
public CBreakpoint( final IResource resource, final String markerType, final Map attributes, final boolean add ) throws CoreException {
        this();
        IWorkspaceRunnable wr = new IWorkspaceRunnable() {

            public void run( IProgressMonitor monitor ) throws CoreException {
                // create the marker
                setMarker( resource.createMarker( markerType ) );
                // set attributes
                ensureMarker().setAttributes( attributes );
                //set the marker message
                setAttribute( IMarker.MESSAGE, getMarkerMessage() );
                // add to breakpoint manager if requested
                register( add );
            }
        };
        run( wr );
    }

**
     * Add this breakpoint to the breakpoint manager, or sets it as
     * unregistered.
     */
    public void register( boolean register ) throws CoreException {
        if ( register ) {
            DebugPlugin.getDefault().getBreakpointManager().addBreakpoint( this );
        }
        /*
         * else { setRegistered( false ); }
         */
    }
}

 

通知CDT层创建

 

通知

private void fireUpdate(List breakpoints, List deltas, int update) {
        if (breakpoints.isEmpty()) {
            return; 
        }
        IBreakpoint[] bpArray = (IBreakpoint[])breakpoints.toArray(new IBreakpoint[breakpoints.size()]);
        IMarkerDelta[] deltaArray = new IMarkerDelta[bpArray.length];
        if (deltas != null) {
            deltaArray = (IMarkerDelta[])deltas.toArray(deltaArray);
        }
        // single listeners
        getBreakpointNotifier().notify(bpArray, deltaArray, update);
        
        // plural listeners
        getBreakpointsNotifier().notify(bpArray, deltaArray, update);
    }    

 

所有实现了IBreakpointsListner的类

    public void notify(IBreakpoint[] breakpoints, IMarkerDelta[] deltas, int update) {
            fType = update;
            fNotifierBreakpoints = breakpoints;
            fDeltas = deltas;
            Object[] copiedListeners = fBreakpointsListeners.getListeners();
            for (int i= 0; i < copiedListeners.length; i++) {
                fListener = (IBreakpointsListener)copiedListeners[i];
                SafeRunner.run(this);
            }
            fDeltas = null;
            fNotifierBreakpoints = null;
            fListener = null;
        }

这时候CBreakpointManager这个C层的断点管理器就收到通知了

 

breakpointsAdded 方法最后调用了setBreakpointsOnTarget0。而这个方法就关联到ICDIFunctionLocation

 

总结一下,其实整个断点的模型就是一个通知监听模式,当视图上创建了一个断点后,就通知管理器下发创建命令。而实现了断点监听的就负责创建。这时候cdt层CBreakpointManager首先了该监听。开始创建。当然还可以有其它的模型。这个可以看下debug的源码。 管理器中 setBreakpointsOnTarget0 。调用了ICDIBreakpointManagement2。创建断点。这里就调用了cdt层的Target目标机。然后继续向cdt下发。最后发送命令。

整个eclipse 源码都大量采用了这种模型框架。因此搞清楚这个原理。看源代码就好理解的多了

现在看下让断点视图上显示跟踪点的id。开始改造

 

CBreakpointManager类中的 setBreakpointsOnTarget0 这个方法差不多就是ui 跟cdt的创建断点的纽带。

我们现在需要的是cdt层的断点下发创建断点命令后,返回的跟踪点id。在ui层展示。因此在ui层我们需要CFunctionBreakpoint类来给我跟踪点的id

因此ICFunctionBreakpoint接口中我们创建跟踪点的参数跟方法

 

public interface ICFunctionBreakpoint extends ICLineBreakpoint {

    /**
     * 断点返回的跟踪点的信息
     * wangmin  
     */
    public static final String FUNCTION_TRACEPOINT_ID="org.eclipse.cdt.debug.core.funcTracepointId";

/***
*
* 跟踪点的id
* @param symbolFile
* @throws CoreException
*/
   public void setNumber( String number ) throws CoreException;
  public String getNumber( String number ) throws CoreException;





}

 

 

 

CFunctionBreakpoint中实现接口。采用IMarker的形式保存参数

    @Override
    public void setNumber(int number) throws CoreException {
        // TODO 自动生成的方法存根
        setAttribute(ICFunctionBreakpoint.FUNCTION_TRACEPOINT_ID, number);
    }

    @Override
    public int getNumber(int number) throws CoreException {
        // TODO 自动生成的方法存根
        return getMarker().getAttribute(ICFunctionBreakpoint.FUNCTION_TRACEPOINT_ID, 0);
    }

 

好了。。现在就需要让cdt层的断电来告诉最后的跟踪点id。

 

继续看CBreakpointManager 找到  doHandleLocationBreakpointCreatedEvent 这是一个 事件通知  。。嗯。cdt源码还有很重要的一种事件通知框架模型。这个以后说

这里只需要知道cdt创建完成之后这个方法就会被触发。这里我们就获取到了cdt创建完成后的 ICDILocationBreakpoint接口   so。就可以将ui层之前定义的跟踪点。设置进来了。

 

哦。cdt层也要改造。让它携带跟踪点id。首先时 ICDIBreakpoint接口 定义

    /***
     * 
     * 
     * @return
     */
         public int getNumber() ;

 

 

 

 

 

然后是其子类。:AddressBreakpoint,FunctionBreakpoint,LineBreakpoint

在其抽象父类实现LocationBreakpoint    MIBreakpoint miBreakpoints  这个就是命令下发后返回的解析后的信息类

 

     public int getNumber() 
     {    if (miBreakpoints != null && miBreakpoints.length > 0) {
            return miBreakpoints[0].getNumber();
        } 
        return 0;
         
     }

 

最后在doHandleLocationBreakpointCreatedEvent 方法中对接

    synchronized private void doHandleLocationBreakpointCreatedEvent( ICDILocationBreakpoint cdiBreakpoint ) {


...

    if (breakpoint instanceof ICFunctionBreakpoint
                            && ((ICFunctionBreakpoint) breakpoint).getCharStart() == -1
                            && ((ICFunctionBreakpoint) breakpoint).getCharEnd() == -1) {
                        ICFunctionBreakpoint bp = (ICFunctionBreakpoint)cTopMap.get(breakpoint);
                        
                        
                        bp.setNumber(cdiBreakpoint.getNumber());
...
}




}

ok..这样就可以获取了number了

 

org.eclipse.cdt.debug.internal.ui 包下

CBreakpointActionsPage类

//显示number

 

posted on 2015-09-11 16:21  代码菇凉  阅读(315)  评论(0编辑  收藏  举报

导航