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 #ifndef ART_RUNTIME_TI_AGENT_H_
18 #define ART_RUNTIME_TI_AGENT_H_
19 
20 #include <dlfcn.h>
21 #include <jni.h>  // for jint, JavaVM* etc declarations
22 
23 #include <memory>
24 
25 #include <android-base/logging.h>
26 #include <android-base/macros.h>
27 
28 namespace art {
29 namespace ti {
30 
31 class Agent;
32 
33 enum LoadError {
34   kNoError,              // No error occurred..
35   kLoadingError,         // dlopen or dlsym returned an error.
36   kInitializationError,  // The entrypoint did not return 0. This might require an abort.
37 };
38 
39 class AgentSpec {
40  public:
41   explicit AgentSpec(const std::string& arg);
42 
GetName()43   const std::string& GetName() const {
44     return name_;
45   }
46 
GetArgs()47   const std::string& GetArgs() const {
48     return args_;
49   }
50 
HasArgs()51   bool HasArgs() const {
52     return !GetArgs().empty();
53   }
54 
55   std::unique_ptr<Agent> Load(/*out*/jint* call_res,
56                               /*out*/LoadError* error,
57                               /*out*/std::string* error_msg);
58 
59   // Tries to attach the agent using its OnAttach method. Returns true on success.
60   std::unique_ptr<Agent> Attach(JNIEnv* env,
61                                 jobject class_loader,
62                                 /*out*/jint* call_res,
63                                 /*out*/LoadError* error,
64                                 /*out*/std::string* error_msg);
65 
66  private:
67   std::unique_ptr<Agent> DoDlOpen(JNIEnv* env,
68                                   jobject class_loader,
69                                   /*out*/LoadError* error,
70                                   /*out*/std::string* error_msg);
71 
72   std::unique_ptr<Agent> DoLoadHelper(JNIEnv* env,
73                                       bool attaching,
74                                       jobject class_loader,
75                                       /*out*/jint* call_res,
76                                       /*out*/LoadError* error,
77                                       /*out*/std::string* error_msg);
78 
79   std::string name_;
80   std::string args_;
81 
82   friend std::ostream& operator<<(std::ostream &os, AgentSpec const& m);
83 };
84 
85 std::ostream& operator<<(std::ostream &os, AgentSpec const& m);
86 
87 using AgentOnLoadFunction = jint (*)(JavaVM*, const char*, void*);
88 using AgentOnUnloadFunction = void (*)(JavaVM*);
89 
90 // Agents are native libraries that will be loaded by the runtime for the purpose of
91 // instrumentation. They will be entered by Agent_OnLoad or Agent_OnAttach depending on whether the
92 // agent is being attached during runtime startup or later.
93 //
94 // The agent's Agent_OnUnload function will be called during runtime shutdown.
95 //
96 // TODO: consider splitting ti::Agent into command line, agent and shared library handler classes
97 // TODO Support native-bridge. Currently agents can only be the actual runtime ISA of the device.
98 class Agent {
99  public:
GetName()100   const std::string& GetName() const {
101     return name_;
102   }
103 
104   void* FindSymbol(const std::string& name) const;
105 
106   // TODO We need to acquire some locks probably.
107   void Unload();
108 
109   Agent(Agent&& other) noexcept;
110   Agent& operator=(Agent&& other) noexcept;
111 
112   ~Agent();
113 
114  private:
Agent(const std::string & name,void * dlopen_handle)115   Agent(const std::string& name, void* dlopen_handle) : name_(name),
116                                                         dlopen_handle_(dlopen_handle),
117                                                         onload_(nullptr),
118                                                         onattach_(nullptr),
119                                                         onunload_(nullptr) {
120     DCHECK(dlopen_handle != nullptr);
121   }
122 
123   void PopulateFunctions();
124 
125   std::string name_;
126   void* dlopen_handle_;
127 
128   // The entrypoints.
129   AgentOnLoadFunction onload_;
130   AgentOnLoadFunction onattach_;
131   AgentOnUnloadFunction onunload_;
132 
133   friend class AgentSpec;
134   friend std::ostream& operator<<(std::ostream &os, Agent const& m);
135 
136   DISALLOW_COPY_AND_ASSIGN(Agent);
137 };
138 
139 std::ostream& operator<<(std::ostream &os, Agent const& m);
140 std::ostream& operator<<(std::ostream &os, const Agent* m);
141 
142 }  // namespace ti
143 }  // namespace art
144 
145 #endif  // ART_RUNTIME_TI_AGENT_H_
146 
147