Nm在共享库中显示符号,但在链接时未定义符号 [英] Nm shows symbol in shared library, but undefined symbol when linking

查看:253
本文介绍了Nm在共享库中显示符号,但在链接时未定义符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为一项心理锻炼,我试图编写一个直接与Macbook Pro的GPU驱动程序链接的程序,而不是使用Apple的Metal框架.经过一些探索,我找到了这个文件(可能是特定于我的特定硬件):

As a mental exercise, I'm trying to write a program that links directly against the GPU driver of my Macbook Pro rather than using Apple's Metal framework. Some exploration led me to this file (presumably specific to my particular hardware):

/System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver

在其上运行 file 确认这是一个Mach-O 64位动态链接的共享库.在其上运行 nm 会告诉我这是AMD ROCr运行时的超集.特别让我感兴趣的一个符号就是这个:

Running file on it confirms this is a Mach-O 64-bit dynamically linked shared library. Running nm on it tells me it's a superset of AMD's ROCr runtime. One symbol in particular that interests me is this one:

$ nm -gD AMDRadeonX6000MTLDriver | grep "hsa_init"
00000000001cca20 T __ZN3HSA8hsa_initEv
$ nm -gCD AMDRadeonX6000MTLDriver | grep "hsa_init"
00000000001cca20 T HSA::hsa_init()

所以我写了这个简单的程序( rocr_test.cpp ):

So I wrote this simple program (rocr_test.cpp):

typedef int hsa_status_t;

namespace HSA {
    hsa_status_t hsa_init();
}

int main() {
    HSA::hsa_init();
    return 0;
}

并像这样编译它:

$ clang++ rocr_test.cpp -c
$ clang++ rocr_test.o /System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver
Undefined symbols for architecture x86_64:
  "HSA::hsa_init()", referenced from:
      _main in rocr_main-95c854.o
ld: symbol(s) not found for architecture x86_64
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)

但是,目标文件上的 nm 显示链接器应查找具有相同名称的符号:

However, nm on the object file shows the linker should look for a symbol with the same name:

$ nm rocr_test.o          
                 U __ZN3HSA8hsa_initEv
0000000000000000 T _main

nm 显示共享库中明确存在具有该确切名称的符号时,为什么会出现此链接器错误?

Why am I seeing this linker error, when nm shows that a symbol with this exact name clearly exists in the shared library?

推荐答案

Apple的编译器有些不同,为了与库链接,它需要使用".tbd"标记.文件.这是一个文本文件,包含符号列表、UUID 和它所链接的 mach-O 的基本细节.您可以在SDK中找到大量示例(转到SDK根目录并找到.-type f -name"* .tbd").TBD看起来像:

Apple's compiler is a bit different, and in order to link with libraries it needs to use a ".tbd" file. This is a textual file containing the symbol list, a UUID and the basic details of a mach-O it is linked against. You can find plenty of examples of those in the SDK (go to the SDK root and find . -type f -name "*.tbd"). The TBD would look something like:

    --- !tapi-tbd-v3
archs:          [ x86_64 ]
uuids:          ['x86_64: 8891E6F5-0B7C-3CC7-88C1-9F5303311EC7' ]
platform:       ios
install-name:  /System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver
objc-constraint:        none
exports:
  - archs:      [ x86_64 ]
    symbols:          [  __Z34amdMtl_GFX10_GetFallbackFamilyNameP15GFX10_HwInfoRec, __Z35amdMtl_GFX10_GetFallbackProductNameP15GFX10_HwInfoRec, __Z25amdMtl_GFX10_AllocLsHsMgrP15GFX10_MtlDeviceP14AMDPPMemMgrRec, ...

您必须为Bundle创建一个TBD(以上内容是使用jtool2 --tbd创建的),并指示编译器使用它(或将其放置在SDK目录中),并且应该(希望)能正常工作

You'd have to create a TBD for the Bundle, (the above was created using jtool2 --tbd), and direct the compiler to use it (or place it in the SDK directory) and that should (hopefully) work.

这篇关于Nm在共享库中显示符号,但在链接时未定义符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆