一个基本块可以有 2 个以上的出边吗?

逆向工程 拆卸 静态分析 控制流图
2021-06-26 09:57:51

为了便于分析(即静态分析),我计划通过删除后向边将函数的控制流图转换为生成树。我想知道这棵生成树是否可以被认为是一棵二叉树?也就是说,一个基本块是否有可能有 2 个以上的出边?

1个回答

这取决于编译可执行文件的目标汇编语言和编译器。例如,C 语言 switch/case 子句可能以允许您的树不是二元树的方式实现。

switch (a)
{
case 1:
    return 1;
break;
case 2:
    return 10;
break;
case 3:
    return 100;
break;
case 4:
    return 1000;
break;
case 5:
    return 10000;
break;
default:
    return -1;
break;
}


00000000004004ed <main>:
  4004ed:   55                      push   %rbp
  4004ee:   48 89 e5                mov    %rsp,%rbp
  4004f1:   89 7d fc                mov    %edi,-0x4(%rbp)
  4004f4:   48 89 75 f0             mov    %rsi,-0x10(%rbp)
  4004f8:   83 7d fc 05             cmpl   $0x5,-0x4(%rbp)
  4004fc:   77 47                   ja     400545 <main+0x58>
  4004fe:   8b 45 fc                mov    -0x4(%rbp),%eax
  400501:   48 8d 14 85 00 00 00    lea    0x0(,%rax,4),%rdx
  400508:   00 
  400509:   48 8d 05 c4 00 00 00    lea    0xc4(%rip),%rax        # 4005d4 <_IO_stdin_used+0x4>
  400510:   8b 04 02                mov    (%rdx,%rax,1),%eax
  400513:   48 63 d0                movslq %eax,%rdx
  400516:   48 8d 05 b7 00 00 00    lea    0xb7(%rip),%rax        # 4005d4 <_IO_stdin_used+0x4>
  40051d:   48 01 d0                add    %rdx,%rax
  400520:   ff e0                   **jmpq   *%rax**
  400522:   b8 01 00 00 00          mov    $0x1,%eax
  400527:   eb 21                   jmp    40054a <main+0x5d>
  400529:   b8 0a 00 00 00          mov    $0xa,%eax
  40052e:   eb 1a                   jmp    40054a <main+0x5d>
  400530:   b8 64 00 00 00          mov    $0x64,%eax
  400535:   eb 13                   jmp    40054a <main+0x5d>
  400537:   b8 e8 03 00 00          mov    $0x3e8,%eax
  40053c:   eb 0c                   jmp    40054a <main+0x5d>
  40053e:   b8 10 27 00 00          mov    $0x2710,%eax
  400543:   eb 05                   jmp    40054a <main+0x5d>
  400545:   b8 ff ff ff ff          mov    $0xffffffff,%eax
  40054a:   5d                      pop    %rbp
  40054b:   c3                      retq   

例如

400520: ff e0                   **jmpq   *%rax**

指令在这个例子中实现了 switch.case 跳转。显然,以这次跳转结束的基本块将有 6 个外向边。

任何其他间接跳转也可能产生这种情况。

这篇文章中有一些很好的例子因此,您的问题的答案绝对是肯定的,存在具有 2 个以上出边的基本块,并且您的生成树不能被视为二元树。