如何将 C 声明链接到非标准部分中的符号?
Posted
技术标签:
【中文标题】如何将 C 声明链接到非标准部分中的符号?【英文标题】:How can I link a C declaration against a symbol in a non-standard section? 【发布时间】:2018-01-19 17:12:34 【问题描述】:我正在尝试使用LLVM's stack map intrinsics,但我无法弄清楚如何处理从 C 程序生成的数据。举个简单的例子,我有以下文件:
st.ll
:
declare void @llvm.experimental.stackmap(i64, i32, ...)
define i32 @some_func(i32 %x)
%y = add i32 %x, %x
call void(i64, i32, ...) @llvm.experimental.stackmap(i64 3735928559, i32 0, i32 %x, i32 %y)
ret i32 %y
ex.c
:
#include <stdio.h>
extern char __LLVM_StackMaps;
int main(void)
fwrite(&__LLVM_StackMaps, sizeof(char), 10, stdout);
return 0;
如果我运行clang -c st.ll
,然后使用nm -f s st.o
检查生成的目标文件,我会得到以下输出:
Symbols from st.o:
Name Value Class Type Size Line Section
__LLVM_StackMaps |0000000000000000| r | NOTYPE| | |.llvm_stackmaps
some_func |0000000000000000| T | FUNC|0000000000000018| |.text
显然,正在生成__LLVM_StackMaps
符号。但是,如果我运行 clang st.ll ex.c
或 clang st.o ex.c
,我会收到此错误:
/tmp/ex-06d9d2.o: In function `main':
ex.c:(.text+0xb): undefined reference to `__LLVM_StackMaps'
clang-5.0: error: linker command failed with exit code 1 (use -v to see invocation)
据我所知,问题在于符号位于 .llvm_stackmaps
部分而不是 .data
或 .bss
。
我该如何解决这个问题?有没有办法在 C 中指定源部分?我可以告诉链接器从.llvm_stackmaps
部分解析吗?
【问题讨论】:
为什么需要__LLVM_StackMaps
符号?我怀疑,它不打算直接从 C 代码中使用。
我需要它来进行堆栈遍历,以便实现垃圾收集器。不过,此时此刻,我主要只是想尝试在调试器中使用地图作为指导,因此我想拉入地图并将数据解析为更好的格式。
然后,我认为,您需要直接在 LLVM IR 中编写一个薄的“运行时”层,该层将执行对 stackmap 内在函数的调用。然后使用运行时的助手在 C 端做一些事情。
是的,我正在使用 stackmap 内部函数生成地图,但您不需要运行时来访问地图。
【参考方案1】:
gnu::section 属性应该可以做到这一点。 clang 显然还支持执行相同操作的 gcc 样式 attribute((section("...")) 和 msvc 样式 __declspec(allocate("...")) 语法。
[gnu::section("....")] void my_func(long, long);
【讨论】:
我尝试将extern
行更改为extern char __LLVM_StackMaps __attribute__ ((section (".llvm_stackmaps")));
(也尝试不使用.
),但仍然失败——我认为该属性仅用于指定放置 符号,而不是在哪里查找。【参考方案2】:
我发现了这个问题——该部分与它无关;只是__LLVM_StackMaps
符号是本地的(正如nm
使用r
类而不是R
报告它所证明的那样)。我尝试先将st.ll
编译为汇编,然后在组装之前手动添加.globl
,并且链接正常。
【讨论】:
如果你尝试用全局__LLVM_StackMaps
链接两个对象文件会不会出错?
是的,但我没有在ex.c
中定义一个全局__LLVM_StackMaps
,而是用extern
声明一个。以上是关于如何将 C 声明链接到非标准部分中的符号?的主要内容,如果未能解决你的问题,请参考以下文章
尽管链接到带有导出符号的 .lib 文件,但从托管 C++ 链接到非托管 C++ 时出现链接错误
如何在运行时解析 dll 中的外部符号,而不是使用 Cygwin 进行链接时