如何将 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.cclang 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 进行链接时

win iCloud移动到非C盘

如何使静态库中的 gcc 链接强符号覆盖弱符号?

使用 SqlBulkCopy,如何将数据插入到非默认数据库架构中的表中?

如何使函数具有库内部链接?