OSDN Git Service

Merge "Improved induction variable analysis and loop optimizations."
[android-x86/art.git] / runtime / ti / agent.cc
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "agent.h"
18 #include "java_vm_ext.h"
19 #include "runtime.h"
20
21 namespace art {
22 namespace ti {
23
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";
27
28 // TODO We need to acquire some locks probably.
29 Agent::LoadError Agent::DoLoadHelper(bool attaching,
30                                      /*out*/jint* call_res,
31                                      /*out*/std::string* error_msg) {
32   DCHECK(call_res != nullptr);
33   DCHECK(error_msg != nullptr);
34
35   if (IsStarted()) {
36     *error_msg = StringPrintf("the agent at %s has already been started!", name_.c_str());
37     VLOG(agents) << "err: " << *error_msg;
38     return kAlreadyStarted;
39   }
40   LoadError err = DoDlOpen(error_msg);
41   if (err != kNoError) {
42     VLOG(agents) << "err: " << *error_msg;
43     return err;
44   }
45   AgentOnLoadFunction callback = attaching ? onattach_ : onload_;
46   if (callback == nullptr) {
47     *error_msg = StringPrintf("Unable to start agent %s: No %s callback found",
48                               (attaching ? "attach" : "load"),
49                               name_.c_str());
50     VLOG(agents) << "err: " << *error_msg;
51     return kLoadingError;
52   }
53   // Need to let the function fiddle with the array.
54   std::unique_ptr<char[]> copied_args(new char[args_.size() + 1]);
55   strcpy(copied_args.get(), args_.c_str());
56   // TODO Need to do some checks that we are at a good spot etc.
57   *call_res = callback(Runtime::Current()->GetJavaVM(),
58                        copied_args.get(),
59                        nullptr);
60   if (*call_res != 0) {
61     *error_msg = StringPrintf("Initialization of %s returned non-zero value of %d",
62                               name_.c_str(), *call_res);
63     VLOG(agents) << "err: " << *error_msg;
64     return kInitializationError;
65   } else {
66     return kNoError;
67   }
68 }
69
70 Agent::LoadError Agent::DoDlOpen(/*out*/std::string* error_msg) {
71   DCHECK(error_msg != nullptr);
72
73   DCHECK(dlopen_handle_ == nullptr);
74   DCHECK(onload_ == nullptr);
75   DCHECK(onattach_ == nullptr);
76   DCHECK(onunload_ == nullptr);
77
78   dlopen_handle_ = dlopen(name_.c_str(), RTLD_LAZY);
79   if (dlopen_handle_ == nullptr) {
80     *error_msg = StringPrintf("Unable to dlopen %s: %s", name_.c_str(), dlerror());
81     return kLoadingError;
82   }
83
84   onload_ = reinterpret_cast<AgentOnLoadFunction>(dlsym(dlopen_handle_,
85                                                         AGENT_ON_LOAD_FUNCTION_NAME));
86   if (onload_ == nullptr) {
87     VLOG(agents) << "Unable to find 'Agent_OnLoad' symbol in " << this;
88   }
89   onattach_ = reinterpret_cast<AgentOnLoadFunction>(dlsym(dlopen_handle_,
90                                                             AGENT_ON_ATTACH_FUNCTION_NAME));
91   if (onattach_ == nullptr) {
92     VLOG(agents) << "Unable to find 'Agent_OnAttach' symbol in " << this;
93   }
94   onunload_= reinterpret_cast<AgentOnUnloadFunction>(dlsym(dlopen_handle_,
95                                                            AGENT_ON_UNLOAD_FUNCTION_NAME));
96   if (onunload_ == nullptr) {
97     VLOG(agents) << "Unable to find 'Agent_OnUnload' symbol in " << this;
98   }
99   return kNoError;
100 }
101
102 // TODO Lock some stuff probably.
103 void Agent::Unload() {
104   if (dlopen_handle_ != nullptr) {
105     if (onunload_ != nullptr) {
106       onunload_(Runtime::Current()->GetJavaVM());
107     }
108     dlclose(dlopen_handle_);
109     dlopen_handle_ = nullptr;
110     onload_ = nullptr;
111     onattach_ = nullptr;
112     onunload_ = nullptr;
113   } else {
114     VLOG(agents) << this << " is not currently loaded!";
115   }
116 }
117
118 Agent::Agent(std::string arg)
119     : dlopen_handle_(nullptr),
120       onload_(nullptr),
121       onattach_(nullptr),
122       onunload_(nullptr) {
123   size_t eq = arg.find_first_of('=');
124   if (eq == std::string::npos) {
125     name_ = arg;
126   } else {
127     name_ = arg.substr(0, eq);
128     args_ = arg.substr(eq + 1, arg.length());
129   }
130 }
131
132 Agent::Agent(const Agent& other)
133     : dlopen_handle_(nullptr),
134       onload_(nullptr),
135       onattach_(nullptr),
136       onunload_(nullptr) {
137   *this = other;
138 }
139
140 // Attempting to copy to/from loaded/started agents is a fatal error
141 Agent& Agent::operator=(const Agent& other) {
142   if (this != &other) {
143     if (other.dlopen_handle_ != nullptr) {
144       LOG(FATAL) << "Attempting to copy a loaded agent!";
145     }
146
147     if (dlopen_handle_ != nullptr) {
148       LOG(FATAL) << "Attempting to assign into a loaded agent!";
149     }
150
151     DCHECK(other.onload_ == nullptr);
152     DCHECK(other.onattach_ == nullptr);
153     DCHECK(other.onunload_ == nullptr);
154
155     DCHECK(onload_ == nullptr);
156     DCHECK(onattach_ == nullptr);
157     DCHECK(onunload_ == nullptr);
158
159     name_ = other.name_;
160     args_ = other.args_;
161
162     dlopen_handle_ = nullptr;
163     onload_ = nullptr;
164     onattach_ = nullptr;
165     onunload_ = nullptr;
166   }
167   return *this;
168 }
169
170 Agent::Agent(Agent&& other)
171     : dlopen_handle_(nullptr),
172       onload_(nullptr),
173       onattach_(nullptr),
174       onunload_(nullptr) {
175   *this = std::move(other);
176 }
177
178 Agent& Agent::operator=(Agent&& other) {
179   if (this != &other) {
180     if (dlopen_handle_ != nullptr) {
181       dlclose(dlopen_handle_);
182     }
183     name_ = std::move(other.name_);
184     args_ = std::move(other.args_);
185     dlopen_handle_ = other.dlopen_handle_;
186     onload_ = other.onload_;
187     onattach_ = other.onattach_;
188     onunload_ = other.onunload_;
189     other.dlopen_handle_ = nullptr;
190     other.onload_ = nullptr;
191     other.onattach_ = nullptr;
192     other.onunload_ = nullptr;
193   }
194   return *this;
195 }
196
197 Agent::~Agent() {
198   if (dlopen_handle_ != nullptr) {
199     dlclose(dlopen_handle_);
200   }
201 }
202
203 std::ostream& operator<<(std::ostream &os, const Agent* m) {
204   return os << *m;
205 }
206
207 std::ostream& operator<<(std::ostream &os, Agent const& m) {
208   return os << "Agent { name=\"" << m.name_ << "\", args=\"" << m.args_ << "\", handle="
209             << m.dlopen_handle_ << " }";
210 }
211
212 }  // namespace ti
213 }  // namespace art