2 * Copyright (C) 2016 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "java_vm_ext.h"
24 const char* AGENT_ON_LOAD_FUNCTION_NAME = "Agent_OnLoad";
25 const char* AGENT_ON_ATTACH_FUNCTION_NAME = "Agent_OnAttach";
26 const char* AGENT_ON_UNLOAD_FUNCTION_NAME = "Agent_OnUnload";
28 Agent Agent::Create(std::string arg) {
29 size_t eq = arg.find_first_of('=');
30 if (eq == std::string::npos) {
31 return Agent(arg, "");
33 return Agent(arg.substr(0, eq), arg.substr(eq + 1, arg.length()));
37 // TODO We need to acquire some locks probably.
38 Agent::LoadError Agent::Load(/*out*/jint* call_res, /*out*/ std::string* error_msg) {
39 DCHECK(call_res != nullptr);
40 DCHECK(error_msg != nullptr);
43 *error_msg = StringPrintf("the agent at %s has already been started!", name_.c_str());
44 VLOG(agents) << "err: " << *error_msg;
45 return kAlreadyStarted;
47 LoadError err = DoDlOpen(error_msg);
48 if (err != kNoError) {
49 VLOG(agents) << "err: " << *error_msg;
52 if (onload_ == nullptr) {
53 *error_msg = StringPrintf("Unable to start agent %s: No Agent_OnLoad function found",
55 VLOG(agents) << "err: " << *error_msg;
58 // Need to let the function fiddle with the array.
59 std::unique_ptr<char[]> copied_args(new char[args_.size() + 1]);
60 strcpy(copied_args.get(), args_.c_str());
61 // TODO Need to do some checks that we are at a good spot etc.
62 *call_res = onload_(static_cast<JavaVM*>(Runtime::Current()->GetJavaVM()),
66 *error_msg = StringPrintf("Initialization of %s returned non-zero value of %d",
67 name_.c_str(), *call_res);
68 VLOG(agents) << "err: " << *error_msg;
69 return kInitializationError;
75 Agent::LoadError Agent::DoDlOpen(/*out*/std::string* error_msg) {
76 DCHECK(error_msg != nullptr);
77 dlopen_handle_ = dlopen(name_.c_str(), RTLD_LAZY);
78 if (dlopen_handle_ == nullptr) {
79 *error_msg = StringPrintf("Unable to dlopen %s: %s", name_.c_str(), dlerror());
83 onload_ = reinterpret_cast<AgentOnLoadFunction>(dlsym(dlopen_handle_,
84 AGENT_ON_LOAD_FUNCTION_NAME));
85 if (onload_ == nullptr) {
86 VLOG(agents) << "Unable to find 'Agent_OnLoad' symbol in " << this;
88 onattach_ = reinterpret_cast<AgentOnAttachFunction>(dlsym(dlopen_handle_,
89 AGENT_ON_ATTACH_FUNCTION_NAME));
90 if (onattach_ == nullptr) {
91 VLOG(agents) << "Unable to find 'Agent_OnAttach' symbol in " << this;
93 onunload_= reinterpret_cast<AgentOnUnloadFunction>(dlsym(dlopen_handle_,
94 AGENT_ON_UNLOAD_FUNCTION_NAME));
95 if (onunload_ == nullptr) {
96 VLOG(agents) << "Unable to find 'Agent_OnUnload' symbol in " << this;
101 // TODO Lock some stuff probably.
102 void Agent::Unload() {
103 if (dlopen_handle_ != nullptr) {
104 if (onunload_ != nullptr) {
105 onunload_(Runtime::Current()->GetJavaVM());
107 dlclose(dlopen_handle_);
108 dlopen_handle_ = nullptr;
110 VLOG(agents) << this << " is not currently loaded!";
114 Agent::Agent(const Agent& other)
115 : name_(other.name_),
117 dlopen_handle_(other.dlopen_handle_),
118 onload_(other.onload_),
119 onattach_(other.onattach_),
120 onunload_(other.onunload_) {
121 if (other.dlopen_handle_ != nullptr) {
122 dlopen(other.name_.c_str(), 0);
127 if (dlopen_handle_ != nullptr) {
128 dlclose(dlopen_handle_);
132 std::ostream& operator<<(std::ostream &os, const Agent* m) {
136 std::ostream& operator<<(std::ostream &os, Agent const& m) {
137 return os << "Agent { name=\"" << m.name_ << "\", args=\"" << m.args_ << "\", handle="
138 << m.dlopen_handle_ << " }";