__chkstk 在哪里定义的?

Where is __chkstk defined?

我目前正在为 LLVM 编写一个新的前端,并且在堆栈上使用大型数组时遇到了一个问题。显然,编译器在具有大堆栈的函数中插入对 __chkstk 的引用,这很好,但会导致 linker 错误:

lld-link: error: undefined symbol: __chkstk

我明白 __chkstk 的目的,我不想做变通办法,比如实现虚拟函数、设置 /Gs9999999... 或我在论坛帖子上看到的任何其他变通办法.相反,我只想 link 这个功能,无论它在哪里。实际上,我什至从等式中删除了我自己的代码,我只是使用 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 正在使用 linker 选项做一些特殊的事情,或者它可能是只是首先阻止插入 __chkstk 符号?如果我没有充分的理由不这样做,我通常希望采用与 clang 相同的方法,但是 clang 的这个区域对我来说是不透明的。

那么我的问题是,clang 在这里做什么 lib 文件(或其他 linker 选项)?或者我如何以其他方式包含包含 __chkstk?

的 header/lib 文件

几经周折,我终于想通了,我认为是正确的方法。我只使用 Windows SDK,这不足以在 Windows 上构建,您还需要 Visual Studio,或者至少只需要构建工具。因此,作为我的工具链安装的一部分,我现在安装了这两个,并将这些参数用于链接器:

/defaultlib:C:\Program Files (x86)\Windows Kits\Lib${sdkVersion}\ucrt${targetDepth}\ucrt.lib

并添加“msvcrt.lib”和“libcmt.lib”,位于C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Tools\MSVC${msvcVersion}\lib\

我自己不分发任何这些文件,而是 运行 Windows SDK 和 MSVC Build Tools 的安装程序,然后希望这些文件中存在正确的 lib 文件地点。

我得到的一个很好的提示是查看 clang 命令的详细输出,clang hello.c -o hello.exe -v 它显示了发送到链接器的完整参数集,并提供了一个很好的模板作为起点。