blob: e3d4d28d86afe0cbd03ad2d4adc32bacea3a5de1 [file] [log] [blame]
jeffhao725a9572012-11-13 18:20:12 -08001/*
2 * Copyright (C) 2011 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 "instrumentation.h"
18
19#include <sys/uio.h>
20
Elliott Hughes76160052012-12-12 16:31:20 -080021#include "base/unix_file/fd_file.h"
jeffhao725a9572012-11-13 18:20:12 -080022#include "class_linker.h"
23#include "debugger.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080024#include "mirror/class-inl.h"
25#include "mirror/dex_cache.h"
26#include "mirror/abstract_method-inl.h"
27#include "mirror/object_array-inl.h"
jeffhao725a9572012-11-13 18:20:12 -080028#if !defined(ART_USE_LLVM_COMPILER)
29#include "oat/runtime/oat_support_entrypoints.h"
30#endif
31#include "object_utils.h"
32#include "os.h"
33#include "scoped_thread_state_change.h"
34#include "thread.h"
35#include "thread_list.h"
36#include "trace.h"
37
38namespace art {
39
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040static bool InstallStubsClassVisitor(mirror::Class* klass, void*)
jeffhao725a9572012-11-13 18:20:12 -080041 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
42 Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
43 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080044 mirror::AbstractMethod* method = klass->GetDirectMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080045 if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
46 instrumentation->SaveAndUpdateCode(method);
47 }
48 }
49
50 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080051 mirror::AbstractMethod* method = klass->GetVirtualMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080052 if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
53 instrumentation->SaveAndUpdateCode(method);
54 }
55 }
56 return true;
57}
58
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080059static bool UninstallStubsClassVisitor(mirror::Class* klass, void*)
jeffhao725a9572012-11-13 18:20:12 -080060 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
61 Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
62 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080063 mirror::AbstractMethod* method = klass->GetDirectMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080064 if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
65 instrumentation->ResetSavedCode(method);
66 }
67 }
68
69 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080070 mirror::AbstractMethod* method = klass->GetVirtualMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080071 if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
72 instrumentation->ResetSavedCode(method);
73 }
74 }
75 return true;
76}
77
Ian Rogers306057f2012-11-26 12:45:53 -080078void InstrumentationInstallStack(Thread* self, void* arg)
79 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
80 struct InstallStackVisitor : public StackVisitor {
81 InstallStackVisitor(Thread* self, uintptr_t instrumentation_exit_pc)
Ian Rogers7a22fa62013-01-23 12:16:16 -080082 : StackVisitor(self, NULL), self_(self),
83 instrumentation_exit_pc_(instrumentation_exit_pc) {}
jeffhao725a9572012-11-13 18:20:12 -080084
Ian Rogers306057f2012-11-26 12:45:53 -080085 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
86 if (GetCurrentQuickFrame() == NULL) {
87 return true; // Ignore shadow frames.
88 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080089 mirror::AbstractMethod* m = GetMethod();
Ian Rogers306057f2012-11-26 12:45:53 -080090 if (m == NULL) {
91 return true; // Ignore upcalls.
92 }
93 if (m->GetDexMethodIndex() == DexFile::kDexNoIndex16) {
94 return true; // Ignore unresolved methods since they will be instrumented after resolution.
95 }
96 uintptr_t pc = GetReturnPc();
97 InstrumentationStackFrame instrumentation_frame(m, pc, GetFrameId());
98 self_->PushBackInstrumentationStackFrame(instrumentation_frame);
99 SetReturnPc(instrumentation_exit_pc_);
100 return true; // Continue.
101 }
102 Thread* const self_;
103 const uintptr_t instrumentation_exit_pc_;
104 };
105 uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
106 InstallStackVisitor visitor(self, instrumentation_exit_pc);
107 visitor.WalkStack(true);
108 Trace* trace = reinterpret_cast<Trace*>(arg);
109 if (trace != NULL) {
110 std::deque<InstrumentationStackFrame>::const_reverse_iterator it =
111 self->GetInstrumentationStack()->rbegin();
112 std::deque<InstrumentationStackFrame>::const_reverse_iterator end =
113 self->GetInstrumentationStack()->rend();
114 for (; it != end; ++it) {
115 trace->LogMethodTraceEvent(self, (*it).method_, Trace::kMethodTraceEnter);
116 }
117 }
118}
119
120static void InstrumentationRestoreStack(Thread* self, void*)
121 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
122 struct RestoreStackVisitor : public StackVisitor {
123 RestoreStackVisitor(Thread* self, uintptr_t instrumentation_exit_pc)
Ian Rogers7a22fa62013-01-23 12:16:16 -0800124 : StackVisitor(self, NULL), self_(self),
125 instrumentation_exit_pc_(instrumentation_exit_pc) {}
Ian Rogers306057f2012-11-26 12:45:53 -0800126
127 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhao725a9572012-11-13 18:20:12 -0800128 if (self_->IsInstrumentationStackEmpty()) {
129 return false; // Stop.
130 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800131 mirror::AbstractMethod* m = GetMethod();
Ian Rogers306057f2012-11-26 12:45:53 -0800132 if (m == NULL) {
133 return true; // Ignore upcalls.
134 }
jeffhao725a9572012-11-13 18:20:12 -0800135 uintptr_t pc = GetReturnPc();
Ian Rogers306057f2012-11-26 12:45:53 -0800136 if (pc == instrumentation_exit_pc_) {
jeffhao725a9572012-11-13 18:20:12 -0800137 InstrumentationStackFrame instrumentation_frame = self_->PopInstrumentationStackFrame();
138 SetReturnPc(instrumentation_frame.return_pc_);
Ian Rogers306057f2012-11-26 12:45:53 -0800139 CHECK(m == instrumentation_frame.method_);
140 CHECK_EQ(GetFrameId(), instrumentation_frame.frame_id_);
141 Runtime* runtime = Runtime::Current();
142 if (runtime->IsMethodTracingActive()) {
143 Trace* trace = runtime->GetInstrumentation()->GetTrace();
144 trace->LogMethodTraceEvent(self_, m, Trace::kMethodTraceExit);
145 }
jeffhao725a9572012-11-13 18:20:12 -0800146 }
147 return true; // Continue.
148 }
Ian Rogers306057f2012-11-26 12:45:53 -0800149 Thread* const self_;
150 const uintptr_t instrumentation_exit_pc_;
jeffhao725a9572012-11-13 18:20:12 -0800151 };
Ian Rogers306057f2012-11-26 12:45:53 -0800152 uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
153 RestoreStackVisitor visitor(self, instrumentation_exit_pc);
154 visitor.WalkStack(true);
jeffhao725a9572012-11-13 18:20:12 -0800155}
156
157Instrumentation::~Instrumentation() {
158 delete trace_;
159}
160
161void Instrumentation::InstallStubs() {
Ian Rogers306057f2012-11-26 12:45:53 -0800162 Thread* self = Thread::Current();
163 Locks::thread_list_lock_->AssertNotHeld(self);
jeffhao725a9572012-11-13 18:20:12 -0800164 Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, NULL);
Ian Rogers306057f2012-11-26 12:45:53 -0800165 MutexLock mu(self, *Locks::thread_list_lock_);
166 Runtime::Current()->GetThreadList()->ForEach(InstrumentationInstallStack, GetTrace());
jeffhao725a9572012-11-13 18:20:12 -0800167}
168
169void Instrumentation::UninstallStubs() {
170 Thread* self = Thread::Current();
171 Locks::thread_list_lock_->AssertNotHeld(self);
172 Runtime::Current()->GetClassLinker()->VisitClasses(UninstallStubsClassVisitor, NULL);
173 MutexLock mu(self, *Locks::thread_list_lock_);
174 Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, NULL);
175}
176
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800177void Instrumentation::AddSavedCodeToMap(const mirror::AbstractMethod* method, const void* code) {
jeffhao725a9572012-11-13 18:20:12 -0800178 saved_code_map_.Put(method, code);
179}
180
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800181void Instrumentation::RemoveSavedCodeFromMap(const mirror::AbstractMethod* method) {
jeffhao725a9572012-11-13 18:20:12 -0800182 saved_code_map_.erase(method);
183}
184
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800185const void* Instrumentation::GetSavedCodeFromMap(const mirror::AbstractMethod* method) {
186 typedef SafeMap<const mirror::AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto
jeffhao725a9572012-11-13 18:20:12 -0800187 It it = saved_code_map_.find(method);
188 if (it == saved_code_map_.end()) {
189 return NULL;
190 } else {
191 return it->second;
192 }
193}
194
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800195void Instrumentation::SaveAndUpdateCode(mirror::AbstractMethod* method) {
jeffhao725a9572012-11-13 18:20:12 -0800196#if defined(ART_USE_LLVM_COMPILER)
197 UNUSED(method);
198 UNIMPLEMENTED(FATAL);
199#else
200 void* instrumentation_stub = GetInstrumentationEntryPoint();
201 CHECK(GetSavedCodeFromMap(method) == NULL);
202 AddSavedCodeToMap(method, method->GetCode());
203 method->SetCode(instrumentation_stub);
204#endif
205}
206
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800207void Instrumentation::ResetSavedCode(mirror::AbstractMethod* method) {
jeffhao725a9572012-11-13 18:20:12 -0800208 CHECK(GetSavedCodeFromMap(method) != NULL);
209 method->SetCode(GetSavedCodeFromMap(method));
210 RemoveSavedCodeFromMap(method);
211}
212
213Trace* Instrumentation::GetTrace() const {
214 return trace_;
215}
216
217void Instrumentation::SetTrace(Trace* trace) {
218 trace_ = trace;
219}
220
221void Instrumentation::RemoveTrace() {
222 delete trace_;
223 trace_ = NULL;
224}
225
226uint32_t InstrumentationMethodUnwindFromCode(Thread* self) {
227 Trace* trace = Runtime::Current()->GetInstrumentation()->GetTrace();
228 InstrumentationStackFrame instrumentation_frame = self->PopInstrumentationStackFrame();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800229 mirror::AbstractMethod* method = instrumentation_frame.method_;
jeffhao725a9572012-11-13 18:20:12 -0800230 uint32_t lr = instrumentation_frame.return_pc_;
231
232 trace->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
233
234 return lr;
235}
236
237} // namespace art