Skip to content

Creating plugins

We offer a template repository on Codeberg that you can use as base. The current ReOxide API involves building native shared libraries from C++11 code and only supports Linux. This will likely change in the future when we add support for different operating systems and languages. For now, the plugin template uses meson as build system and requires C++11. The minimal template should adapt well to other build systems if necessary.

The template makes use of the reoxide command to find the paths of:

  • The C++ headers
  • The necessary dynamic libraries for linking
  • The plugin install directory

The ReOxide pip package provides this command, so you need to complete the setup guide first and install the package globally or into a virtual environment. Then you can set up the meson build from your plugin repository:

sh
$ meson setup build

If you installed the pip package into a virtual environment, make sure to activate it before executing meson commands. You can build and install the plugin with the meson install command:

sh
$ meson install -C build

This uses the build folder created by the setup command, builds the plugin and installs it into the plugin folder. The section on loading plugins shows you how you can find the plugin folder.

Because of the fragile stability of the C++ Application Binary Interface (ABI), building the plugin this way only works safely if you also compiled ReOxide yourself. When using the reoxide pip package or distributing your plugin, you need to use the manylinux2014 container provided by the Python Packaging Authority. If you have Docker installed, you can use the provided Dockerfile to build your plugin:

sh
$ docker build . -o output_dir

You can then find the shared objects for your plugins in the output_dir folder and copy them manually into your ReOxide plugin folder. You can also adjust the Dockerfile to not compile during the image build, but only install the necessary tools. This way you can mount the build folder from outside the container and make builds faster.

Structure of a plugin

A plugin can specify a context, rules, and actions. Rules and actions work the same way as the ones Ghidra uses internally. They can store information necessary for their analysis locally for one function, for example by implementing a key value store with the Funcdata object as key. Compared to that, the plugin context allows storage to persist beyond the lifetime of a rule or action. Unfortunately, as Ghidra might create many decompiler instances for the same program, you cannot expect to store information across functions in a consistent manner. This limits the use cases for storing data in the context to e.g.:

  • Statistics
  • Sharing data across rules/actions, but for one function

You can define a context by deriving from the reoxide::Plugin base class. As the context only stores data, you do not have to add any functions:

cpp
class Plugin : public reoxide::Plugin {
// Add data, additional functions, etc.
};

To finish the minimal plugin definition, you have to register the plugin by using the macros provided by ReOxide. These macros register context, rules, and actions:

cpp
REOXIDE_CONTEXT(Plugin);
REOXIDE_RULES();
REOXIDE_ACTIONS();

As we have not defined any rules or actions yet, we assign empty vectors to the REOXIDE_RULES and REOXIDE_ACTIONS macros. You can either place the macros at the end of the plugin file, or at the beginning by using forward declarations. The template does currently not check for the presence of the macros. Not using the macros might lead to unexpected behavior or crashes when ReOxide loads the plugin as a consequence.