1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20/*!
21 * \file dso_libary.cc
22 * \brief Create library module to load from dynamic shared library.
23 */
24#include <tvm/runtime/memory.h>
25#include <tvm/runtime/module.h>
26#include <tvm/runtime/packed_func.h>
27#include <tvm/runtime/registry.h>
28
29#include "library_module.h"
30
31#if defined(_WIN32)
32#include <windows.h>
33#else
34#include <dlfcn.h>
35#endif
36
37#if defined(__hexagon__)
38extern "C" {
39#include <HAP_farf.h>
40}
41#endif
42
43namespace tvm {
44namespace runtime {
45
46/*!
47 * \brief Dynamic shared library object used to load
48 * and retrieve symbols by name. This is the default
49 * module TVM uses for host-side AOT compilation.
50 */
51class DSOLibrary final : public Library {
52 public:
53 ~DSOLibrary();
54 /*!
55 * \brief Initialize by loading and storing
56 * a handle to the underlying shared library.
57 * \param name The string name/path to the
58 * shared library over which to initialize.
59 */
60 void Init(const std::string& name);
61 /*!
62 * \brief Returns the symbol address within
63 * the shared library for a given symbol name.
64 * \param name The name of the symbol.
65 * \return The symbol.
66 */
67 void* GetSymbol(const char* name) final;
68
69 private:
70 /*! \brief Private implementation of symbol lookup.
71 * Implementation is operating system dependent.
72 * \param The name of the symbol.
73 * \return The symbol.
74 */
75 void* GetSymbol_(const char* name);
76 /*! \brief Implementation of shared library load.
77 * Implementation is operating system dependent.
78 * \param The name/path of the shared library.
79 */
80 void Load(const std::string& name);
81 /*! \brief Implementation of shared library unload.
82 * Implementation is operating system dependent.
83 */
84 void Unload();
85
86#if defined(_WIN32)
87 //! \brief Windows library handle
88 HMODULE lib_handle_{nullptr};
89#else
90 // \brief Linux library handle
91 void* lib_handle_{nullptr};
92#endif
93};
94
95DSOLibrary::~DSOLibrary() {
96 if (lib_handle_) Unload();
97}
98
99void DSOLibrary::Init(const std::string& name) { Load(name); }
100
101void* DSOLibrary::GetSymbol(const char* name) { return GetSymbol_(name); }
102
103#if defined(_WIN32)
104
105void* DSOLibrary::GetSymbol_(const char* name) {
106 return reinterpret_cast<void*>(GetProcAddress(lib_handle_, (LPCSTR)name)); // NOLINT(*)
107}
108
109void DSOLibrary::Load(const std::string& name) {
110 // use wstring version that is needed by LLVM.
111 std::wstring wname(name.begin(), name.end());
112 lib_handle_ = LoadLibraryW(wname.c_str());
113 ICHECK(lib_handle_ != nullptr) << "Failed to load dynamic shared library " << name;
114}
115
116void DSOLibrary::Unload() {
117 FreeLibrary(lib_handle_);
118 lib_handle_ = nullptr;
119}
120
121#else
122
123void DSOLibrary::Load(const std::string& name) {
124 lib_handle_ = dlopen(name.c_str(), RTLD_LAZY | RTLD_LOCAL);
125 ICHECK(lib_handle_ != nullptr) << "Failed to load dynamic shared library " << name << " "
126 << dlerror();
127#if defined(__hexagon__)
128 int p;
129 int rc = dlinfo(lib_handle_, RTLD_DI_LOAD_ADDR, &p);
130 if (rc)
131 FARF(ERROR, "error getting model .so start address : %u", rc);
132 else
133 FARF(ALWAYS, "Model .so Start Address : %x", p);
134#endif
135}
136
137void* DSOLibrary::GetSymbol_(const char* name) { return dlsym(lib_handle_, name); }
138
139void DSOLibrary::Unload() {
140 dlclose(lib_handle_);
141 lib_handle_ = nullptr;
142}
143
144#endif
145
146ObjectPtr<Library> CreateDSOLibraryObject(std::string library_path) {
147 auto n = make_object<DSOLibrary>();
148 n->Init(library_path);
149 return n;
150}
151} // namespace runtime
152} // namespace tvm
153