使用gcc/clang对齐死代码中的标签值

wj8zmpe1  于 2023-02-18  发布在  其他
关注(0)|答案(1)|浏览(146)

在某些编译器上(我最感兴趣的是GCC/clang)使用void *jmp = &&label,您可以获得标签的地址,稍后可以使用goto jmp。对于使用指针标记的解释器,我希望将这些标签与下一个8字节边界对齐,因此标签值都具有0b...000。通常,您可以将指令位置与汇编对齐,例如,__asm__ volatile(".p2align 8");将使用NOP s等填充2^8字节的下一条指令。但是,由于解释器在跳转块之间没有代码,因此汇编得到了优化(或其他-即使使用volatile,它也不会出现在输出中)。

void test() {
    void *next = &&LABEL_A;
    goto *next;

/* won't get reached – optimized away? */
__asm__ volatile(".p2align 8");
LABEL_A:
    goto *next;
}

godbolt上,它显示编译器没有对齐LABEL_A

void test() {
    unsigned long foo = (unsigned long)&&LABEL;
    void *next = &&LABEL_A;
    goto *next;
LABEL:
__asm__ volatile(".p2align 8");
LABEL_A:
    goto *next;
}

output将显示LABEL_A得到了正确的填充-大概是因为LABEL和下面的语句无法得到优化。然而,这似乎非常脆弱,不适用于-O3。有更好的方法吗?
我尝试了几个__attribute__(aligned(8), used)属性、块之间的volatile值/访问,尽管只有LABEL引用阻止了代码消除。

vfwfrxfs

vfwfrxfs1#

对于GCC,应该使用-falign-labels=8或较弱的-falign-jumps=8选项。
您可以将它们放在函数属性中:__attribute__((optimise ("-falign-labels=8")).

相关问题