我目前正在为 LLVM 编写一个新的前端,在堆栈上使用大型数组时遇到了一个问题。显然,编译器在具有大堆栈的函数中插入对 __chkstk 的引用,这很好,但会导致链接器错误:
lld-link: error: undefined symbol: __chkstk
我明白 __chkstk 的目的,我不想做变通方法,比如实现虚拟函数、设置 /Gs9999999... 或我在论坛帖子中看到的任何其他变通方法。相反,我想实际上只是链接到此功能,无论它在哪里。实际上,我什至从等式中删除了我自己的代码,我只是使用了 clang 和其他 llvm 工具,并且可以显示以下内容:
PS> cat hello.c
int main()
{
char buffer[10000000];
}
PS> clang -S -emit-llvm hello.c
PS> cat hello.ll ; ModuleID = 'hello.c'
source_filename = "hello.c"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.29.30038"
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca [10000000 x i8],align 16
ret i32 0
}
attributes #0 = { noinline nounwind optnone uwtable "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0,!1}
!llvm.ident = !{!2}
!0 = !{i32 1,!"wchar_size",i32 2}
!1 = !{i32 7,!"PIC Level",i32 2}
!2 = !{!"clang version 12.0.1"}
PS> llc -o hello.obj --filetype=obj hello.ll
PS> lld-link /out:hello.exe /entry:main hello.obj lld-link: error: undefined symbol: __chkstk
>>> referenced by hello.obj:(main)
实际上,当我使用 link.exe 而不是 lld-link 时,我得到了同样的错误。
error LNK2001: unresolved external symbol __chkstk
当我直接编译为可执行文件 clang hello.c -o hello.exe
时,这工作得很好,所以我想在幕后,clang 正在对链接器选项做一些特殊的事情,或者它只是阻止插入 __chkstk 符号首先?如果我没有充分的理由不这样做,我通常会采用与 clang 相同的方法,但是 clang 的这个领域对我来说是不透明的。
那么我的问题是,clang 在这里做什么 lib 文件(或其他链接器选项)?或者我如何以其他方式包含包含 __chkstk 的头文件/lib 文件?