mcpField
O
ohos-dev-distributed-cpp-callgraph-analysis

ohos-dev-distributed-cpp-callgraph-analysis

github.com/openharmonyinsight测试与质量3538 次安装11 周前更新
代码仓库

关于 ohos-dev-distributed-cpp-callgraph-analysis

用于检查 OpenHarmony C++ 调用链和数据传递路径是否完整的技能。它结合 LSP、源码证据、边分类和覆盖矩阵;可选脚本仅用于发现候选边,不能单独证明完整性。

主要功能

  1. 01定义入口、目标行为和分析范围
  2. 02结合 LSP、源码及构建信息发现调用边
  3. 03分类直接、虚拟、回调、IPC 等边
  4. 04用调用链表整理证据
  5. 05检查代码各层的修改覆盖情况
  6. 06可选地从构建产物发现候选边

适用场景

  1. 01追踪数据字段在 OpenHarmony 子系统间的传递
  2. 02评估变更是否覆盖相关调用路径
  3. 03调查未明确的回调、IPC 或动态加载路径

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openharmonyinsight/openharmony-skills --skill ohos-dev-distributed-cpp-callgraph-analysis

安装后在 Claude Code 中输入/ohos-dev-distributed-cpp-callgraph-analysis确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

ohos_callgraph.py
README.md
evals/
evals.json
README.md
references/
lsp-bootstrap.md
scripts/
setup_lsp.py
tests/
test_ohos_callgraph.py
test_setup_lsp.py

详细介绍

OpenHarmony 调用链完整性分析

此技能包含一个决策层和可选的工具支持:

  1. Agent 工作流:唯一能够判断调用链完整性的层。它使用 LSP/源码证据、边分类和覆盖矩阵。
  2. 可选的产物回退方案:当 LSP/源码证据存在缺口或 LSP 不可用时,ohos_callgraph.py 会从构建产物中发现候选直接调用边,并尽力提供 vtable/dlopen 提示。

不要仅凭脚本输出就声称调用链完整。

引导配置仓库范围的 LSP

开始分析前,检查是否已有基于正确 OpenHarmony 产品编译上下文的可用 LSP/MCP 工具。有则使用。

如果 LSP 缺失或解析的仓库不正确,请阅读 references/lsp-bootstrap.md,并在分析前按其中说明操作。引导配置属于可选支持,而非前置条件:如果设置或冒烟测试失败,请记录 LSP 不可用或不完整,并继续使用源码、构建、符号、辅助工具和运行时证据进行分析。

如果 clangd 在某个文件上极其缓慢(CPU 占用率达到 100% 且持续数分钟),该文件可能未包含在经过筛选的 compile_commands.json 中。对于 Claude 客户端,请在设置期间传入 --install-hook,以安装 Claude PreToolUse 自动修复钩子。对于 Codex 或其他客户端,请使用 references/lsp-bootstrap.md 中“文件不在 compile_commands.json 中”一节所述的手动修复方法。

必需的工作流

1. 定义分析目标

使用工具前,请说明:

  • 入口点或事件路径,例如 OnRemoteRequest、HandleEvent 或特定子系统的入口函数。
  • 目标数据或行为,例如传播的字段、路由决策或状态转换。
  • 要纳入的范围边界:客户端/服务端、IPC、回调、虚拟接口、dlopen/dlsym 实现、生成代码和测试。
  • 有意排除的范围边界及其原因。

如果其中任何一项未知,请先检查代码,再作出有界假设。不要跳过此步骤。

2. 发现候选边

按以下顺序使用证据来源:

  1. LSP / clangd:首选的静态来源,用于查找定义、声明、引用、调用层级、候选重写项以及支持宏的符号位置。
  2. 源码搜索:使用 rg 查找 LSP 不易建模的框架模式,例如事务码、监听器注册、LoadLibrary<>、dlsym 和生成文件名。
  3. 构建图和符号工具:使用 GN/Ninja、llvm-nm、llvm-readelf、llvm-objdump 和 llvm-cxxfilt 查找库、导出项、链接边和生成产物。
  4. 仅在需要时使用辅助脚本:当 LSP/源码/构建证据仍存在无法解释的边、需要产物级确认,或 LSP 不可用/不完整时,使用 ohos_callgraph.py 发现 IR 级候选直接边,并尽力提供 vtable/dlopen 提示。
  5. 运行时跟踪:当静态证据无法唯一确定虚调用、回调、IPC 或 dlopen/dlsym 边时,使用日志、插桩或符号化跟踪。

LSP 是获取语言级 C++ 事实的首选,但不足以确定运行时绑定或 OpenHarmony 框架协议。

当 LSP/clangd 可用时,将其作为以下操作的主要途径:

  • definition / declaration
  • references
  • call hierarchy 中的传入/传出调用
  • 重写项和实现候选项
  • 宏展开后的符号位置

不要仅为重复 LSP 得到的直接调用结果而运行辅助脚本。只有当脚本能回答不同问题时才运行,例如“此编译产物是否包含候选边?”或“LSP 无法解析此路径时有哪些候选项?”

当 LSP 不可用或不完整时,请在证据表中说明,并回退到源码搜索以及构建/符号证据。

辅助脚本

资源检查:运行辅助脚本前,使用 find <obj_dir> -name '*.o' | grep <repo-filter> | wc -l 估算 bitcode 文件数量。如果文件数超过约 200 个,请缩小 --repo 过滤范围,或改用 LSP/源码证据。每个文件需要调用两次 LLVM 工具(每次约 1-2 秒),因此处理 200 个文件可能需要 5-10 分钟。

辅助脚本的必要调用形式。调用脚本前,Agent 必须确定源码树和仓库过滤条件,然后显式传入:

SCRIPT=/path/to/skills/ohos-dev-distributed-cpp-callgraph-analysis/ohos_callgraph.py
python3 "$SCRIPT" <entry-function> \
  --oh-root <openharmony-source-root> \
  --product <product-name> \
  --repo <repo-filter> \
  --depth 4 \
  --skip-prefix "Subsystem::LogHelper" --skip-prefix "Subsystem::TimeUtil"

省略 --skip-prefix 可使用内置默认值(HiLog、std::h 等)。传入一个或多个 --skip-prefix 可完全覆盖这些默认值,改用针对特定子系统的前缀。

反向查找直接调用者:

python3 "$SCRIPT" <target-function> \
  --oh-root <openharmony-source-root> \
  --product <product-name> \
  --repo <repo-filter> \
  --reverse \
  --depth 3

辅助脚本输出的是候选列表。每条重要边仍需源码证据。 在反向模式下,辅助脚本只会反向查找直接调用边,不会反向查找 vtable 或 dlopen/dlsym 提示边。

3. 对每条边进行分类

必须对每条调用链边进行分类:

类型所需证据
direct优先使用 LSP 调用层级/引用;包含调用者行号以及被调用者的定义或声明
virtual优先使用 LSP 重写候选;包含接口调用位置、候选重写项,以及已知的分发原因
callback注册位置和调用位置;LSP 可以定位符号,但通常无法证明从注册到调用的流程
ipc代理写入、存根读取、事务代码和服务处理程序
dlopen/dlsym加载位置、库/符号名称、工厂或函数指针的使用;必要时通过符号或跟踪确认
macro/generated优先使用能识别宏的 LSP 位置;包含可证明该边的生成源码或展开后的目标
unknown证据缺口;无法据此声称内容完整

对于 virtual、callback、IPC 和 dlopen/dlsym 边,列出所有相关候选项,或明确说明为何只有一个候选项适用。

4. 构建证据表

输出包含以下列的表格:

调用者被调用者/候选项边类型证据来源证据置信度是否需要变更变更状态

规则:

  • Evidence Source 是以下一个或多个值:lsp、source、build、symbol、script、runtime 或 manual。
  • Evidence 必须包含文件路径和行号。
  • Confidence 为 confirmed、candidate 或 unknown。
  • Needs Change 说明目标数据或行为为何必须经过这条边。
  • Change Status 为 done、missing、not needed 或 unknown。
  • 仅凭 script 证据,不能将非直接边标记为 confirmed。

不要将多种边类型合并到同一行。

5. 构建修改覆盖矩阵

对于数据传播变更(例如必须在多个层之间传递的字段),请检查每个适用的层面:

层面检查内容静态证据运行时证据状态
函数签名参数或对象是否携带目标数据LSP 定义/声明或源代码行可选
调用参数调用方是否传递正确的值,而非默认值或过时值LSP 调用层次结构/引用或源代码行可选
事件/对象字段字段是否正确设置、复制、克隆和重置源代码/LSP 字段引用可选
IPC 代理/存根Parcel 写入/读取顺序和事务兼容性源代码事务和 Parcel 证据如果有歧义,则提供跟踪/日志
服务分发服务端是否接收并使用该值源代码/LSP 处理程序路径如果有歧义,则提供跟踪/日志
虚函数重写所有可达的重写是否都接受或推导该值LSP 重写候选项和源代码证据如果静态分发不唯一,则必需
回调流程注册和调用是否都保留该值源代码注册/调用证据如果注册到调用的流程有歧义,则必需
dlopen/dlsym 实现加载的实现是否处理该值源代码 + 符号/构建证据如果加载目标取决于运行时,则必需
生成的代码生成的包装器和 ABI 层是否保留该值生成的源代码或构建产物证据可选
测试单元/系统测试是否至少覆盖一条有代表性的路径和边界情况测试源代码证据可用时提供测试执行结果

最终答案必须说明哪些行已完成、缺失或未知。

6. 判断完整性

使用以下标签:

  • 完整:所有相关的已确认边和候选边均标记为 done 或 not needed,且未知项已解决或明确排除在范围之外。
  • 不完整:至少有一个必需的边或层面标记为 missing。
  • 无法证明:仍有重要边标记为 unknown,或者仅凭静态证据无法确定影响结论的运行时绑定边。

辅助脚本的范围

ohos_callgraph.py 是在检查 LSP/源代码之后可选使用的产物回退方案:

  • 来自 opt --print-callgraph 的直接 IR 调用边
  • 基于 LLVM IR 元数据尽力提供的虚表接口提示
  • 基于常见 LoadLibrary<> / CreateInstance 模式尽力提供的 dlopen 提示
  • 仅反向查找直接调用方;反向模式不包含虚表或 dlopen/dlsym 提示边

局限性:

  • 它无法证明所有可能的 C++ 调用。
  • 它无法将运行时虚分发解析为唯一的重写实现。
  • 它无法证明回调、函数指针或 std::function 的目标。
  • 它无法证明 IPC 参数传播。
  • 它无法证明字段传播。--name-keyword 仅检查反混淆后的函数名和直接子函数名,作为粗略提示;它不会检查 C++ 参数名、调用参数、成员访问、局部变量或 IPC 序列化。
  • 如果构建产物过时、缺少位码、优化方式不同或外部工具失败,它可能会遗漏边。

仅将辅助脚本用作证据工作流中的候选项发现工具。如果 LSP/源代码证据已覆盖相关直接调用,且不需要产物级确认,则跳过此脚本。

LSP 指引

仅当 LSP/clangd 使用的编译上下文适用于正在审查的 OpenHarmony 产品时,才将其作为证据。如果仓库缺少 compile_commands.json,或 clangd 无法解析 include/宏,则应将 LSP 证据标记为不完整,并改用源码/构建证据。

当 LSP 不可用且环境允许进行配置时,应先遵循引导仓库范围的 LSP,再考虑其他方式。若能生成仓库范围的数据库,就不要直接使用产品范围的编译数据库;产品数据库可能有数 GB,会造成不必要的索引开销。

建议执行的 LSP 证据检查:

  • 对于直接函数调用,使用调用点的出站调用层次结构或转到定义,然后记录调用方和被调用方所在的文件行。
  • 对于反向分析,使用入站调用层次结构和引用,然后手动验证调用点。
  • 对于虚调用,使用实现/重写查询列出候选项。除非构造/注册/源码规则或运行时跟踪能够证明确切目标,否则应将候选项保留为 candidate。
  • 对于宏,使用 LSP 获取解析后的符号位置;必要时记录宏或生成的展开源码。

不要仅凭 LSP 确认回调流、IPC 分发或 dlopen/dlsym 目标。

必需的最终回复格式

使用此技能时,结尾必须包含:

  1. 范围:入口点、目标数据/行为、涵盖的边界。
  2. 证据表:逐边列出证据来源、证据、置信度和状态。
  3. 覆盖矩阵:列出修改面、静态证据、运行时证据和状态。
  4. 结论:Complete、Incomplete 或 Not provable,并准确列出缺失或未知的项目。

如果无法检查必需的边界,请说明原因并将其标记为 unknown。

示例:MMI 子系统

分析多模态输入(MMI)子系统时,常见的分析目标包括:

  • 入口点:HandleMouseEvent、UpdateMouseTarget、OnRemoteRequest
  • 传播字段:groupId、displayId、指针目标路由、设备绑定
  • 跳过前缀:OHOS::MMI::FormatLog、OHOS::MMI::GetSysClockTime、OHOS::MMI::InnerFunction(通过 --skip-prefix 传入)
  • 关键边界:通过 MultimodalInputConnectStub 进行客户端/服务端 IPC、EventDispatchHandler 回调链、InputDeviceManager 的 dlopen 加载

评论

支持 Markdown