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