如何使用“ clang”启用“ cfi”为“ aarch64”编译“ .c”文件?

时间:2019-04-11 14:40:22

标签: clang sanitization address-sanitizer

我正在构建“ main.c”文件:

int sum(int x, int y) {
  return x + y;
}

int dbl(int x) {
  return x + x;
}

void call_fn(int (*fn)(int)) {
  (*fn)(42);
}

void erase_type(void *fn) {
  call_fn(fn);
}

int main() {
  erase_type(sum);
  return 0;
}

对于使用以下命令启用了“ cfi”清理程序功能的主机“ x86”平台:

./clang-8 \
-fsanitize=cfi \
-fvisibility=hidden \
-fno-sanitize-trap=all \
-fuse-ld=gold \
-flto \
main.c \
-o \
main

现在,我需要为“ aarch64”处理器编译该文件。 我知道如何简单地编译该文件(具有禁用的CFI功能)。

rm -f main.o && \
./clang-8 \
-cc1 \
-triple \
aarch64-funnyos-unknown-gnueabi \
-emit-obj \
-target-cpu \
generic \
-O2 \
-Wall \
-o \
main.o \
-x \
c \
main.c \
&& \
file main.o

但是我不知道如何在启用“ cfi”的情况下为“ aarch64”编译“ main.c”文件。

有人知道怎么做吗?

UPD。假设CPU是ARMv8类型的,而Linux例如在QEMU仿真器上运行。假设主机是x86并在Linux上运行。我需要在x86 Linux主机上为ARMv8目标(在QEMU,Linux上运行)交叉编译代码。

2 个答案:

答案 0 :(得分:0)

您的x86和AArch64命令非常不同。第一个运行编译器 driver ,该编译器支持compiler flags(尤其是-fsanitize=cfi)。

第二条命令虽然运行编译器 proper (如-cc1开关所示)。这是一种内部模式:它是在后台由编译器驱动程序运行的,因此它不支持正常的编译器标志,并且不打算由普通用户运行。您应该切换到在AArch64上使用编译器驱动程序。

答案 1 :(得分:0)

首先,我们需要使用clang的编译器将main.c编译为llvm的中间代码:

./clang-8 \
--target=\
aarch64-funnyos-unknown-gnueabi \
-c \
-flto \
-fsanitize=cfi \
-fvisibility=default \
main.c \
-o \
main.o

下一步是使用gold插件(来自LLVM项目),通过gold链接器(例如,来自AndroidNDK)将此代码转换/链接为二进制文件,并告知链接器仿真模式(-m选项),这意味着体系结构应生成二进制文件):

/PATH/TO/aarch64-linux-android-4.9/prebuilt/linux-x86_64/aarch64-linux-android/bin/ld.gold \
-pie \
-m \
aarch64_elf64_le_vec \
-o \
main \
-plugin \
/PATH/TO/llvm-project/build/lib/LLVMgold.so \
-plugin-opt=mcpu=generic \
-plugin-opt=O2 \
-plugin-opt=-debugger-tune=gdb \
main.o

P.S。感谢@yugr的帮助和帮助!