diff options
Diffstat (limited to 'runtime/plugin.cc')
| -rw-r--r-- | runtime/plugin.cc | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/runtime/plugin.cc b/runtime/plugin.cc new file mode 100644 index 0000000000..481b1caa15 --- /dev/null +++ b/runtime/plugin.cc @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "plugin.h" + +#include <dlfcn.h> +#include "base/stringprintf.h" +#include "base/logging.h" + +namespace art { + +const char* PLUGIN_INITIALIZATION_FUNCTION_NAME = "ArtPlugin_Initialize"; +const char* PLUGIN_DEINITIALIZATION_FUNCTION_NAME = "ArtPlugin_Deinitialize"; + +Plugin::Plugin(const Plugin& other) : library_(other.library_), dlopen_handle_(nullptr) { + if (other.IsLoaded()) { + std::string err; + Load(&err); + } +} + +bool Plugin::Load(/*out*/std::string* error_msg) { + DCHECK(!IsLoaded()); + void* res = dlopen(library_.c_str(), RTLD_LAZY); + if (res == nullptr) { + *error_msg = StringPrintf("dlopen failed: %s", dlerror()); + return false; + } + // Get the initializer function + PluginInitializationFunction init = reinterpret_cast<PluginInitializationFunction>( + dlsym(res, PLUGIN_INITIALIZATION_FUNCTION_NAME)); + if (init != nullptr) { + if (!init()) { + dlclose(res); + *error_msg = StringPrintf("Initialization of plugin failed"); + return false; + } + } else { + LOG(WARNING) << this << " does not include an initialization function"; + } + dlopen_handle_ = res; + return true; +} + +bool Plugin::Unload() { + DCHECK(IsLoaded()); + bool ret = true; + void* handle = dlopen_handle_; + PluginDeinitializationFunction deinit = reinterpret_cast<PluginDeinitializationFunction>( + dlsym(handle, PLUGIN_DEINITIALIZATION_FUNCTION_NAME)); + if (deinit != nullptr) { + if (!deinit()) { + LOG(WARNING) << this << " failed deinitialization"; + ret = false; + } + } else { + LOG(WARNING) << this << " does not include a deinitialization function"; + } + dlopen_handle_ = nullptr; + if (dlclose(handle) != 0) { + LOG(ERROR) << this << " failed to dlclose: " << dlerror(); + ret = false; + } + return ret; +} + +std::ostream& operator<<(std::ostream &os, const Plugin* m) { + return os << *m; +} + +std::ostream& operator<<(std::ostream &os, Plugin const& m) { + return os << "Plugin { library=\"" << m.library_ << "\", handle=" << m.dlopen_handle_ << " }"; +} + +} // namespace art |