Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin-interface: use extern "C" for plugin init function #150

Merged
merged 1 commit into from
Sep 30, 2024

Conversation

phip1611
Copy link
Contributor

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 "init_plugin" 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.

Copy link
Member

@rageagainsthepc rageagainsthepc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of, thanks for the PR. 👍

I am not really happy with this solution because it makes plugin initialization less foolproof. There is not really a good way of reliably validating all input parameters on the plugin side, nor should this be the responsibility of the plugin. On the vmicore side loading the wrong function will probably lead to undefined behavior or crashes. On the other hand, these are all more or less theoretical issues and it's probably fine to accept these downsides if it is not possible to demangle this function signature on all platforms in a consistent way. I would simply remove all checks you've added and accept the fact that everything will break if we load the wrong library who happens to have a similar export.

vmicore/src/lib/plugins/PluginSystem.h Outdated Show resolved Hide resolved
plugins/apitracing/src/lib/ApiTracing.cpp Outdated Show resolved Hide resolved
vmicore/src/lib/plugins/PluginSystem.cpp Outdated Show resolved Hide resolved
@rageagainsthepc
Copy link
Member

So, you didn't run into any demangling errors with the plugin api version? Should we export this as extern C nonetheless? 🤔

@phip1611
Copy link
Contributor Author

phip1611 commented Sep 23, 2024

I am not really happy with this solution because it makes plugin initialization less foolproof. There is not really a good way of reliably validating all input parameters on the plugin side, nor should this be the responsibility of the plugin.

Fair point. However, we should look at actual realistic use-cases of smartvmi. Correct me if I'm wrong but I don't see real use-cases in the past or the near or even far future, where smartvmi is not consumed as entire tree and built from that.

Although I understand the possible idea that smartvmi is distributed via a package manager and users create plugins on their own, VMI is much too niche for that to be actually used like that. Right? Or am I missing something? :)

So, you didn't run into any demangling errors with the plugin api version? Should we export this as extern C nonetheless? 🤔

Nope, no problems. I'd say leave it as it is for now if it works

@rageagainsthepc
Copy link
Member

Fair point. However, we should look at actual realistic use-cases of smartvmi. Correct me if I'm wrong but I don't see real use-cases in the past or the near or even far future, where smartvmi is not consumed as entire tree and built from that.

The university partners we have worked together with over the past two years mentioned that they might consider letting students write their thesis using this software and for this use case it might be handy to develop a plugin separately. I don't know how likely this is to happen though ;)

Comment on lines 173 to 176
if (plugin == nullptr)
{
throw PluginException(pluginName, "init function returned null");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you forgot to remove this? The init function can never return a nullptr, just an empty unique_ptr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes, thanks

@@ -17,6 +17,8 @@

namespace VmiCore
{
constexpr std::string_view PLUGIN_INIT_FUNCTION = "init_plugin";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a suggestion. No need to add it if you don't want to, but maybe name it something like "vmicore_plugin_init" since we are already at it?

@rageagainsthepc
Copy link
Member

rageagainsthepc commented Sep 26, 2024

Regarding the formatting issues: Most IDEs support formatting with clang-format, so you don't have to do it manually. Alternatively, you can also use the clang-format CLI tool: clang-format --style=file

Copy link
Member

@rageagainsthepc rageagainsthepc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am mostly fine with these changes. Just remove the unnecessary check in initializePlugin and resolve the formatting issues and we should be good to go. 👍

@phip1611
Copy link
Contributor Author

Done. Are we good to go?

@rageagainsthepc
Copy link
Member

Done. Are we good to go?

There are still some formatting issues unfortunately.

@phip1611
Copy link
Contributor Author

phip1611 commented Sep 27, 2024

Weird, I thought I ran exactly the same commands locally and it worked.

Now, hopefully.

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.
@rageagainsthepc rageagainsthepc merged commit add8a3e into GDATASoftwareAG:main Sep 30, 2024
15 checks passed
@phip1611 phip1611 deleted the plugin-interface branch October 1, 2024 06:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants