__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
它显示了发送到链接器的完整参数集,并提供了一个很好的模板作为起点。
我目前正在为 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
它显示了发送到链接器的完整参数集,并提供了一个很好的模板作为起点。