Skip to content

fla处理后报错“Terminator found in the middle of a basic block!”,基本块中含有多个terminator #39

@c10udlnk

Description

@c10udlnk

在实际使用fla模式发现会报错:
image

测试代码:

#include <stdio.h>
#include <stdint.h>

int main() {
    uint32_t v[2] = {0x12345678, 0x12345678};
    uint32_t k[4] = {0x90ABCDEF, 0x90ABCDEF, 0x90ABCDEF, 0x90ABCDEF};
    uint32_t sum = 0, delta = 0x9e3779b9;
    for (int i = 0; i < 32; i++) {
        sum += delta;
        v[0] += ((v[1]<<4) + k[0]) ^ (v[1] + sum) ^ ((v[1]>>5) + k[1]);
        v[1] += ((v[0]<<4) + k[2]) ^ (v[0] + sum) ^ ((v[0]>>5) + k[3]);
    }
    printf("%u %u", v[0], v[1]);
    return 0;
}

fla处理后的IR:
image

可见确实有两个terminator,这违反了LLVM验证时的“每个基本块末尾必须只有一个合法的终结符指令”要求。

查看Flattening.cpp发现:只有在第一个基本块(entryBB)的末尾是条件跳转时,才会删除entryBB的terminator(后面的基本块判断BB->getTerminator()->getNumSuccessors() == 1时也是这个代码,重复处理?)。但按照平坦化的原理来说块后面增加到returnBB的跳转之前也要把原来的跳转删掉?即:

// 原65行
    if (bEntryBB_isConditional) {
        entryBB.getTerminator()->eraseFromParent();
    }
// 改为
    entryBB.getTerminator()->eraseFromParent();
// 原97行
            if (bEntryBB_isConditional) {
                entryBB.getTerminator()->eraseFromParent();
            }
// 改为
            BB->getTerminator()->eraseFromParent();

修改后再编译,测试程序就能被平坦化处理且能正常运行了。

然后查看commits发现这是在 2f70402 里面刚刚改的,为什么这个commit里删除terminator前要做一个bEntryBB_isConditional的判断呢……?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions