• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/logging.h"
24 
25 namespace art {
26 namespace ti {
27 
28 using AgentOnLoadFunction = jint (*)(JavaVM*, const char*, void*);
29 using AgentOnUnloadFunction = void (*)(JavaVM*);
30 
31 // Agents are native libraries that will be loaded by the runtime for the purpose of
32 // instrumentation. They will be entered by Agent_OnLoad or Agent_OnAttach depending on whether the
33 // agent is being attached during runtime startup or later.
34 //
35 // The agent's Agent_OnUnload function will be called during runtime shutdown.
36 //
37 // TODO: consider splitting ti::Agent into command line, agent and shared library handler classes
38 // TODO Support native-bridge. Currently agents can only be the actual runtime ISA of the device.
39 class Agent {
40  public:
41   enum LoadError {
42     kNoError,              // No error occurred..
43     kAlreadyStarted,       // The agent has already been loaded.
44     kLoadingError,         // dlopen or dlsym returned an error.
45     kInitializationError,  // The entrypoint did not return 0. This might require an abort.
46   };
47 
IsStarted()48   bool IsStarted() const {
49     return dlopen_handle_ != nullptr;
50   }
51 
GetName()52   const std::string& GetName() const {
53     return name_;
54   }
55 
GetArgs()56   const std::string& GetArgs() const {
57     return args_;
58   }
59 
HasArgs()60   bool HasArgs() const {
61     return !GetArgs().empty();
62   }
63 
64   void* FindSymbol(const std::string& name) const;
65 
Load(jint * call_res,std::string * error_msg)66   LoadError Load(/*out*/jint* call_res, /*out*/std::string* error_msg) {
67     VLOG(agents) << "Loading agent: " << name_ << " " << args_;
68     return DoLoadHelper(false, call_res, error_msg);
69   }
70 
71   // TODO We need to acquire some locks probably.
72   void Unload();
73 
74   // Tries to attach the agent using its OnAttach method. Returns true on success.
Attach(jint * call_res,std::string * error_msg)75   LoadError Attach(/*out*/jint* call_res, /*out*/std::string* error_msg) {
76     VLOG(agents) << "Attaching agent: " << name_ << " " << args_;
77     return DoLoadHelper(true, call_res, error_msg);
78   }
79 
80   explicit Agent(std::string arg);
81 
82   Agent(const Agent& other);
83   Agent& operator=(const Agent& other);
84 
85   Agent(Agent&& other);
86   Agent& operator=(Agent&& other);
87 
88   ~Agent();
89 
90  private:
91   LoadError DoDlOpen(/*out*/std::string* error_msg);
92 
93   LoadError DoLoadHelper(bool attaching,
94                          /*out*/jint* call_res,
95                          /*out*/std::string* error_msg);
96 
97   std::string name_;
98   std::string args_;
99   void* dlopen_handle_;
100 
101   // The entrypoints.
102   AgentOnLoadFunction onload_;
103   AgentOnLoadFunction onattach_;
104   AgentOnUnloadFunction onunload_;
105 
106   friend std::ostream& operator<<(std::ostream &os, Agent const& m);
107 };
108 
109 std::ostream& operator<<(std::ostream &os, Agent const& m);
110 std::ostream& operator<<(std::ostream &os, const Agent* m);
111 
112 }  // namespace ti
113 }  // namespace art
114 
115 #endif  // ART_RUNTIME_TI_AGENT_H_
116 
117