了解 gcov 文件中的分支
我试图了解 gcov 工具的输出。在没有选项的情况下运行它是有意义的,但我想尝试并理解分支覆盖选项。不幸的是,很难理解这些分支的作用以及为什么它们没有被占用。以下是方法的输出(使用最新的 LLVM/Clang 版本进行编译)。
function -[TestCoverageAppDelegate loopThroughArray:] called 5 returned 100% blocks executed 88%
5: 30:- (NSInteger)loopThroughArray:(NSArray *)array {
5: 31: NSInteger i = 0;
22: 32: for (NSString *string in array) {
branch 0 taken 0
branch 1 taken 7
-: 33:
22: 34: }
branch 0 taken 4
branch 1 taken 3
branch 2 taken 0
branch 3 taken 3
5: 35: return i;
-: 36:}
我已经通过这个运行了 5 个测试,传入 nil、一个空数组、一个包含 1 个对象的数组、一个包含 2 个对象的数组和一个包含 4 个对象的数组。我可以猜测在第一种情况下,分支 1 意味着“进入循环”,但我不知道分支 0 是什么。在第二种情况下,分支 0 似乎再次循环,分支 1 似乎结束循环,分支 3 继续/退出循环,但我不知道分支 2 是什么或为什么/何时执行它。
如果有人知道如何破译分支信息,或者知道有关其含义的任何详细文档,我将不胜感激。
I'm trying to understand the output of the gcov tool. Running it with no options makes sense, but I'm wanting to try and understand the branch coverage options. Unfortunately it's hard to make sense of what the branches do and why they aren't taken. Below is the output for a method (compile using the latest LLVM/Clang build).
function -[TestCoverageAppDelegate loopThroughArray:] called 5 returned 100% blocks executed 88%
5: 30:- (NSInteger)loopThroughArray:(NSArray *)array {
5: 31: NSInteger i = 0;
22: 32: for (NSString *string in array) {
branch 0 taken 0
branch 1 taken 7
-: 33:
22: 34: }
branch 0 taken 4
branch 1 taken 3
branch 2 taken 0
branch 3 taken 3
5: 35: return i;
-: 36:}
I've run 5 test through this, passing in nil, an empty array, an array with 1 object, and array with 2 objects and an array with 4 objects. I can guess that in the first case, branch 1 means "go into the loop" but I haven't a clue what branch 0 is. In the second case branch 0 seems to be loop through again, branch 1 seems to be end the loop and branch 3 is continue/exit the loop, but I have no idea what branch 2 is or why/when it would be executed.
If anyone knows how to decipher the branch info, or knows of any detailed documentation on what it all means, I'd appreciate the help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Gcov 的工作原理是检测(在编译时)机器命令的每个基本块(您可以考虑汇编程序)。 基本块表示代码的线性部分,内部没有分支,内部没有标签。因此,当且仅当您开始运行基本块时,您才会到达基本块的末尾。基本块以 CFG(控制流图,将其视为有向图)组织,它显示了基本块之间的关系(从 V1 到 V2 的边是 V1 调用 V2;V2 被 V1 调用)。因此,编译器和 gcov 的
profile-arcs
模式希望获取每一行的执行计数,并通过计算基本块执行来实现这一点。 CFG 中的一些边被检测,一些则没有,因为图中的基本块之间存在代数关系。您的 ObjC 构造(for..in)被降低(在早期编译中转换)为几个基本块。因此,gcov 会看到 4 个分支,因为它只看到降低的 BB。它对这种降低一无所知,但它知道哪一行对应于每个汇编器指令(这是调试信息)。因此,分支是 CFG 的边缘。
如果您想查看基本块,您应该对已编译程序进行汇编程序转储或反汇编二进制文件或从编译器转储 CFG。您可以对
profile-arcs
和非profile-arcs
模式执行此操作并进行比较。profile-arcs 模式将有很多调用和增量,例如“__llvm_gcov_ctr”或“__llvm_gcda_edge” - 它是基本块的实际检测。
Gcov works by instrumenting (while compiling) every basic block of machine commands (you can think about assembler). Basic block means a linear section of code, which have no branches inside it and no lables inside it. So, If and only if you start running a basic block, you will reach end of basic block. Basic blocks are organized in CFG (Control flow graph, think about it as directed graph), which shows relations between basicblocks (edge from V1 to V2 is V1 calls V2; and V2 is called by V1). So,
profile-arcs
mode of compiler and gcov want to get execution count for every line and do this via counting basic block executions. Some of edges in CFG are instrumented and some are not, because there are algebraic relations between basic blocks in graph.Your ObjC construction (for..in) is lowered (converted in early compilation) to several basic blocks. So, gcov sees 4 branches, because it sees only lowered BBs. It knows nothing about this lowering, but it knows which line corresponds to every assembler instruction (this is debug info). So, branches are edges of CFG.
If you want to see basic blocks, you should do an assembler dump of compiled program or disassemble a binary or dump CFG from compiler. You can do this both for
profile-arcs
and non-profile-arcs
modes and compare them.profile-arcs
mode will have a lot calls and increments of something like "__llvm_gcov_ctr" or "__llvm_gcda_edge" - it is an actual instrumentation of basic blocks.