OSDN Git Service

ART: Dump referenced type in IRT overflows am: 280f32b095
[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 Agent Agent::Create(std::string arg) {
29   size_t eq = arg.find_first_of('=');
30   if (eq == std::string::npos) {
31     return Agent(arg, "");
32   } else {
33     return Agent(arg.substr(0, eq), arg.substr(eq + 1, arg.length()));
34   }
35 }
36
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);
41
42   if (IsStarted()) {
43     *error_msg = StringPrintf("the agent at %s has already been started!", name_.c_str());
44     VLOG(agents) << "err: " << *error_msg;
45     return kAlreadyStarted;
46   }
47   LoadError err = DoDlOpen(error_msg);
48   if (err != kNoError) {
49     VLOG(agents) << "err: " << *error_msg;
50     return err;
51   }
52   if (onload_ == nullptr) {
53     *error_msg = StringPrintf("Unable to start agent %s: No Agent_OnLoad function found",
54                               name_.c_str());
55     VLOG(agents) << "err: " << *error_msg;
56     return kLoadingError;
57   }
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()),
63                       copied_args.get(),
64                       nullptr);
65   if (*call_res != 0) {
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;
70   } else {
71     return kNoError;
72   }
73 }
74
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());
80     return kLoadingError;
81   }
82
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;
87   }
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;
92   }
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;
97   }
98   return kNoError;
99 }
100
101 // TODO Lock some stuff probably.
102 void Agent::Unload() {
103   if (dlopen_handle_ != nullptr) {
104     if (onunload_ != nullptr) {
105       onunload_(Runtime::Current()->GetJavaVM());
106     }
107     dlclose(dlopen_handle_);
108     dlopen_handle_ = nullptr;
109   } else {
110     VLOG(agents) << this << " is not currently loaded!";
111   }
112 }
113
114 Agent::Agent(const Agent& other)
115   : name_(other.name_),
116     args_(other.args_),
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);
123   }
124 }
125
126 Agent::~Agent() {
127   if (dlopen_handle_ != nullptr) {
128     dlclose(dlopen_handle_);
129   }
130 }
131
132 std::ostream& operator<<(std::ostream &os, const Agent* m) {
133   return os << *m;
134 }
135
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_ << " }";
139 }
140
141 }  // namespace ti
142 }  // namespace art