简体   繁体   中英

Nm shows symbol in shared library, but undefined symbol when linking

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

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()

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;
}

And compiled it like so:

$ 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)

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

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

If has_init is not part of a class, then you can still call the function by it's mangled name. However, this will only work if it is a free function. If it is part of a class, then you can not really call it without class definition, as you don't know what it does to the class members and you would have to pass the object as the first argument.

#include <iostream>
#include <dlfcn.h>

using namespace std;

typedef int hsa_status_t;
typedef hsa_status_t (*hsa_init_t)();
hsa_init_t hsa_init;

const char *hsa_init_name = "__ZN3HSA8hsa_initEv";
const char *libPath = "/System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver";

int main()
{
    void *libraryHandle = dlopen(libPath, RTLD_NOW);
    if (!libraryHandle)
    {
        cout << "Error opening library: " << libPath << " Error: " << dlerror() << endl;
        return 0;
    }
    dlerror(); // clear any existing error

    hsa_init = (hsa_init_t)dlsym(libraryHandle, hsa_init_name);
    if (!hsa_init)
    {
        cout << "Error importing symbol: " << hsa_init_name << " Error: " << dlerror() << endl;
        return 0;
    }

    hsa_init();

    return 0;
}

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, ...

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM