vsc++调试没有调试界面_了解C / C ++调试器界面

vsc++调试没有调试界面

命令行界面是调试的有用工具,但没有什么能像精心设计的图形环境那样散发出专业性和精致感。 从头开始构建功能全面的调试环境需要花费大量时间和精力,但是还有一种选择:Eclipse C / C ++开发工具(CDT)。 CDT的可扩展性允许您将其图形调试功能连接到自定义调试器。 这不需要很多代码,但是您需要了解CDT的扩展点和CDI。

CDI是基于Java™的应用程序编程接口(API),其类和接口使访问CDT的调试框架成为可能。 使用CDI的Eclipse插件可以将新的调试器添加到CDT的操作中,并在Eclipse / CDT调试透视图中显示调试结果。 本文详细介绍了CDI。 该“ 与CDT调试器接口 ”系列的第2部分展示了CDI如何通过其机器接口(MI)专门用于GNU调试器(gdb)的接口。

示例CDI插件

学习CDT调试器如何工作的最好方法是查看并试验实际代码。 本文介绍了如何构建功能不足的插件,该插件扩展了CDT以提供基本的调试功能。 没有实际的调试器可执行文件,但是您可以使用此代码作为将自己的自定义调试器添加到CDT的基础。

该示例插件由CDT和Eclipse Debug Framework的三个扩展组成:

org.eclipse.debug.core.launchConfigurationTypes
创建一个单独的启动器来调试C / C ++应用程序
org.eclipse.debug.ui.launchConfigurationTabGroups
从用户接收调试配置参数
org.eclipse.cdt.debug.core.CDebugger
为启动的C / C ++应用程序创建调试会话

本文介绍了每种方法,并提供了示例代码说明它们如何工作。 然后深入研究CDI的操作,涵盖CDI模型并研究CDI如何使断点和观察点成为可能。

创建自定义启动配置类型

在Eclipse中,启动应用程序的过程称为在运行模式下启动应用程序。 调试会话称为“ 调试”模式下的启动。 选择启动模式后,下一步就是选择启动配置类型。 这准确地告诉Eclipse应用程序应如何执行或调试。 例如,“调试”模式的启动配置类型定义了调试器可执行文件,默认调试选项以及应如何在Eclipse中显示调试输出。 图1显示了“ CDT调试配置”窗口中显示的配置类型。

图1. CDT启动配置窗口
vsc++调试没有调试界面_了解C / C ++调试器界面_第1张图片

要将新的调试器与Eclipse接口,第一步是创建新的启动配置类型。 这需要一个扩展org.eclipse.debug.core.launchConfigurationTypes扩展点的插件。 在图1中,您可以在窗口左侧看到示例配置类型。 清单1显示了定义此新类型的扩展。

清单1.示例LaunchConfigurationType扩展

      
      
   

由于将modes字段设置为debug并将public字段设置为true ,因此将示例配置类型放置在Debug窗口中。 最重要的字段是delegate ,它标识管理启动过程的类。 此类必须实现ILaunchConfigurationDelegate接口,并且从头开始编写委托可能很复杂。 值得庆幸的是,CDT通过提供四个预构建的委托类使您的生活更轻松:

LocalRunLaunchDelegate
运行本地C / C ++应用程序
LocalAttachLaunchDelegate
调试本地应用程序
CoreFileLaunchDelegate
执行后分析核心文件
LocalCDILaunchDelegate
连接本地CDI调试器

CDT将前三个用于本地软件启动。 最后一个代表是为CDT之外的工具创建的,并且是此讨论的重点。 当调用LocalCDILaunchDelegate以调试模式启动时,它获得有关要调试的可执行文件和要发送到调试器的参数的信息。 此信息必须打包在ILaunchConfiguration对象中,并且需要合适的UI才能从用户那里获取此信息。

为启动配置添加选项卡组

在调试Eclipse应用程序之前,必须选择启动配置类型,然后通过双击或右键单击来创建新的启动配置。 此时,右侧将出现一个图形面板,并请求与启动有关的信息。 该面板称为启动配置选项卡组 。 图1的右侧显示了一个示例选项卡组。该选项卡组由多个选项卡组成,图1中的可见选项卡接受要调试的可执行文件及其项目的名称。

每次启动都必须具有自己的选项卡组,并且必须在plugin-in.xml中将其标识为org.eclipse.debug.ui.launchConfigurationTabGroups的扩展。 清单2显示了此扩展在本示例中的外观。

清单2.声明示例选项卡组

      
      
   

此扩展很容易理解。 type字段标识启动配置, class标识创建选项卡组的类, id为选项卡组提供唯一的名称。 由类标识的class必须实现ILaunchConfigurationTabGroup接口,其工作是创建一个或多个ILaunchConfigurationTab 这些选项卡为调试器提供了操作所需的信息,包括调试标志,源代码的位置和内存地址。 要配置ILaunchConfigurationTab来完成其工作,您必须实现两个重要的方法:

  • createControl(Composite parent) —为调试器选项卡创建用户界面
  • performApply(ILaunchConfigurationWorkingCopy configuration) —配置调试器参数

第二种方法特别重要。 它通过为LaunchConfigurationWorkingCopy属性分配值来LaunchConfigurationWorkingCopy 此数据对象包含调试所需的信息,并且在调试会话开始时将其发送到调试器。 属性名称在ICDTLaunchConfigurationConstants接口中列出。 重要属性包括:

ATTR_DEBUGGER_ID
要启动的调试器的ID
ATTR_DEBUGGER_SPECIFIC_ATTRS_MAP
提供给调试器会话的属性
ATTR_PROJECT_NAME
被调试项目的名称
ATTR_PROGRAM_NAME
被调试程序的名称
ATTR_PROGRAM_ARGUMENTS
提供给正在运行的程序的参数
ATTR_PLATFORM
运行程序的操作系统

ExampleConfigurationTabGroup代码创建一个配置选项卡: ExampleTab 此选项卡显示六个预初始化的文本框-每个先前详述的属性。 图2显示了ExampleTab外观。 通常,您应该创建带有各种控件的多个选项卡。 CDT提供了用于配置C / C ++调试器的CDebuggerTab类。

图2.示例启动配置选项卡
vsc++调试没有调试界面_了解C / C ++调试器界面_第2张图片

ExampleTab的代码使用setDefaults()方法初始化调试属性。 此方法将示例调试器标识为要使用的调试器,并搜索选定的CDT资源以查找要调试的项目和程序。 执行此搜索不需要新代码,因为ExampleConfigurationTab扩展了CDT的CLaunchConfigurationTab类。 这个抽象类提供了两个重要的方法: getContext()返回CDT资源, initializeCProject()使用项目名称初始化ATTR_PROJECT_NAME属性。

创建自定义调试器

当您单击Debug时 ,Eclipse将搜索ATTR_DEBUGGER_ID属性标识的调试器。 在示例项目中,将其设置为org.dworks.debugexample.ExampleDebugger ,它与示例项目扩展名org.eclipse.cdt.debug.core.CDebuggerid字段相对应。 清单3展示了完整的扩展。

清单3.示例调试器扩展点

      
      
   

当调试器启动时,Eclipse将检查调试器的platformcpu元素是否支持处理环境。 如果是这样,它将检查以确保调试器的mode元素支持当前的启动模式。 如果所有检查均通过,则Eclipse将在class字段中找到标识的class 此类必须实现ICDIDebugger2接口,因此必须提供createSession()方法的实现。

createSession()的目标是构造一个实现ICDISession接口的对象。 此对象使CDT可以在调试器运行时访问调试器。 此访问提供了许多方法,其中最重要的三个方法如下:

  • getSessionProcess() —返回正在运行的调试器的进程
  • getTargets() —返回要调试的目标数组
  • getEventManager() —返回添加和删除事件侦听器的管理器对象

这些方法中的第一个很简单,并且返回与调试器可执行文件相对应的Process对象。 接下来的两个方法getTargets()getEventManager()涉及更多。 本文的其余部分将对它们进行解释。 因为这些方法取决于调试器可执行文件,并且由于示例插件没有插件,所以ExampleDebugger类将这些方法ExampleDebugger空。

目标,事件和CDI模型

当CDT调用getTargets() ,会话必须为正在调试的每个进程提供ICDITarget ICDITarget的工作是接收调试命令,将其转换为调试器,然后将其发送给调试器。 例如,当您单击CDT调试透视图中的“ 步骤”或“ 继续”按钮时,CDT分别调用目标的stepOver()resume()方法。 CDI对调试器目标接口的工作方式没有任何要求,但是第2部分解释了gdb如何使用MI协议与目标接口。

除了将命令发送到调试器之外, ICDITarget还将调试器的输出发送给任何有兴趣接收调试器的对象。 这是通过CDI事件完成的,这是会话的getEventManager()方法所在的位置。当任何CDI对象(例如RegisterView )希望收到调试器事件的通知时,它将调用getEventManager()来访问会话的ICDIEventManager 然后,它调用管理器的addEventListener()方法将自身添加为侦听器。 当调试器产生输出时,目标调用管理器以警告其所有侦听器。 管理器通过调用每个侦听器的handleDebugEvents()方法来执行此操作,该方法必须由所有ICDIEventListener实现。

CDI提供了一组标准的ICDIEvent 每个调试器的响应或调试环境中的更改必须打包为以下之一:

ICDIBreakpointMovedEvent
当用户选择新的断点时触发
ICDIChangedEvent
当目标的某个方面(例如变量,寄存器或内存的一部分)更改值时触发
ICDICreationEvent/ICDIDestroyedEvent
当创建或删除对象(例如断点)时触发
ICDIExitedEvent
程序完成时触发
ICDIRestartedEvent/ICDIDisconnectedEvent
目标重新启动或断开连接时触发
ICDIExecutableReloadedEvent
重新加载程序时触发,例如在生成新版本后触发
ICDISuspendedEvent/ICDIRestartedEvent/ICDIResumedEvent
当可执行文件停止,重新启动或恢复时触发

部分2点的细节的gdb输出是如何转化为MIEvent S和如何MIEvent小号成为ICDIEvent秒。

ICDIChangedEvent特别重要,因为每次目标更改时都会触发该事件。 目标的每个可变方面都由ICDIObject表示,这些对象形成称为CDI模型的层次结构。 它们包括ICDIRegisterICDIVariableICDIMemoryBlockICDIThread等等。 ICDITarget是这些CDI模型对象的根和容器。 每个ICDIObject必须实现的唯一方法是getTarget()

CDI断点和观察点

控制调试器的两种最重要的方法是使用断点和观察点。 一旦到达特定位置或满足条件,断点就会终止调试器。 当读取或写入特定变量时,监视点将停止调试器。 CDI提供了两个接口来表示这些接口: ICDIBreakpoint及其子接口ICDIWatchpoint ICDIBreakpoint可以是常规的,临时的或硬件辅助的; ICDIWatchpoint可以是读类型,写类型或两者都可以。

您可以通过ICDIBreakpointManagement实例创建和删除断点和观察点。 这提供了许多相关方法,例如setLineBreakpoint()deleteBreakpoints()setWatchpoint() 但请务必记住, org.eclipse.debug.core插件的插件类提供了自己的断点管理器IBreakpointManager ,您可以使用DebugPlugin.getDefault().getBreakpointManager() 在许多情况下,您可能需要访问它并将IBreakpoint转换为ICDIBreakpoint

结论

从头开始构建图形调试环境是一项艰巨的任务:不仅必须了解目标处理器的内外,而且还必须与调试器进行通信并将其输出传递给图形用户环境。 对于不是Hercules的用户,Eclipse提供了一个API,用于将自定义调试器添加到CDT框架。 该API称为C / C ++调试器接口(CDI),本文介绍了其操作和使用的基础知识。 本系列“ 与CDT调试器接口 ”的第2部分介绍了CDT如何使用CDI来连接所有最好的开源调试器:GNU调试器(gdb)。


翻译自: https://www.ibm.com/developerworks/opensource/library/os-eclipse-cdt-debug1/index.html

vsc++调试没有调试界面

你可能感兴趣的:(vsc++调试没有调试界面_了解C / C ++调试器界面)