Skip to content

Commit add8a3e

Browse files
phip1611rageagainsthepc
authored andcommitted
plugin-interface: use extern "C" for plugin init function
Currently, smartvmi loads plugins dynamically by loading their shared object. From that shared object, the main entry function is searched. The problem with that is that the current approach depends on the hard-coded C++-mangled symbol name. This however depends on the toolchain (compiler version etc.). Specifically, when compiled on NixOS, the name didn't match the upstream source code version. As this symbol name is only relevant when loading a shared object into memory as part of the shared object's metadata analysis, this name doesn't have to be unique across plugins. Therefore, to get rid of the hardcoded symbol name, we use "extern C" to make things easier and more portable. The function was renamed from "init" to "vmicore_plugin_init" to have a more expressive name. The disadvantage is that the caller can no longer implicitly verify the function signature used when the plugin was compiled. However, with a few more assertions, we can mitigate this mostly.
1 parent 1f25821 commit add8a3e

File tree

6 files changed

+21
-19
lines changed

6 files changed

+21
-19
lines changed

plugins/apitracing/src/lib/ApiTracing.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ namespace ApiTracing
9999
}
100100
}
101101

102-
std::unique_ptr<IPlugin>
103-
VmiCore::Plugin::init(PluginInterface* pluginInterface,
104-
std::shared_ptr<IPluginConfig> config, // NOLINT(performance-unnecessary-value-param)
105-
std::vector<std::string> args)
102+
extern "C" std::unique_ptr<IPlugin> VmiCore::Plugin::vmicore_plugin_init(
103+
PluginInterface* pluginInterface,
104+
std::shared_ptr<IPluginConfig> config, // NOLINT(performance-unnecessary-value-param)
105+
std::vector<std::string> args)
106106
{
107107
return std::make_unique<ApiTracing::ApiTracing>(pluginInterface, *config, args);
108108
}

plugins/inmemoryscanner/src/lib/InMemory.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ namespace InMemoryScanner
6666
}
6767
}
6868

69-
std::unique_ptr<IPlugin>
70-
VmiCore::Plugin::init(PluginInterface* pluginInterface,
71-
std::shared_ptr<IPluginConfig> config, // NOLINT(performance-unnecessary-value-param)
72-
std::vector<std::string> args)
69+
extern "C" std::unique_ptr<IPlugin> VmiCore::Plugin::vmicore_plugin_init(
70+
PluginInterface* pluginInterface,
71+
std::shared_ptr<IPluginConfig> config, // NOLINT(performance-unnecessary-value-param)
72+
std::vector<std::string> args)
7373
{
7474
return std::make_unique<InMemoryScanner::InMemory>(pluginInterface, *config, args);
7575
}

plugins/template/src/lib/Template.cpp

100755100644
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ namespace Template
5151
}
5252
}
5353

54-
// This is the init function. It is called by VmiCore and is responsible for creating an instance of a plugin.
54+
// This is the init function. It is linked and called dynamically at runtime by
55+
// VmiCore and is responsible for creating an instance of a plugin.
5556
// All plugins have to inherit from IPlugin.
56-
std::unique_ptr<IPlugin>
57-
VmiCore::Plugin::init(PluginInterface* pluginInterface,
58-
std::shared_ptr<IPluginConfig> config, // NOLINT(performance-unnecessary-value-param)
59-
std::vector<std::string> args)
57+
extern "C" std::unique_ptr<IPlugin> VmiCore::Plugin::vmicore_plugin_init(
58+
PluginInterface* pluginInterface,
59+
std::shared_ptr<IPluginConfig> config, // NOLINT(performance-unnecessary-value-param)
60+
std::vector<std::string> args)
6061
{
6162
return std::make_unique<Template::Template>(pluginInterface, *config, args);
6263
}

vmicore/src/include/vmicore/plugins/IPlugin.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ namespace VmiCore::Plugin
4444
* @param args Commandline arguments passed to this specific plugin. Elements are whitespace separated.
4545
* @return An instance of the plugin. Has to implement the IPlugin interface. Lifetime will be managed by VMICore.
4646
*/
47-
extern std::unique_ptr<IPlugin>
48-
init(PluginInterface* pluginInterface, std::shared_ptr<IPluginConfig> config, std::vector<std::string> args);
47+
extern "C" std::unique_ptr<IPlugin> vmicore_plugin_init(PluginInterface* pluginInterface,
48+
std::shared_ptr<IPluginConfig> config,
49+
std::vector<std::string> args);
4950
}
5051

5152
#endif // APITRACING_IPLUGIN_H

vmicore/src/lib/plugins/PluginSystem.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,8 @@ namespace VmiCore
161161
Plugin::PluginInterface::API_VERSION));
162162
}
163163

164-
auto pluginInitFunction = std::bit_cast<decltype(Plugin::init)*>(
165-
dlsym(libraryHandle,
166-
"_ZN7VmiCore6Plugin4initEPNS0_15PluginInterfaceENSt3__110shared_ptrINS0_13IPluginConfigEEENS3_"
167-
"6vectorINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEENSB_ISD_EEEE"));
164+
auto pluginInitFunction =
165+
std::bit_cast<decltype(Plugin::vmicore_plugin_init)*>(dlsym(libraryHandle, PLUGIN_INIT_FUNCTION.data()));
168166
dlErrorMessage = dlerror();
169167
if (dlErrorMessage != nullptr)
170168
{

vmicore/src/lib/plugins/PluginSystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
namespace VmiCore
1919
{
20+
constexpr std::string_view PLUGIN_INIT_FUNCTION = "vmicore_plugin_init";
21+
2022
class IPluginSystem : public Plugin::PluginInterface
2123
{
2224
public:

0 commit comments

Comments
 (0)