1185d134a3b43ab7529053e965917e0fa74bceba4Alex Light/*
2185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * Copyright (C) 2016 The Android Open Source Project
3185d134a3b43ab7529053e965917e0fa74bceba4Alex Light *
4185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * Licensed under the Apache License, Version 2.0 (the "License");
5185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * you may not use this file except in compliance with the License.
6185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * You may obtain a copy of the License at
7185d134a3b43ab7529053e965917e0fa74bceba4Alex Light *
8185d134a3b43ab7529053e965917e0fa74bceba4Alex Light *      http://www.apache.org/licenses/LICENSE-2.0
9185d134a3b43ab7529053e965917e0fa74bceba4Alex Light *
10185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * Unless required by applicable law or agreed to in writing, software
11185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * distributed under the License is distributed on an "AS IS" BASIS,
12185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * See the License for the specific language governing permissions and
14185d134a3b43ab7529053e965917e0fa74bceba4Alex Light * limitations under the License.
15185d134a3b43ab7529053e965917e0fa74bceba4Alex Light */
16185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
17185d134a3b43ab7529053e965917e0fa74bceba4Alex Light#include "plugin.h"
18185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
19185d134a3b43ab7529053e965917e0fa74bceba4Alex Light#include <dlfcn.h>
2046ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
2146ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
2246ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
23185d134a3b43ab7529053e965917e0fa74bceba4Alex Light#include "base/logging.h"
24185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
25185d134a3b43ab7529053e965917e0fa74bceba4Alex Lightnamespace art {
26185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
2746ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
2846ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
29185d134a3b43ab7529053e965917e0fa74bceba4Alex Lightconst char* PLUGIN_INITIALIZATION_FUNCTION_NAME = "ArtPlugin_Initialize";
30185d134a3b43ab7529053e965917e0fa74bceba4Alex Lightconst char* PLUGIN_DEINITIALIZATION_FUNCTION_NAME = "ArtPlugin_Deinitialize";
31185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
32185d134a3b43ab7529053e965917e0fa74bceba4Alex LightPlugin::Plugin(const Plugin& other) : library_(other.library_), dlopen_handle_(nullptr) {
33185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  if (other.IsLoaded()) {
34185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    std::string err;
35185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    Load(&err);
36185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  }
37185d134a3b43ab7529053e965917e0fa74bceba4Alex Light}
38185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
39185d134a3b43ab7529053e965917e0fa74bceba4Alex Lightbool Plugin::Load(/*out*/std::string* error_msg) {
40185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  DCHECK(!IsLoaded());
41185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  void* res = dlopen(library_.c_str(), RTLD_LAZY);
42185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  if (res == nullptr) {
43185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    *error_msg = StringPrintf("dlopen failed: %s", dlerror());
44185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    return false;
45185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  }
46185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  // Get the initializer function
47185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  PluginInitializationFunction init = reinterpret_cast<PluginInitializationFunction>(
48185d134a3b43ab7529053e965917e0fa74bceba4Alex Light      dlsym(res, PLUGIN_INITIALIZATION_FUNCTION_NAME));
49185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  if (init != nullptr) {
50185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    if (!init()) {
51185d134a3b43ab7529053e965917e0fa74bceba4Alex Light      dlclose(res);
52185d134a3b43ab7529053e965917e0fa74bceba4Alex Light      *error_msg = StringPrintf("Initialization of plugin failed");
53185d134a3b43ab7529053e965917e0fa74bceba4Alex Light      return false;
54185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    }
55185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  } else {
56185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    LOG(WARNING) << this << " does not include an initialization function";
57185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  }
58185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  dlopen_handle_ = res;
59185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  return true;
60185d134a3b43ab7529053e965917e0fa74bceba4Alex Light}
61185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
62185d134a3b43ab7529053e965917e0fa74bceba4Alex Lightbool Plugin::Unload() {
63185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  DCHECK(IsLoaded());
64185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  bool ret = true;
65185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  void* handle = dlopen_handle_;
66185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  PluginDeinitializationFunction deinit = reinterpret_cast<PluginDeinitializationFunction>(
67185d134a3b43ab7529053e965917e0fa74bceba4Alex Light      dlsym(handle, PLUGIN_DEINITIALIZATION_FUNCTION_NAME));
68185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  if (deinit != nullptr) {
69185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    if (!deinit()) {
70185d134a3b43ab7529053e965917e0fa74bceba4Alex Light      LOG(WARNING) << this << " failed deinitialization";
71185d134a3b43ab7529053e965917e0fa74bceba4Alex Light      ret = false;
72185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    }
73185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  } else {
74185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    LOG(WARNING) << this << " does not include a deinitialization function";
75185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  }
76185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  dlopen_handle_ = nullptr;
77185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  if (dlclose(handle) != 0) {
78185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    LOG(ERROR) << this << " failed to dlclose: " << dlerror();
79185d134a3b43ab7529053e965917e0fa74bceba4Alex Light    ret = false;
80185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  }
81185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  return ret;
82185d134a3b43ab7529053e965917e0fa74bceba4Alex Light}
83185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
84185d134a3b43ab7529053e965917e0fa74bceba4Alex Lightstd::ostream& operator<<(std::ostream &os, const Plugin* m) {
85185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  return os << *m;
86185d134a3b43ab7529053e965917e0fa74bceba4Alex Light}
87185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
88185d134a3b43ab7529053e965917e0fa74bceba4Alex Lightstd::ostream& operator<<(std::ostream &os, Plugin const& m) {
89185d134a3b43ab7529053e965917e0fa74bceba4Alex Light  return os << "Plugin { library=\"" << m.library_ << "\", handle=" << m.dlopen_handle_ << " }";
90185d134a3b43ab7529053e965917e0fa74bceba4Alex Light}
91185d134a3b43ab7529053e965917e0fa74bceba4Alex Light
92185d134a3b43ab7529053e965917e0fa74bceba4Alex Light}  // namespace art
93