1d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light/*
2d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * Copyright (C) 2017 The Android Open Source Project
3d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light *
4d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * Licensed under the Apache License, Version 2.0 (the "License");
5d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * you may not use this file except in compliance with the License.
6d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * You may obtain a copy of the License at
7d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light *
8d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light *      http://www.apache.org/licenses/LICENSE-2.0
9d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light *
10d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * Unless required by applicable law or agreed to in writing, software
11d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * distributed under the License is distributed on an "AS IS" BASIS,
12d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * See the License for the specific language governing permissions and
14d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light * limitations under the License.
15d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light */
16d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
17d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light#include "common_helper.h"
18d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
19d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light#include "jni.h"
20d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light#include "jvmti.h"
21d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
22d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light#include "jvmti_helper.h"
23d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light#include "scoped_local_ref.h"
24d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light#include "test_env.h"
25d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
26d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightnamespace art {
27d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
28d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightnamespace common_breakpoint {
29d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
30d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightstruct BreakpointData {
31d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jclass test_klass;
32d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jmethodID breakpoint_method;
33d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  bool in_callback;
34d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  bool allow_recursive;
35d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light};
36d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
37d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightextern "C" void breakpointCB(jvmtiEnv* jvmti,
38d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                             JNIEnv* jnienv,
39d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                             jthread thread,
40d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                             jmethodID method,
41d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                             jlocation location) {
42d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  BreakpointData* data = nullptr;
43d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (JvmtiErrorToException(jnienv, jvmti,
44d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                            jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
45d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
46d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
47d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (data->in_callback && !data->allow_recursive) {
48d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
49d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
50d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  data->in_callback = true;
51d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jobject method_arg = GetJavaMethod(jvmti, jnienv, method);
52d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jnienv->CallStaticVoidMethod(data->test_klass,
53d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                               data->breakpoint_method,
54d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                               thread,
55d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                               method_arg,
56d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                               static_cast<jlong>(location));
57d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jnienv->DeleteLocalRef(method_arg);
58d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  data->in_callback = false;
59d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}
60d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
61d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightextern "C" JNIEXPORT jobjectArray JNICALL Java_art_Breakpoint_getLineNumberTableNative(
62d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    JNIEnv* env,
63d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jclass k ATTRIBUTE_UNUSED,
64d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jobject target) {
65d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jmethodID method = env->FromReflectedMethod(target);
66d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
67d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return nullptr;
68d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
69d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jint nlines;
70d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jvmtiLineNumberEntry* lines = nullptr;
71d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (JvmtiErrorToException(env, jvmti_env,
72d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                            jvmti_env->GetLineNumberTable(method, &nlines, &lines))) {
73d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return nullptr;
74d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
75d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jintArray lines_array = env->NewIntArray(nlines);
76d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
77d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(lines));
78d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return nullptr;
79d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
80d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jlongArray locs_array = env->NewLongArray(nlines);
81d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
82d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(lines));
83d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return nullptr;
84d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
85d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  ScopedLocalRef<jclass> object_class(env, env->FindClass("java/lang/Object"));
86d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
87d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(lines));
88d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return nullptr;
89d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
90d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jobjectArray ret = env->NewObjectArray(2, object_class.get(), nullptr);
91d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
92d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(lines));
93d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return nullptr;
94d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
95d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jint* temp_lines = env->GetIntArrayElements(lines_array, /*isCopy*/nullptr);
96d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jlong* temp_locs = env->GetLongArrayElements(locs_array, /*isCopy*/nullptr);
97d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  for (jint i = 0; i < nlines; i++) {
98d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    temp_lines[i] = lines[i].line_number;
99d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    temp_locs[i] = lines[i].start_location;
100d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
101d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  env->ReleaseIntArrayElements(lines_array, temp_lines, 0);
102d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  env->ReleaseLongArrayElements(locs_array, temp_locs, 0);
103d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  env->SetObjectArrayElement(ret, 0, locs_array);
104d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  env->SetObjectArrayElement(ret, 1, lines_array);
105d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(lines));
106d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  return ret;
107d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}
108d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
109d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightextern "C" JNIEXPORT jlong JNICALL Java_art_Breakpoint_getStartLocation(JNIEnv* env,
110d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                        jclass k ATTRIBUTE_UNUSED,
111d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                        jobject target) {
112d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jmethodID method = env->FromReflectedMethod(target);
113d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
114d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return 0;
115d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
116d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jlong start = 0;
117d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jlong end = end;
118d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  JvmtiErrorToException(env, jvmti_env, jvmti_env->GetMethodLocation(method, &start, &end));
119d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  return start;
120d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}
121d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
122d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightextern "C" JNIEXPORT void JNICALL Java_art_Breakpoint_clearBreakpoint(JNIEnv* env,
123d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                      jclass k ATTRIBUTE_UNUSED,
124d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                      jobject target,
125d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                      jlocation location) {
126d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jmethodID method = env->FromReflectedMethod(target);
127d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
128d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
129d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
130d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  JvmtiErrorToException(env, jvmti_env, jvmti_env->ClearBreakpoint(method, location));
131d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}
132d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
133d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightextern "C" JNIEXPORT void JNICALL Java_art_Breakpoint_setBreakpoint(JNIEnv* env,
134d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                    jclass k ATTRIBUTE_UNUSED,
135d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                    jobject target,
136d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                    jlocation location) {
137d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  jmethodID method = env->FromReflectedMethod(target);
138d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (env->ExceptionCheck()) {
139d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
140d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
141d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  JvmtiErrorToException(env, jvmti_env, jvmti_env->SetBreakpoint(method, location));
142d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}
143d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
144d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightextern "C" JNIEXPORT void JNICALL Java_art_Breakpoint_startBreakpointWatch(
145d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    JNIEnv* env,
146d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jclass k ATTRIBUTE_UNUSED,
147d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jclass method_klass,
148d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jobject method,
149d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jboolean allow_recursive,
150d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jthread thr) {
151d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  BreakpointData* data = nullptr;
152d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (JvmtiErrorToException(env,
153d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                            jvmti_env,
154d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                            jvmti_env->Allocate(sizeof(BreakpointData),
155d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                reinterpret_cast<unsigned char**>(&data)))) {
156d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
157d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
158d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  memset(data, 0, sizeof(BreakpointData));
159d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  data->test_klass = reinterpret_cast<jclass>(env->NewGlobalRef(method_klass));
160d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  data->breakpoint_method = env->FromReflectedMethod(method);
161d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  data->in_callback = false;
162d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  data->allow_recursive = allow_recursive;
163d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
164d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  void* old_data = nullptr;
165d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(&old_data))) {
166d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
167d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  } else if (old_data != nullptr) {
168d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException"));
169d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    env->ThrowNew(rt_exception.get(), "Environment already has local storage set!");
170d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
171d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
172d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEnvironmentLocalStorage(data))) {
173d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
174d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
175d3782f304acee54273f551c52f547539c8f4a78bAlex Light  current_callbacks.Breakpoint = breakpointCB;
176d3782f304acee54273f551c52f547539c8f4a78bAlex Light  if (JvmtiErrorToException(env,
177d3782f304acee54273f551c52f547539c8f4a78bAlex Light                            jvmti_env,
178d3782f304acee54273f551c52f547539c8f4a78bAlex Light                            jvmti_env->SetEventCallbacks(&current_callbacks,
179d3782f304acee54273f551c52f547539c8f4a78bAlex Light                                                         sizeof(current_callbacks)))) {
180d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
181d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
182d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (JvmtiErrorToException(env,
183d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                            jvmti_env,
184d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                            jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
185d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                JVMTI_EVENT_BREAKPOINT,
186d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                thr))) {
187d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
188d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
189d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}
190d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
191d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Lightextern "C" JNIEXPORT void JNICALL Java_art_Breakpoint_stopBreakpointWatch(
192d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    JNIEnv* env,
193d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jclass k ATTRIBUTE_UNUSED,
194d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    jthread thr) {
195d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  if (JvmtiErrorToException(env, jvmti_env,
196d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                            jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
197d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                JVMTI_EVENT_BREAKPOINT,
198d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light                                                                thr))) {
199d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light    return;
200d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light  }
201d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}
202d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
203d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}  // namespace common_breakpoint
204d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light
205d0d6596dd85e6fdd7c82c242fbc050f611ad3b09Alex Light}  // namespace art
206