24 #include <plugin/loader.h> 26 #include <utils/system/dynamic_module/module_manager.h> 27 #include <utils/system/dynamic_module/module.h> 46 class PluginLoader::Data
50 std::map< Plugin *, Module * > plugin_module_map;
51 std::map< std::string, Plugin * > name_plugin_map;
52 std::map< Plugin *, std::string > plugin_name_map;
67 append(
"Plugin '%s' could not be loaded: %s", plugin, message);
85 append(
"Plugin '%s' could not be loaded: %s", plugin, message);
111 append(
"Plugin '%s' could not be unloaded", plugin_name);
131 plugin_base_dir_ = plugin_base_dir;
158 PluginLoader::open_module(
const char *plugin_name)
160 std::string module_name = std::string(plugin_name) +
"." + d_->mm->get_module_file_extension();
163 return d_->mm->open_module(module_name.c_str());
171 PluginLoader::create_instance(
const char *plugin_name,
Module *module)
173 if ( ! module->
has_symbol(
"plugin_factory") ) {
174 throw PluginLoadException(plugin_name,
"Symbol 'plugin_factory' not found. Forgot EXPORT_PLUGIN?");
176 if ( ! module->
has_symbol(
"plugin_description") ) {
177 throw PluginLoadException(plugin_name,
"Symbol 'plugin_description' not found. Forgot PLUGIN_DESCRIPTION?");
180 PluginFactoryFunc pff = (PluginFactoryFunc)module->
get_symbol(
"plugin_factory");
213 std::string pn = plugin_name;
215 if ( d_->name_plugin_map.find(pn) != d_->name_plugin_map.end() ) {
216 return d_->name_plugin_map[pn];
220 Module *module = open_module(plugin_name);
221 Plugin *p = create_instance(plugin_name, module);
223 d_->plugin_module_map[p] = module;
224 d_->name_plugin_map[pn] = p;
225 d_->plugin_name_map[p] = pn;
242 PluginLoader::get_string_symbol(
const char *plugin_name,
243 const char *symbol_name,
const char *section_name)
246 GElf_Ehdr elf_header;
249 std::string module_name =
250 plugin_base_dir_ +
"/" + plugin_name +
"." + d_->mm->get_module_file_extension();
252 if(elf_version(EV_CURRENT) == EV_NONE) {
253 throw Exception(
"libelf library ELF version too old");
256 int fd = open(module_name.c_str(), O_RDONLY);
258 throw Exception(
"Failed to open file of plugin '%s'", plugin_name);
261 elf = elf_begin(fd, ELF_C_READ, NULL);
263 throw Exception(
"Cannot read elf file: %s", elf_errmsg(elf_errno()));
266 if (gelf_getehdr(elf, &elf_header) == NULL) {
268 throw Exception(
"Failed to read ELF header of plugin %s: %s",
269 plugin_name, elf_errmsg(elf_errno()));
273 while((scn = elf_nextscn(elf, scn)) != 0) {
275 gelf_getshdr(scn, &shdr);
277 if(shdr.sh_type == SHT_SYMTAB) {
278 Elf_Data *edata = elf_getdata(scn, NULL);
279 size_t symbol_count = shdr.sh_size / shdr.sh_entsize;
281 for(
size_t i = 0; i < symbol_count; ++i) {
283 gelf_getsym(edata, i, &sym);
286 Elf_Scn *sym_scn = elf_getscn(elf, sym.st_shndx);
287 gelf_getshdr(sym_scn, &sym_shdr);
289 char *secname = elf_strptr(elf, elf_header.e_shstrndx, sym_shdr.sh_name);
290 char *symname = elf_strptr(elf, shdr.sh_link, sym.st_name);
292 if ((strcmp(secname, section_name) == 0) &&
293 (strcmp(symname, symbol_name) == 0))
296 Elf_Data *sym_data = elf_rawdata(sym_scn, NULL);
298 (
const char *)sym_data->d_buf + (sym.st_value - sym_shdr.sh_offset);
299 const char *
const limit = start + sym.st_size;
300 const char *
end = (
const char *)memchr(start,
'\0', limit - start);
304 std::string rv(start);
310 throw Exception(
"Failed to retrieve string for symbol '%s' in section '%s'" 311 " of plugin '%s'", symbol_name, section_name, plugin_name);
319 throw Exception(
"Description for plugin %s not found. " 320 "Forgot PLUGIN_DESCRIPTION?", plugin_name);
322 throw Exception(
"libelf not supported at compile time");
336 return get_string_symbol(plugin_name,
"_plugin_description");
338 Module *module = open_module(plugin_name);
340 if ( ! module->
has_symbol(
"plugin_description") ) {
341 throw PluginLoadException(plugin_name,
"Symbol 'plugin_description' not found. Forgot PLUGIN_DESCRIPTION?");
345 std::string rv = pdf();
346 d_->mm->close_module(module);
360 return ( d_->name_plugin_map.find(plugin_name) != d_->name_plugin_map.end() );
378 if ( d_->plugin_module_map.find(plugin) != d_->plugin_module_map.end() ) {
380 PluginDestroyFunc pdf = (PluginDestroyFunc)d_->plugin_module_map[plugin]->get_symbol(
"plugin_destroy");
384 d_->mm->close_module(d_->plugin_module_map[plugin]);
385 d_->plugin_module_map.erase(plugin);
387 d_->name_plugin_map.erase(d_->plugin_name_map[plugin]);
388 d_->plugin_name_map.erase(plugin);
PluginLoader(const char *plugin_base_dir, Configuration *config)
Constructor.
PluginUnloadException(const char *plugin_type, const char *add_msg=NULL)
Constructor.
void set_name(const char *name)
Set plugin name.
Fawkes library namespace.
Exception()
Constructor for subclasses.
This exception is thrown if the requested plugin could not be loaded.
~PluginLoadException()
Destructor.
PluginLoadException(const char *plugin, const char *message)
Constructor.
void unload(Plugin *plugin)
Unload the given plugin This will unload the given plugin.
iterator end()
Get end iterator for messages.
Dynamic module loader for Linux, FreeBSD, and MacOS X.
Base class for exceptions in Fawkes.
std::string get_description(const char *plugin_name)
Get plugin description.
const char *(* PluginDescriptionFunc)()
Plugin description function for the shared library.
std::string plugin_name() const
Get name of plugin which failed to load.
virtual void * get_symbol(const char *symbol_name)
Get a symbol from the module.
void copy_messages(const Exception &exc)
Copy messages from given exception.
ModuleManager * get_module_manager() const
Get module manager.
bool is_loaded(const char *plugin_name)
Check if a plugin is loaded.
~PluginLoader()
Destructor.
Interface for configuration handling.
void append(const char *format,...)
Append messages to the message list.
virtual bool has_symbol(const char *symbol_name)
Check if the module has the given symbol.
Plugin * load(const char *plugin_name)
Load a specific plugin The plugin loader is clever and guarantees that every plugin is only loaded on...