1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License.
6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at
7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software
11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and
14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License.
15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
16872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <stdlib.h>
1807ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <string.h>
1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <unistd.h>
20700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory>
21a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes#include <string>
22a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes
23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "atomic.h"
2443b2e0f9105848da6470458e7c04bf1fd7fcb25cIan Rogers#include "base/hex_dump.h"
2507ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
26761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
27e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h"
28872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h"
29872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_constants.h"
3007ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_event.h"
31872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_expand_buf.h"
3207ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_priv.h"
332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "runtime.h"
34f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier#include "scoped_thread_state_change.h"
35693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "thread-inl.h"
3680afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "utils.h"
37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art {
39872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP {
41872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
424b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughesstd::string DescribeField(const FieldId& field_id) {
43d3ed9a320a89cb9b91b2361892c043ab7e112717Mathieu Chartier  return StringPrintf("%#" PRIx64 " (%s)", field_id, Dbg::GetFieldName(field_id).c_str());
44a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes}
45a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes
464b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughesstd::string DescribeMethod(const MethodId& method_id) {
47d3ed9a320a89cb9b91b2361892c043ab7e112717Mathieu Chartier  return StringPrintf("%#" PRIx64 " (%s)", method_id, Dbg::GetMethodName(method_id).c_str());
48a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes}
49a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes
504b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughesstd::string DescribeRefTypeId(const RefTypeId& ref_type_id) {
51a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  std::string signature("unknown");
52fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers  Dbg::GetSignature(ref_type_id, &signature);
53d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers  return StringPrintf("%#" PRIx64 " (%s)", ref_type_id, signature.c_str());
54872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
564993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughesstatic JdwpError WriteTaggedObject(ExpandBuf* reply, ObjectId object_id)
5790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
584993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  uint8_t tag;
59c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetObjectTag(object_id, &tag);
604993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  if (rc == ERR_NONE) {
614993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    expandBufAdd1(reply, tag);
624993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    expandBufAddObjectId(reply, object_id);
634993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  }
644993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  return rc;
654993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes}
664993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
670cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughesstatic JdwpError WriteTaggedObjectList(ExpandBuf* reply, const std::vector<ObjectId>& objects)
6890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
690cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  expandBufAdd4BE(reply, objects.size());
700cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  for (size_t i = 0; i < objects.size(); ++i) {
710cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes    JdwpError rc = WriteTaggedObject(reply, objects[i]);
720cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes    if (rc != ERR_NONE) {
730cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes      return rc;
740cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes    }
750cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  }
760cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  return ERR_NONE;
770cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes}
780cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes
79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Common code for *_InvokeMethod requests.
81872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
82748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * If "is_constructor" is set, this returns "object_id" rather than the
83872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * expected-to-be-void return value of the called function.
84872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
85cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzstatic JdwpError RequestInvoke(JdwpState*, Request* request,
861558b577907b613864e98f05862543557263e864Sebastien Hertz                               ObjectId thread_id, ObjectId object_id,
871558b577907b613864e98f05862543557263e864Sebastien Hertz                               RefTypeId class_id, MethodId method_id, bool is_constructor)
8890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
89748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  CHECK(!is_constructor || object_id != 0);
90872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
91c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t arg_count = request->ReadSigned32("argument count");
92872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
93d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers  VLOG(jdwp) << StringPrintf("    --> thread_id=%#" PRIx64 " object_id=%#" PRIx64,
94d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                             thread_id, object_id);
95d3ed9a320a89cb9b91b2361892c043ab7e112717Mathieu Chartier  VLOG(jdwp) << StringPrintf("        class_id=%#" PRIx64 " method_id=%#" PRIx64 " %s.%s",
96d3ed9a320a89cb9b91b2361892c043ab7e112717Mathieu Chartier                             class_id, method_id, Dbg::GetClassName(class_id).c_str(),
97a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes                             Dbg::GetMethodName(method_id).c_str());
9845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes  VLOG(jdwp) << StringPrintf("        %d args:", arg_count);
9945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes
1007d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  std::unique_ptr<JdwpTag[]> argTypes(arg_count > 0 ? new JdwpTag[arg_count] : nullptr);
1017d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  std::unique_ptr<uint64_t[]> argValues(arg_count > 0 ? new uint64_t[arg_count] : nullptr);
102a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  for (int32_t i = 0; i < arg_count; ++i) {
103c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    argTypes[i] = request->ReadTag();
10445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes    size_t width = Dbg::GetTagWidth(argTypes[i]);
105c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    argValues[i] = request->ReadValue(width);
106d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers    VLOG(jdwp) << "          " << argTypes[i] << StringPrintf("(%zd): %#" PRIx64, width,
107d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                                                              argValues[i]);
108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
110c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t options = request->ReadUnsigned32("InvokeOptions bit flags");
11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  VLOG(jdwp) << StringPrintf("        options=0x%04x%s%s", options,
11200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                             (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "",
11300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                             (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
115cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  JDWP::JdwpError error =  Dbg::PrepareInvokeMethod(request->GetId(), thread_id, object_id,
116cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                                    class_id, method_id, arg_count,
117cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                                    argValues.get(), argTypes.get(), options);
118cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (error == JDWP::ERR_NONE) {
119cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // We successfully requested the invoke. The event thread now owns the arguments array in its
120cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // DebugInvokeReq mailbox.
121cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    argValues.release();
122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
123cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  return error;
124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
126c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_Version(JdwpState*, Request*, ExpandBuf* pReply)
12790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
128927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  // Text information on runtime version.
129872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  std::string version(StringPrintf("Android Runtime %s", Runtime::Current()->GetVersion()));
1304740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes  expandBufAddUtf8String(pReply, version);
131927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes
132927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  // JDWP version numbers, major and minor.
133927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  expandBufAdd4BE(pReply, 1);
134927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  expandBufAdd4BE(pReply, 6);
135927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes
136927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  // "java.version".
137927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  expandBufAddUtf8String(pReply, "1.6.0");
138927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes
139927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  // "java.vm.name".
140927bd29ded304e143a967ef014c13a02af4c5c4bElliott Hughes  expandBufAddUtf8String(pReply, "Dalvik");
141872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
142872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
143872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
144872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
145872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
146872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Given a class JNI signature (e.g. "Ljava/lang/Error;"), return the
147872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * referenceTypeID.  We need to send back more than one if the class has
148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * been loaded by multiple class loaders.
149872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
150c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_ClassesBySignature(JdwpState*, Request* request, ExpandBuf* pReply)
15190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
152c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  std::string classDescriptor(request->ReadUtf8String());
153872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1546fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes  std::vector<RefTypeId> ids;
155c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Dbg::FindLoadedClassBySignature(classDescriptor.c_str(), &ids);
156872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1576fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes  expandBufAdd4BE(pReply, ids.size());
158872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1596fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes  for (size_t i = 0; i < ids.size(); ++i) {
1606fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes    // Get class vs. interface and status flags.
161436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    JDWP::JdwpTypeTag type_tag;
162436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    uint32_t class_status;
1637d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz    JDWP::JdwpError status = Dbg::GetClassInfo(ids[i], &type_tag, &class_status, nullptr);
164436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    if (status != ERR_NONE) {
165436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes      return status;
1667b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes    }
167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
168436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    expandBufAdd1(pReply, type_tag);
1696fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes    expandBufAddRefTypeId(pReply, ids[i]);
170436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    expandBufAdd4BE(pReply, class_status);
171872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
172872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
173872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
174872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
175872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
176872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
177872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Handle request for the thread IDs of all running threads.
178872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
179872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We exclude ourselves from the list, because we don't allow ourselves
180872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * to be suspended, and that violates some JDWP expectations.
181872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
182c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_AllThreads(JdwpState*, Request*, ExpandBuf* pReply)
18390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
184caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes  std::vector<ObjectId> thread_ids;
185a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  Dbg::GetThreads(nullptr /* all thread groups */, &thread_ids);
186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
187caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes  expandBufAdd4BE(pReply, thread_ids.size());
188caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes  for (uint32_t i = 0; i < thread_ids.size(); ++i) {
189caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes    expandBufAddObjectId(pReply, thread_ids[i]);
190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
191872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
192872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
193872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
194872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
195872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
196872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * List all thread groups that do not have a parent.
197872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
198c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_TopLevelThreadGroups(JdwpState*, Request*, ExpandBuf* pReply)
19990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
200872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
201872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * TODO: maintain a list of parentless thread groups in the VM.
202872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   *
203872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * For now, just return "system".  Application threads are created
204872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * in "main", which is a child of "system".
205872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
206872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint32_t groups = 1;
207872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, groups);
208caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes  ObjectId thread_group_id = Dbg::GetSystemThreadGroupId();
209caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes  expandBufAddObjectId(pReply, thread_group_id);
210872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
211872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
212872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
213872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
214872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Respond with the sizes of the basic debugger types.
216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
217c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_IDSizes(JdwpState*, Request*, ExpandBuf* pReply)
21890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
219872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, sizeof(FieldId));
220872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, sizeof(MethodId));
221872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, sizeof(ObjectId));
222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, sizeof(RefTypeId));
223872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, sizeof(FrameId));
224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
225872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
226872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
227c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_Dispose(JdwpState*, Request*, ExpandBuf*)
22890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
2294e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz  Dbg::Dispose();
230872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
231872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
232872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
233872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
234872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Suspend the execution of the application running in the VM (i.e. suspend
235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * all threads).
236872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
237872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This needs to increment the "suspend count" on all threads.
238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
239c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_Suspend(JdwpState*, Request*, ExpandBuf*)
24090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
241a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao  Thread* self = Thread::Current();
242f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  ScopedThreadSuspension sts(self, kWaitingForDebuggerSuspension);
243475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes  Dbg::SuspendVM();
244872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
245872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
246872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Resume execution.  Decrements the "suspend count" of all threads.
249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
250c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_Resume(JdwpState*, Request*, ExpandBuf*)
25190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
252872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  Dbg::ResumeVM();
253872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
254872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
255872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
256c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_Exit(JdwpState* state, Request* request, ExpandBuf*)
25790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
258c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t exit_status = request->ReadUnsigned32("exit_status");
25964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  state->ExitAfterReplying(exit_status);
26064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return ERR_NONE;
261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
262872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
263872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
264872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Create a new string in the VM and return its ID.
265872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
266872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * (Ctrl-Shift-I in Eclipse on an array of objects causes it to create the
267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * string "java.util.Arrays".)
268872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
269c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_CreateString(JdwpState*, Request* request, ExpandBuf* pReply)
27090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
271c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  std::string str(request->ReadUtf8String());
2722c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  ObjectId string_id;
2732c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  JdwpError status = Dbg::CreateString(str, &string_id);
2742c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  if (status != ERR_NONE) {
2752c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz    return status;
276872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
2772c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz  expandBufAddObjectId(pReply, string_id);
278872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
279872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
280872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
281c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_ClassPaths(JdwpState*, Request*, ExpandBuf* pReply)
28290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
283a3ae2b7c6598e9b1cf08e42ae4a8de38237b181bElliott Hughes  expandBufAddUtf8String(pReply, "/");
284872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
285a3ae2b7c6598e9b1cf08e42ae4a8de38237b181bElliott Hughes  std::vector<std::string> class_path;
2866f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  Split(Runtime::Current()->GetClassPathString(), ':', &class_path);
287a3ae2b7c6598e9b1cf08e42ae4a8de38237b181bElliott Hughes  expandBufAdd4BE(pReply, class_path.size());
288e6c143fae8ec487704b3d0d28914cda3d6d19e88Sebastien Hertz  for (const std::string& str : class_path) {
289e6c143fae8ec487704b3d0d28914cda3d6d19e88Sebastien Hertz    expandBufAddUtf8String(pReply, str);
290872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
291872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
292a3ae2b7c6598e9b1cf08e42ae4a8de38237b181bElliott Hughes  std::vector<std::string> boot_class_path;
2936f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  Split(Runtime::Current()->GetBootClassPathString(), ':', &boot_class_path);
294a3ae2b7c6598e9b1cf08e42ae4a8de38237b181bElliott Hughes  expandBufAdd4BE(pReply, boot_class_path.size());
295e6c143fae8ec487704b3d0d28914cda3d6d19e88Sebastien Hertz  for (const std::string& str : boot_class_path) {
296e6c143fae8ec487704b3d0d28914cda3d6d19e88Sebastien Hertz    expandBufAddUtf8String(pReply, str);
297872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
298872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
299872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
300872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
301872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
302c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_DisposeObjects(JdwpState*, Request* request, ExpandBuf*)
30390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
304c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  size_t object_count = request->ReadUnsigned32("object_count");
30564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  for (size_t i = 0; i < object_count; ++i) {
306c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    ObjectId object_id = request->ReadObjectId();
307c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    uint32_t reference_count = request->ReadUnsigned32("reference_count");
30864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    Dbg::DisposeObject(object_id, reference_count);
30964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
310872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
311872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
312872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
313c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_Capabilities(JdwpState*, Request*, ExpandBuf* reply)
31490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
315479fc1ecc12fa6560ca90d841c4d5174fb346618Sebastien Hertz  expandBufAdd1(reply, true);    // canWatchFieldModification
316479fc1ecc12fa6560ca90d841c4d5174fb346618Sebastien Hertz  expandBufAdd1(reply, true);    // canWatchFieldAccess
3179777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  expandBufAdd1(reply, true);    // canGetBytecodes
3184993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, true);    // canGetSyntheticAttribute
3194993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, true);    // canGetOwnedMonitorInfo
320f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  expandBufAdd1(reply, true);    // canGetCurrentContendedMonitor
3214993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, true);    // canGetMonitorInfo
3224993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  return ERR_NONE;
3234993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes}
3244993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
325c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_CapabilitiesNew(JdwpState*, Request* request, ExpandBuf* reply)
32690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
3274993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  // The first few capabilities are the same as those reported by the older call.
3287d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  VM_Capabilities(nullptr, request, reply);
3294993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
3304993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // canRedefineClasses
3314993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // canAddMethod
3324993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // canUnrestrictedlyRedefineClasses
3334993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // canPopFrames
3345f4e6f56fcc4289eed73e7ad00d874148aeb68d1Sebastien Hertz  expandBufAdd1(reply, true);    // canUseInstanceFilters
3354993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // canGetSourceDebugExtension
3364993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // canRequestVMDeathEvent
3374993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // canSetDefaultStratum
338ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  expandBufAdd1(reply, true);    // 1.6: canGetInstanceInfo
3394993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // 1.6: canRequestMonitorEvents
340734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  expandBufAdd1(reply, true);    // 1.6: canGetMonitorFrameInfo
3414993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // 1.6: canUseSourceNameFilters
3424993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // 1.6: canGetConstantPool
3434993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd1(reply, false);   // 1.6: canForceEarlyReturn
3444993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
3454993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  // Fill in reserved22 through reserved32; note count started at 1.
3464993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  for (size_t i = 22; i <= 32; ++i) {
3474993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    expandBufAdd1(reply, false);
348872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
349872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
350872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
351872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
35200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic JdwpError VM_AllClassesImpl(ExpandBuf* pReply, bool descriptor_and_status, bool generic)
35390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
3547b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  std::vector<JDWP::RefTypeId> classes;
355c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  Dbg::GetClassList(&classes);
356872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
3577b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  expandBufAdd4BE(pReply, classes.size());
358872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
3597b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  for (size_t i = 0; i < classes.size(); ++i) {
360a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    static const char genericSignature[1] = "";
361436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    JDWP::JdwpTypeTag type_tag;
362a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    std::string descriptor;
363436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    uint32_t class_status;
364436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    JDWP::JdwpError status = Dbg::GetClassInfo(classes[i], &type_tag, &class_status, &descriptor);
365436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    if (status != ERR_NONE) {
366436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes      return status;
3677b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes    }
368872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
369436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    expandBufAdd1(pReply, type_tag);
3707b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes    expandBufAddRefTypeId(pReply, classes[i]);
3718696433d1b3d8ba15288483b777edd888de69135Elliott Hughes    if (descriptor_and_status) {
3728696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      expandBufAddUtf8String(pReply, descriptor);
3738696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      if (generic) {
3748696433d1b3d8ba15288483b777edd888de69135Elliott Hughes        expandBufAddUtf8String(pReply, genericSignature);
3758696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      }
376436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes      expandBufAdd4BE(pReply, class_status);
3771fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes    }
378872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
379872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
380872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
382872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
383c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_AllClasses(JdwpState*, Request*, ExpandBuf* pReply)
38490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
3856e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  return VM_AllClassesImpl(pReply, true, false);
3861fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes}
3871fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes
388c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_AllClassesWithGeneric(JdwpState*, Request*, ExpandBuf* pReply)
38990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
3906e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  return VM_AllClassesImpl(pReply, true, true);
3911fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes}
3921fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes
393c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError VM_InstanceCounts(JdwpState*, Request* request, ExpandBuf* pReply)
39490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
395c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t class_count = request->ReadSigned32("class count");
396ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  if (class_count < 0) {
397ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes    return ERR_ILLEGAL_ARGUMENT;
398ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  }
399ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  std::vector<RefTypeId> class_ids;
400ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  for (int32_t i = 0; i < class_count; ++i) {
401c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    class_ids.push_back(request->ReadRefTypeId());
402ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  }
403ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes
404ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  std::vector<uint64_t> counts;
405c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetInstanceCounts(class_ids, &counts);
406ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  if (rc != ERR_NONE) {
407ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes    return rc;
408ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  }
409ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes
410ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  expandBufAdd4BE(pReply, counts.size());
411ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  for (size_t i = 0; i < counts.size(); ++i) {
412ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes    expandBufAdd8BE(pReply, counts[i]);
413ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  }
414ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  return ERR_NONE;
415ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes}
416ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes
417c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Modifiers(JdwpState*, Request* request, ExpandBuf* pReply)
41890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
419c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
420436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return Dbg::GetModifiers(refTypeId, pReply);
421872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
422872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
423872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
424872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Get values from static fields in a reference type.
425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
426c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
42790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
428c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
429c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t field_count = request->ReadSigned32("field count");
4300cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  expandBufAdd4BE(pReply, field_count);
431a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  for (int32_t i = 0; i < field_count; ++i) {
432c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    FieldId fieldId = request->ReadFieldId();
4330cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    JdwpError status = Dbg::GetStaticFieldValue(refTypeId, fieldId, pReply);
4343f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    if (status != ERR_NONE) {
4353f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes      return status;
4363f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    }
437872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
438872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
439872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
440872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
441872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
442872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Get the name of the source file in which a reference type was declared.
443872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
444c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_SourceFile(JdwpState*, Request* request, ExpandBuf* pReply)
44590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
446c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
44703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  std::string source_file;
448c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError status = Dbg::GetSourceFile(refTypeId, &source_file);
449436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  if (status != ERR_NONE) {
450436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    return status;
451872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
4524740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes  expandBufAddUtf8String(pReply, source_file);
45303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes  return ERR_NONE;
454872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
455872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
456872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
457872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the current status of the reference type.
458872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
459c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Status(JdwpState*, Request* request, ExpandBuf* pReply)
46090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
461c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
462436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  JDWP::JdwpTypeTag type_tag;
463436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  uint32_t class_status;
4647d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  JDWP::JdwpError status = Dbg::GetClassInfo(refTypeId, &type_tag, &class_status, nullptr);
465436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  if (status != ERR_NONE) {
466436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    return status;
4677b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
468436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  expandBufAdd4BE(pReply, class_status);
469872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
470872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
471872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
472872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
473872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return interfaces implemented directly by this class.
474872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
475c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Interfaces(JdwpState*, Request* request, ExpandBuf* pReply)
47690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
477c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
478436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return Dbg::OutputDeclaredInterfaces(refTypeId, pReply);
479872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
480872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
481872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the class object corresponding to this type.
483872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
484c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_ClassObject(JdwpState*, Request* request, ExpandBuf* pReply)
48590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
486c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
487a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  ObjectId class_object_id;
488c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError status = Dbg::GetClassObject(refTypeId, &class_object_id);
489436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  if (status != ERR_NONE) {
490436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    return status;
4917b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
492d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers  VLOG(jdwp) << StringPrintf("    --> ObjectId %#" PRIx64, class_object_id);
493a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  expandBufAddObjectId(pReply, class_object_id);
494872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
495872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
496872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
497872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
498872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Returns the value of the SourceDebugExtension attribute.
499872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
500872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * JDB seems interested, but DEX files don't currently support this.
501872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
502c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_SourceDebugExtension(JdwpState*, Request*, ExpandBuf*)
50390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
504872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* referenceTypeId in, string out */
505872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_ABSENT_INFORMATION;
506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
508c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Signature(JdwpState*, Request* request, ExpandBuf* pReply, bool with_generic)
50990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
510c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
511872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
5127b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  std::string signature;
513fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers  JdwpError status = Dbg::GetSignature(refTypeId, &signature);
51498e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes  if (status != ERR_NONE) {
51598e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes    return status;
51698e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes  }
51798e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes  expandBufAddUtf8String(pReply, signature);
51898e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes  if (with_generic) {
5190cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes    expandBufAddUtf8String(pReply, "");
520872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
521872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
522872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
523872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
524c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Signature(JdwpState* state, Request* request, ExpandBuf* pReply)
52590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
5264b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  return RT_Signature(state, request, pReply, false);
52798e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes}
52898e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes
529c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_SignatureWithGeneric(JdwpState* state, Request* request, ExpandBuf* pReply)
53090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
5314b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  return RT_Signature(state, request, pReply, true);
53298e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes}
53398e43f6f6ebed9c5901de53f2d6b41a32cd6ad95Elliott Hughes
534872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
535872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the instance of java.lang.ClassLoader that loaded the specified
536872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * reference type, or null if it was loaded by the system loader.
537872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
538c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_ClassLoader(JdwpState*, Request* request, ExpandBuf* pReply)
53990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
540c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
541436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return Dbg::GetClassLoader(refTypeId, pReply);
542872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
543872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
544872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
545872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Given a referenceTypeId, return a block of stuff that describes the
546872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * fields declared by a class.
547872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
548c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_FieldsWithGeneric(JdwpState*, Request* request, ExpandBuf* pReply)
54990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
550c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
551436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return Dbg::OutputDeclaredFields(refTypeId, true, pReply);
5527b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes}
5537b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes
5547b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes// Obsolete equivalent of FieldsWithGeneric, without the generic type information.
555c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Fields(JdwpState*, Request* request, ExpandBuf* pReply)
55690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
557c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
558436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return Dbg::OutputDeclaredFields(refTypeId, false, pReply);
559872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
560872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
561872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
562872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Given a referenceTypeID, return a block of goodies describing the
563872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * methods declared by a class.
564872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
565c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_MethodsWithGeneric(JdwpState*, Request* request, ExpandBuf* pReply)
56690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
567c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
568436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return Dbg::OutputDeclaredMethods(refTypeId, true, pReply);
5697b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes}
570872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
5717b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes// Obsolete equivalent of MethodsWithGeneric, without the generic type information.
572c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Methods(JdwpState*, Request* request, ExpandBuf* pReply)
57390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
574c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
575436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  return Dbg::OutputDeclaredMethods(refTypeId, false, pReply);
576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
577872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
578c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError RT_Instances(JdwpState*, Request* request, ExpandBuf* reply)
57990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
580c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
581c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t max_count = request->ReadSigned32("max count");
5823b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  if (max_count < 0) {
5833b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes    return ERR_ILLEGAL_ARGUMENT;
5843b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  }
5853b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes
5863b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  std::vector<ObjectId> instances;
587c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetInstances(class_id, max_count, &instances);
5883b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  if (rc != ERR_NONE) {
5893b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes    return rc;
5903b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  }
5913b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes
5920cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  return WriteTaggedObjectList(reply, instances);
5933b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes}
5943b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes
595872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
596872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the immediate superclass of a class.
597872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
598c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError CT_Superclass(JdwpState*, Request* request, ExpandBuf* pReply)
59990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
600c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
6017b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  RefTypeId superClassId;
602c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError status = Dbg::GetSuperclass(class_id, &superClassId);
6033d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  if (status != ERR_NONE) {
6043d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    return status;
6057b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
606872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAddRefTypeId(pReply, superClassId);
607872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
608872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
609872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
610872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
611872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Set static class values.
612872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
613c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError CT_SetValues(JdwpState* , Request* request, ExpandBuf*)
61490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
615c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
616c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t values_count = request->ReadSigned32("values count");
617872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
618a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  UNUSED(class_id);
619872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
620a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  for (int32_t i = 0; i < values_count; ++i) {
621c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    FieldId fieldId = request->ReadFieldId();
622aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes    JDWP::JdwpTag fieldTag = Dbg::GetStaticFieldBasicTag(fieldId);
623dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    size_t width = Dbg::GetTagWidth(fieldTag);
624c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    uint64_t value = request->ReadValue(width);
625872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
626a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    VLOG(jdwp) << "    --> field=" << fieldId << " tag=" << fieldTag << " --> " << value;
6273d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    JdwpError status = Dbg::SetStaticFieldValue(fieldId, value, width);
6283d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    if (status != ERR_NONE) {
6293d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes      return status;
6303d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    }
631872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
632872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
633872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
634872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
635872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
636872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Invoke a static method.
638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Example: Eclipse sometimes uses java/lang/Class.forName(String s) on
640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * values in the "variables" display.
641872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
642cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzstatic JdwpError CT_InvokeMethod(JdwpState* state, Request* request,
643cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                 ExpandBuf* pReply ATTRIBUTE_UNUSED)
64490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
645c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
646c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
647c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  MethodId method_id = request->ReadMethodId();
648872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
649cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  return RequestInvoke(state, request, thread_id, 0, class_id, method_id, false);
650872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
651872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
652872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
653872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Create a new object of the requested type, and invoke the specified
654872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * constructor.
655872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
656872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Example: in IntelliJ, create a watch on "new String(myByteArray)" to
657872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * see the contents of a byte[] as a string.
658872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
659cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzstatic JdwpError CT_NewInstance(JdwpState* state, Request* request,
660cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                ExpandBuf* pReply ATTRIBUTE_UNUSED)
66190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
662c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
663c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
664c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  MethodId method_id = request->ReadMethodId();
665872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
666748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  ObjectId object_id;
667c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError status = Dbg::CreateObject(class_id, &object_id);
668436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  if (status != ERR_NONE) {
669436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    return status;
6707b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
671cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  return RequestInvoke(state, request, thread_id, object_id, class_id, method_id, true);
672872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
673872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
674872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
675872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Create a new array object of the requested type and length.
676872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
677c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError AT_newInstance(JdwpState*, Request* request, ExpandBuf* pReply)
67890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
679c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId arrayTypeId = request->ReadRefTypeId();
680c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t length = request->ReadSigned32("length");
681872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
682748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  ObjectId object_id;
683c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError status = Dbg::CreateArrayObject(arrayTypeId, length, &object_id);
684436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes  if (status != ERR_NONE) {
685436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes    return status;
6867b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes  }
687872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd1(pReply, JT_ARRAY);
688748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  expandBufAddObjectId(pReply, object_id);
689872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
690872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
691872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
692872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
69370fa1a5497c057eecf336c60975fbca015f8aebdAlex Light * Invoke a static method on an interface.
69470fa1a5497c057eecf336c60975fbca015f8aebdAlex Light */
69570fa1a5497c057eecf336c60975fbca015f8aebdAlex Lightstatic JdwpError IT_InvokeMethod(JdwpState* state, Request* request,
69670fa1a5497c057eecf336c60975fbca015f8aebdAlex Light                                 ExpandBuf* pReply ATTRIBUTE_UNUSED)
69770fa1a5497c057eecf336c60975fbca015f8aebdAlex Light    SHARED_REQUIRES(Locks::mutator_lock_) {
69870fa1a5497c057eecf336c60975fbca015f8aebdAlex Light  RefTypeId class_id = request->ReadRefTypeId();
69970fa1a5497c057eecf336c60975fbca015f8aebdAlex Light  ObjectId thread_id = request->ReadThreadId();
70070fa1a5497c057eecf336c60975fbca015f8aebdAlex Light  MethodId method_id = request->ReadMethodId();
70170fa1a5497c057eecf336c60975fbca015f8aebdAlex Light
70270fa1a5497c057eecf336c60975fbca015f8aebdAlex Light  return RequestInvoke(state, request, thread_id, 0, class_id, method_id, false);
70370fa1a5497c057eecf336c60975fbca015f8aebdAlex Light}
70470fa1a5497c057eecf336c60975fbca015f8aebdAlex Light
70570fa1a5497c057eecf336c60975fbca015f8aebdAlex Light/*
706872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return line number information for the method, if present.
707872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
708c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError M_LineTable(JdwpState*, Request* request, ExpandBuf* pReply)
70990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
710c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId refTypeId = request->ReadRefTypeId();
711c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  MethodId method_id = request->ReadMethodId();
712872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
713748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  Dbg::OutputLineTable(refTypeId, method_id, pReply);
714872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
715872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
716872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
717872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
718c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError M_VariableTable(JdwpState*, Request* request, ExpandBuf* pReply,
71900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                 bool generic)
72090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
721c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
722c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  MethodId method_id = request->ReadMethodId();
723872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
7243d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  // We could return ERR_ABSENT_INFORMATION here if the DEX file was built without local variable
7253d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  // information. That will cause Eclipse to make a best-effort attempt at displaying local
7263d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  // variables anonymously. However, the attempt isn't very good, so we're probably better off just
7273d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  // not showing anything.
728748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  Dbg::OutputVariableTable(class_id, method_id, generic, pReply);
729872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
730872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
731872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
732c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError M_VariableTable(JdwpState* state, Request* request, ExpandBuf* pReply)
73390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
7344b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  return M_VariableTable(state, request, pReply, false);
7353d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes}
7363d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes
737c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError M_VariableTableWithGeneric(JdwpState* state, Request* request, ExpandBuf* pReply)
73890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
7394b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  return M_VariableTable(state, request, pReply, true);
7403d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes}
7413d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes
742c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError M_Bytecodes(JdwpState*, Request* request, ExpandBuf* reply)
74390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
744c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
745c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  MethodId method_id = request->ReadMethodId();
7469777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes
7479777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  std::vector<uint8_t> bytecodes;
748c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetBytecodes(class_id, method_id, &bytecodes);
7499777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  if (rc != ERR_NONE) {
7509777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes    return rc;
7519777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  }
7529777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes
7539777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  expandBufAdd4BE(reply, bytecodes.size());
7549777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  for (size_t i = 0; i < bytecodes.size(); ++i) {
7559777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes    expandBufAdd1(reply, bytecodes[i]);
7569777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  }
7579777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes
7589777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  return ERR_NONE;
7599777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes}
7609777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes
7610a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz// Default implementation for IDEs relying on this command.
7620a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertzstatic JdwpError M_IsObsolete(JdwpState*, Request* request, ExpandBuf* reply)
7630a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz    SHARED_REQUIRES(Locks::mutator_lock_) {
7640a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz  request->ReadRefTypeId();  // unused reference type ID
7650a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz  request->ReadMethodId();   // unused method ID
7660a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz  expandBufAdd1(reply, false);  // a method is never obsolete.
7670a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz  return ERR_NONE;
7680a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz}
7690a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz
770872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
771872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Given an object reference, return the runtime type of the object
772872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * (class or array).
773872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
774748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * This can get called on different things, e.g. thread_id gets
775872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * passed in here.
776872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
777c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_ReferenceType(JdwpState*, Request* request, ExpandBuf* pReply)
77890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
779c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
780748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  return Dbg::GetReferenceType(object_id, pReply);
781872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
782872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
783872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
784872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Get values from the fields of an object.
785872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
786c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
78790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
788c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
789c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t field_count = request->ReadSigned32("field count");
790872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
7910cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes  expandBufAdd4BE(pReply, field_count);
792a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  for (int32_t i = 0; i < field_count; ++i) {
793c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    FieldId fieldId = request->ReadFieldId();
794748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes    JdwpError status = Dbg::GetFieldValue(object_id, fieldId, pReply);
7953f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    if (status != ERR_NONE) {
7963f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes      return status;
7973f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    }
798872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
799872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
800872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
801872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
802872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
803872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
804872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Set values in the fields of an object.
805872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
806c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_SetValues(JdwpState*, Request* request, ExpandBuf*)
80790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
808c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
809c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t field_count = request->ReadSigned32("field count");
810872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
811a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  for (int32_t i = 0; i < field_count; ++i) {
812c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    FieldId fieldId = request->ReadFieldId();
813872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
814aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes    JDWP::JdwpTag fieldTag = Dbg::GetFieldBasicTag(fieldId);
815dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    size_t width = Dbg::GetTagWidth(fieldTag);
816c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    uint64_t value = request->ReadValue(width);
817872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
8182435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes    VLOG(jdwp) << "    --> fieldId=" << fieldId << " tag=" << fieldTag << "(" << width << ") value=" << value;
819748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes    JdwpError status = Dbg::SetFieldValue(object_id, fieldId, value, width);
8203f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    if (status != ERR_NONE) {
8213f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes      return status;
8223f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    }
823872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
824872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
825872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
826872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
827872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
828c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_MonitorInfo(JdwpState*, Request* request, ExpandBuf* reply)
82990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
830c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
831f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  return Dbg::GetMonitorInfo(object_id, reply);
832f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes}
833f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes
834872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
835872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Invoke an instance method.  The invocation must occur in the specified
836872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * thread, which must have been suspended by an event.
837872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
838872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The call is synchronous.  All threads in the VM are resumed, unless the
839872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * SINGLE_THREADED flag is set.
840872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
841872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If you ask Eclipse to "inspect" an object (or ask JDB to "print" an
842872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * object), it will try to invoke the object's toString() function.  This
843872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * feature becomes crucial when examining ArrayLists with Eclipse.
844872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
845cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzstatic JdwpError OR_InvokeMethod(JdwpState* state, Request* request,
846cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz                                 ExpandBuf* pReply ATTRIBUTE_UNUSED)
84790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
848c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
849c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
850c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_id = request->ReadRefTypeId();
851c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  MethodId method_id = request->ReadMethodId();
852872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
853cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  return RequestInvoke(state, request, thread_id, object_id, class_id, method_id, false);
854872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
855872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
856c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_DisableCollection(JdwpState*, Request* request, ExpandBuf*)
85790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
858c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
85964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return Dbg::DisableCollection(object_id);
860872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
861872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
862c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_EnableCollection(JdwpState*, Request* request, ExpandBuf*)
86390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
864c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
86564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return Dbg::EnableCollection(object_id);
866872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
867872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
868c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_IsCollected(JdwpState*, Request* request, ExpandBuf* pReply)
86990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
870c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
87164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  bool is_collected;
872c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::IsCollected(object_id, &is_collected);
87364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  expandBufAdd1(pReply, is_collected ? 1 : 0);
87464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return rc;
875872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
876872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
877c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError OR_ReferringObjects(JdwpState*, Request* request, ExpandBuf* reply)
87890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
879c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId object_id = request->ReadObjectId();
880c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t max_count = request->ReadSigned32("max count");
8810cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  if (max_count < 0) {
8820cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes    return ERR_ILLEGAL_ARGUMENT;
8830cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  }
8840cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes
8850cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  std::vector<ObjectId> referring_objects;
886c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetReferringObjects(object_id, max_count, &referring_objects);
8870cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  if (rc != ERR_NONE) {
8880cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes    return rc;
8890cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  }
8900cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes
8910cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  return WriteTaggedObjectList(reply, referring_objects);
8920cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes}
8930cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes
894872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
895872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the string value in a string object.
896872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
897c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError SR_Value(JdwpState*, Request* request, ExpandBuf* pReply)
89890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
899c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId stringObject = request->ReadObjectId();
900b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  std::string str;
901b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  JDWP::JdwpError error = Dbg::StringToUtf8(stringObject, &str);
902b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  if (error != JDWP::ERR_NONE) {
903b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz    return error;
904b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz  }
905872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
90668b56858367e29461ae290fd797443a1ef6d8005Ian Rogers  VLOG(jdwp) << StringPrintf("    --> %s", PrintableString(str.c_str()).c_str());
907872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9084740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes  expandBufAddUtf8String(pReply, str);
909872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
910872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
911872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
912872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
913872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
914872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return a thread's name.
915872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
916c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_Name(JdwpState*, Request* request, ExpandBuf* pReply)
91790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
918c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
919872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
920a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes  std::string name;
921c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError error = Dbg::GetThreadName(thread_id, &name);
922221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != ERR_NONE) {
923221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
924872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
925d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers  VLOG(jdwp) << StringPrintf("  Name of thread %#" PRIx64 " is \"%s\"", thread_id, name.c_str());
9264740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes  expandBufAddUtf8String(pReply, name);
927872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
928872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
929872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
930872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
931872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
932872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Suspend the specified thread.
933872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
934872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * It's supposed to remain suspended even if interpreted code wants to
935872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * resume it; only the JDI is allowed to resume it.
936872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
937c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_Suspend(JdwpState*, Request* request, ExpandBuf*)
93890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
939c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
940872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
941748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  if (thread_id == Dbg::GetThreadSelfId()) {
942872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(INFO) << "  Warning: ignoring request to suspend self";
943872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return ERR_THREAD_NOT_SUSPENDED;
944872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
945a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes
94600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
947f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  ScopedThreadSuspension sts(self, kWaitingForDebuggerSend);
94800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  JdwpError result = Dbg::SuspendThread(thread_id);
94900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return result;
950872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
951872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
952872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
953872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Resume the specified thread.
954872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
955c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_Resume(JdwpState*, Request* request, ExpandBuf*)
95690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
957c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
958872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
959748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  if (thread_id == Dbg::GetThreadSelfId()) {
960872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(INFO) << "  Warning: ignoring request to resume self";
961872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return ERR_NONE;
962872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
963a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes
964748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  Dbg::ResumeThread(thread_id);
965872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
966872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
967872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
968872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
969872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return status of specified thread.
970872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
971c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_Status(JdwpState*, Request* request, ExpandBuf* pReply)
97290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
973c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
974872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9753d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes  JDWP::JdwpThreadStatus threadStatus;
9763d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes  JDWP::JdwpSuspendStatus suspendStatus;
977221229cb523f849f165fdafbf9785010963715daElliott Hughes  JdwpError error = Dbg::GetThreadStatus(thread_id, &threadStatus, &suspendStatus);
978221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != ERR_NONE) {
979221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
980872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
981872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9824dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(jdwp) << "    --> " << threadStatus << ", " << suspendStatus;
983872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
984872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, threadStatus);
985872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, suspendStatus);
986872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
987872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
988872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
989872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
990872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
991872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the thread group that the specified thread is a member of.
992872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
993c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_ThreadGroup(JdwpState*, Request* request, ExpandBuf* pReply)
99490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
995c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
996748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  return Dbg::GetThreadGroup(thread_id, pReply);
997872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
998872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
999872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1000872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the current call stack of a suspended thread.
1001872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1002872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If the thread isn't suspended, the error code isn't defined, but should
1003872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * be THREAD_NOT_SUSPENDED.
1004872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1005c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_Frames(JdwpState*, Request* request, ExpandBuf* pReply)
100690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1007c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
1008c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t start_frame = request->ReadUnsigned32("start frame");
1009c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t length = request->ReadUnsigned32("length");
1010872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1011221229cb523f849f165fdafbf9785010963715daElliott Hughes  size_t actual_frame_count;
1012c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError error = Dbg::GetThreadFrameCount(thread_id, &actual_frame_count);
1013221229cb523f849f165fdafbf9785010963715daElliott Hughes  if (error != ERR_NONE) {
1014221229cb523f849f165fdafbf9785010963715daElliott Hughes    return error;
1015221229cb523f849f165fdafbf9785010963715daElliott Hughes  }
1016872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10173f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  if (actual_frame_count <= 0) {
10187934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    return ERR_THREAD_NOT_SUSPENDED;  // 0 means no managed frames (which means "in native").
1019872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
10203f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes
10213f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  if (start_frame > actual_frame_count) {
10223f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    return ERR_INVALID_INDEX;
10233f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  }
10243f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  if (length == static_cast<uint32_t>(-1)) {
10253f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    length = actual_frame_count - start_frame;
10263f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  }
10273f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  if (start_frame + length > actual_frame_count) {
10283f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes    return ERR_INVALID_LENGTH;
1029872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1030872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10316e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  return Dbg::GetThreadFrames(thread_id, start_frame, length, pReply);
1032872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1033872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1034872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1035872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Returns the #of frames on the specified thread, which must be suspended.
1036872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1037c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_FrameCount(JdwpState*, Request* request, ExpandBuf* pReply)
103890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1039c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
1040872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1041221229cb523f849f165fdafbf9785010963715daElliott Hughes  size_t frame_count;
1042c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetThreadFrameCount(thread_id, &frame_count);
10434993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  if (rc != ERR_NONE) {
10444993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    return rc;
1045872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
10463f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes  expandBufAdd4BE(pReply, static_cast<uint32_t>(frame_count));
1047872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1048872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
1049872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1050872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1051c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_OwnedMonitors(Request* request, ExpandBuf* reply, bool with_stack_depths)
105290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1053c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
10544993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
10554993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  std::vector<ObjectId> monitors;
1056734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  std::vector<uint32_t> stack_depths;
1057c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetOwnedMonitors(thread_id, &monitors, &stack_depths);
10584993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  if (rc != ERR_NONE) {
10594993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    return rc;
10604993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  }
10614993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
10624993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  expandBufAdd4BE(reply, monitors.size());
10634993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  for (size_t i = 0; i < monitors.size(); ++i) {
10644993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    rc = WriteTaggedObject(reply, monitors[i]);
10654993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    if (rc != ERR_NONE) {
10664993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes      return rc;
10674993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes    }
1068734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes    if (with_stack_depths) {
1069734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes      expandBufAdd4BE(reply, stack_depths[i]);
1070734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes    }
10714993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  }
10724993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  return ERR_NONE;
10734993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes}
10744993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes
1075c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_OwnedMonitors(JdwpState*, Request* request, ExpandBuf* reply)
107690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
10774b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  return TR_OwnedMonitors(request, reply, false);
1078734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes}
1079734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes
1080c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_OwnedMonitorsStackDepthInfo(JdwpState*, Request* request, ExpandBuf* reply)
108190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
10824b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  return TR_OwnedMonitors(request, reply, true);
1083734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes}
1084734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes
1085c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_CurrentContendedMonitor(JdwpState*, Request* request, ExpandBuf* reply)
108690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1087c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
1088872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1089f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  ObjectId contended_monitor;
1090c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError rc = Dbg::GetContendedMonitor(thread_id, &contended_monitor);
1091f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  if (rc != ERR_NONE) {
1092f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes    return rc;
1093f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  }
1094f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  return WriteTaggedObject(reply, contended_monitor);
1095f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes}
1096872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10974b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainstatic JdwpError TR_Interrupt(JdwpState*, Request* request, ExpandBuf* reply ATTRIBUTE_UNUSED)
109890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1099c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
1100f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes  return Dbg::Interrupt(thread_id);
1101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
110400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * Return the debug suspend count for the specified thread.
1105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * (The thread *might* still be running -- it might not have examined
1107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * its suspend count recently.)
1108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1109c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TR_DebugSuspendCount(JdwpState*, Request* request, ExpandBuf* pReply)
111090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1111c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
111200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return Dbg::GetThreadDebugSuspendCount(thread_id, pReply);
1113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the name of a thread group.
1117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The Eclipse debugger recognizes "main" and "system" as special.
1119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1120c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TGR_Name(JdwpState*, Request* request, ExpandBuf* pReply)
112190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1122c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_group_id = request->ReadThreadGroupId();
1123a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  return Dbg::GetThreadGroupName(thread_group_id, pReply);
1124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Returns the thread group -- if any -- that contains the specified
1128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * thread group.
1129872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1130c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TGR_Parent(JdwpState*, Request* request, ExpandBuf* pReply)
113190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1132c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_group_id = request->ReadThreadGroupId();
1133a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  return Dbg::GetThreadGroupParent(thread_group_id, pReply);
1134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the active threads and thread groups that are part of the
1138872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * specified thread group.
1139872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1140c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError TGR_Children(JdwpState*, Request* request, ExpandBuf* pReply)
114190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1142c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_group_id = request->ReadThreadGroupId();
1143a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz  return Dbg::GetThreadGroupChildren(thread_group_id, pReply);
1144872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1145872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1146872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1147872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the #of components in the array.
1148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1149c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError AR_Length(JdwpState*, Request* request, ExpandBuf* pReply)
115090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1151c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId array_id = request->ReadArrayId();
1152872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1153c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t length;
1154c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpError status = Dbg::GetArrayLength(array_id, &length);
11553d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  if (status != ERR_NONE) {
11563d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes    return status;
11573d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  }
11582435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes  VLOG(jdwp) << "    --> " << length;
1159872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
11603d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes  expandBufAdd4BE(pReply, length);
1161872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1162872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
1163872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1164872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1165872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1166872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the values from an array.
1167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1168c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError AR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
116990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1170c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId array_id = request->ReadArrayId();
1171c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t offset = request->ReadUnsigned32("offset");
1172c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t length = request->ReadUnsigned32("length");
1173a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  return Dbg::OutputArray(array_id, offset, length, pReply);
1174872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1175872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1176872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1177872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Set values in an array.
1178872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1179c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError AR_SetValues(JdwpState*, Request* request, ExpandBuf*)
118090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1181c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId array_id = request->ReadArrayId();
1182c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t offset = request->ReadUnsigned32("offset");
1183c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t count = request->ReadUnsigned32("count");
11844b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  return Dbg::SetArrayElements(array_id, offset, count, request);
1185872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1187c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError CLR_VisibleClasses(JdwpState*, Request* request, ExpandBuf* pReply)
118890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1189c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  request->ReadObjectId();  // classLoaderObject
11908696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  // TODO: we should only return classes which have the given class loader as a defining or
11918696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  // initiating loader. The former would be easy; the latter is hard, because we don't have
11928696433d1b3d8ba15288483b777edd888de69135Elliott Hughes  // any such notion.
11936e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  return VM_AllClassesImpl(pReply, false, false);
1194872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1195872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1196358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz// Delete function class to use std::unique_ptr with JdwpEvent.
1197358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertzstruct JdwpEventDeleter {
1198358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz  void operator()(JdwpEvent* event) {
1199358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz    EventFree(event);
1200358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz  }
1201358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz};
1202358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz
1203872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1204872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Set an event trigger.
1205872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1206872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Reply with a requestID.
1207872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1208c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError ER_Set(JdwpState* state, Request* request, ExpandBuf* pReply)
120990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1210c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpEventKind event_kind = request->ReadEnum1<JdwpEventKind>("event kind");
1211c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  JdwpSuspendPolicy suspend_policy = request->ReadEnum1<JdwpSuspendPolicy>("suspend policy");
1212c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  int32_t modifier_count = request->ReadSigned32("modifier count");
1213872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1214a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  CHECK_LT(modifier_count, 256);    /* reasonableness check */
1215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1216358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz  std::unique_ptr<JDWP::JdwpEvent, JdwpEventDeleter> pEvent(EventAlloc(modifier_count));
12174b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  pEvent->eventKind = event_kind;
12184b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  pEvent->suspend_policy = suspend_policy;
1219a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  pEvent->modCount = modifier_count;
1220872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1221872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Read modifiers.  Ordering may be significant (see explanation of Count
1223872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * mods in JDWP doc).
1224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1225a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  for (int32_t i = 0; i < modifier_count; ++i) {
1226972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes    JdwpEventMod& mod = pEvent->mods[i];
1227c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    mod.modKind = request->ReadModKind();
1228972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes    switch (mod.modKind) {
1229a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_COUNT:
1230872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1231a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Report once, when "--count" reaches 0.
1232c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        uint32_t count = request->ReadUnsigned32("count");
1233872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        if (count == 0) {
1234872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes          return ERR_INVALID_COUNT;
1235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        }
1236972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.count.count = count;
1237872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1239a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_CONDITIONAL:
1240872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1241a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Conditional on expression.
1242c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        uint32_t exprId = request->ReadUnsigned32("expr id");
1243972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.conditional.exprId = exprId;
1244872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1245872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1246a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_THREAD_ONLY:
1247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1248a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Only report events in specified thread.
1249c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        ObjectId thread_id = request->ReadThreadId();
1250748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes        mod.threadOnly.threadId = thread_id;
1251872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1252872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1253a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_CLASS_ONLY:
1254872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1255a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // For ClassPrepare, MethodEntry.
1256c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        RefTypeId class_id = request->ReadRefTypeId();
1257748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes        mod.classOnly.refTypeId = class_id;
1258872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1259872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1260a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_CLASS_MATCH:
1261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1262a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Restrict events to matching classes.
12638696433d1b3d8ba15288483b777edd888de69135Elliott Hughes        // pattern is "java.foo.*", we want "java/foo/*".
1264c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        std::string pattern(request->ReadUtf8String());
12658696433d1b3d8ba15288483b777edd888de69135Elliott Hughes        std::replace(pattern.begin(), pattern.end(), '.', '/');
1266972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.classMatch.classPattern = strdup(pattern.c_str());
1267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1268872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1269a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_CLASS_EXCLUDE:
1270872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1271a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Restrict events to non-matching classes.
12728696433d1b3d8ba15288483b777edd888de69135Elliott Hughes        // pattern is "java.foo.*", we want "java/foo/*".
1273c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        std::string pattern(request->ReadUtf8String());
12748696433d1b3d8ba15288483b777edd888de69135Elliott Hughes        std::replace(pattern.begin(), pattern.end(), '.', '/');
1275972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.classExclude.classPattern = strdup(pattern.c_str());
1276872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1277872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1278a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_LOCATION_ONLY:
1279872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1280a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Restrict certain events based on location.
1281c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        JdwpLocation location = request->ReadLocation();
1282a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        mod.locationOnly.loc = location;
1283872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1284872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1285a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_EXCEPTION_ONLY:
1286872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1287a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Modifies EK_EXCEPTION events,
1288c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        mod.exceptionOnly.refTypeId = request->ReadRefTypeId();  // null => all exceptions.
1289c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        mod.exceptionOnly.caught = request->ReadEnum1<uint8_t>("caught");
1290c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        mod.exceptionOnly.uncaught = request->ReadEnum1<uint8_t>("uncaught");
1291872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1292872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1293a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_FIELD_ONLY:
1294872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1295a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // For field access/modification events.
1296c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        RefTypeId declaring = request->ReadRefTypeId();
1297c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        FieldId fieldId = request->ReadFieldId();
1298972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.fieldOnly.refTypeId = declaring;
1299972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.fieldOnly.fieldId = fieldId;
1300872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1301872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1302a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_STEP:
1303872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1304a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // For use with EK_SINGLE_STEP.
1305c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        ObjectId thread_id = request->ReadThreadId();
1306c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        uint32_t size = request->ReadUnsigned32("step size");
1307c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        uint32_t depth = request->ReadUnsigned32("step depth");
1308d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers        VLOG(jdwp) << StringPrintf("    Step: thread=%#" PRIx64, thread_id)
1309872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes                     << " size=" << JdwpStepSize(size) << " depth=" << JdwpStepDepth(depth);
1310872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1311748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes        mod.step.threadId = thread_id;
1312972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.step.size = size;
1313972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.step.depth = depth;
1314872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1316a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes    case MK_INSTANCE_ONLY:
1317872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      {
1318a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes        // Report events related to a specific object.
1319c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        ObjectId instance = request->ReadObjectId();
1320972a47bf0c180dee7e4c697b74dd31daaf58e008Elliott Hughes        mod.instanceOnly.objectId = instance;
1321872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1322872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1323872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    default:
13246d7839e03348111a4237f0d47d0e70bc81b32e7aSebastien Hertz      LOG(WARNING) << "Unsupported modifier " << mod.modKind << " for event " << pEvent->eventKind;
13256d7839e03348111a4237f0d47d0e70bc81b32e7aSebastien Hertz      return JDWP::ERR_NOT_IMPLEMENTED;
1326872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1327872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1328872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1329872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1330872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * We reply with an integer "requestID".
1331872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1332376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  uint32_t requestId = state->NextEventSerial();
1333872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReply, requestId);
1334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1335872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  pEvent->requestId = requestId;
1336872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
13374dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(jdwp) << StringPrintf("    --> event requestId=%#x", requestId);
1338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* add it to the list */
1340358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz  JdwpError err = state->RegisterEvent(pEvent.get());
1341872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (err != ERR_NONE) {
1342872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* registration failed, probably because event is bogus */
1343872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(WARNING) << "WARNING: event request rejected";
1344358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz    return err;
1345872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1346358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz  pEvent.release();
1347358bcaf13ec288ee45be8fc53cb09170c1b8a8f1Sebastien Hertz  return ERR_NONE;
1348872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1349872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1350c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError ER_Clear(JdwpState* state, Request* request, ExpandBuf*)
135190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1352c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  request->ReadEnum1<JdwpEventKind>("event kind");
1353c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  uint32_t requestId = request->ReadUnsigned32("request id");
1354872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
13554b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  // Failure to find an event with a matching ID is a no-op
13564b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  // and does not return an error.
1357761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  state->UnregisterEventById(requestId);
1358872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
1359872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1360872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1361872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1362872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the values of arguments and local variables.
1363872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1364c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError SF_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
136590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
13668009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  return Dbg::GetLocalValues(request, pReply);
1367872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1368872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1369872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1370872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Set the values of arguments and local variables.
1371872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1372c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError SF_SetValues(JdwpState*, Request* request, ExpandBuf*)
137390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
13748009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz  return Dbg::SetLocalValues(request);
1375872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1376872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1377c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError SF_ThisObject(JdwpState*, Request* request, ExpandBuf* reply)
137890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1379c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ObjectId thread_id = request->ReadThreadId();
1380c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  FrameId frame_id = request->ReadFrameId();
1381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
13824993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  ObjectId object_id;
13834993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  JdwpError rc = Dbg::GetThisObject(thread_id, frame_id, &object_id);
13846e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  if (rc != ERR_NONE) {
13856e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes    return rc;
1386546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes  }
1387872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
13884993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes  return WriteTaggedObject(reply, object_id);
1389872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1390872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1391872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1392872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the reference type reflected by this class object.
1393872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1394872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This appears to be required because ReferenceTypeId values are NEVER
1395872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * reused, whereas ClassIds can be recycled like any other object.  (Either
1396872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * that, or I have no idea what this is for.)
1397872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1398c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError COR_ReflectedType(JdwpState*, Request* request, ExpandBuf* pReply)
139990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
1400c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  RefTypeId class_object_id = request->ReadRefTypeId();
1401a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes  return Dbg::GetReflectedType(class_object_id, pReply);
1402872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1403872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1404872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1405872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Handle a DDM packet with a single chunk in it.
1406872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1407c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JdwpError DDM_Chunk(JdwpState* state, Request* request, ExpandBuf* pReply)
140890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
14094b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  state->NotifyDdmsActive();
14107d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  uint8_t* replyBuf = nullptr;
1411872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int replyLen = -1;
14124b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  if (Dbg::DdmHandlePacket(request, &replyBuf, &replyLen)) {
14134b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    // If they want to send something back, we copy it into the buffer.
14144b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    // TODO: consider altering the JDWP stuff to hold the packet header
14154b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    // in a separate buffer.  That would allow us to writev() DDM traffic
14164b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    // instead of copying it into the expanding buffer.  The reduction in
14174b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    // heap requirements is probably more valuable than the efficiency.
14184b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes    CHECK_GT(replyLen, 0);
1419872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    memcpy(expandBufAddSpace(pReply, replyLen), replyBuf, replyLen);
14203901bbc170b73b13aa5092f5709a495a1847198fSebastien Hertz    delete[] replyBuf;
1421872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1422872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
1423872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1424872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Handler map decl.
1427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1428c0542af3e2170143ba40d89136e284997e16bf64Ian Rogerstypedef JdwpError (*JdwpRequestHandler)(JdwpState* state, Request* request, ExpandBuf* reply);
1429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstruct JdwpHandlerMap {
14314b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  uint8_t cmdSet;
14324b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  uint8_t cmd;
14334b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  JdwpRequestHandler func;
14344b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes  const char* name;
1435872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes};
1436872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1437872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1438872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Map commands to functions.
1439872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1440872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Command sets 0-63 are incoming requests, 64-127 are outbound requests,
1441872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * and 128-256 are vendor-defined.
1442872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1443cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughesstatic const JdwpHandlerMap gHandlers[] = {
1444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* VirtualMachine command set (1) */
1445f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    1,  VM_Version,               "VirtualMachine.Version" },
1446f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    2,  VM_ClassesBySignature,    "VirtualMachine.ClassesBySignature" },
1447f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    3,  VM_AllClasses,            "VirtualMachine.AllClasses" },
1448f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    4,  VM_AllThreads,            "VirtualMachine.AllThreads" },
1449f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    5,  VM_TopLevelThreadGroups,  "VirtualMachine.TopLevelThreadGroups" },
1450f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    6,  VM_Dispose,               "VirtualMachine.Dispose" },
1451f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    7,  VM_IDSizes,               "VirtualMachine.IDSizes" },
1452f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    8,  VM_Suspend,               "VirtualMachine.Suspend" },
1453f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    9,  VM_Resume,                "VirtualMachine.Resume" },
1454f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    10, VM_Exit,                  "VirtualMachine.Exit" },
1455f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    11, VM_CreateString,          "VirtualMachine.CreateString" },
1456f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    12, VM_Capabilities,          "VirtualMachine.Capabilities" },
1457f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    13, VM_ClassPaths,            "VirtualMachine.ClassPaths" },
1458f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    14, VM_DisposeObjects,        "VirtualMachine.DisposeObjects" },
14597d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 1,    15, nullptr,                  "VirtualMachine.HoldEvents" },
14607d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 1,    16, nullptr,                  "VirtualMachine.ReleaseEvents" },
1461f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 1,    17, VM_CapabilitiesNew,       "VirtualMachine.CapabilitiesNew" },
14627d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 1,    18, nullptr,                  "VirtualMachine.RedefineClasses" },
14637d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 1,    19, nullptr,                  "VirtualMachine.SetDefaultStratum" },
14646e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 1,    20, VM_AllClassesWithGeneric, "VirtualMachine.AllClassesWithGeneric" },
1465ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  { 1,    21, VM_InstanceCounts,        "VirtualMachine.InstanceCounts" },
1466872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1467872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ReferenceType command set (2) */
1468f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    1,  RT_Signature,            "ReferenceType.Signature" },
1469f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    2,  RT_ClassLoader,          "ReferenceType.ClassLoader" },
1470f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    3,  RT_Modifiers,            "ReferenceType.Modifiers" },
1471f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    4,  RT_Fields,               "ReferenceType.Fields" },
1472f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    5,  RT_Methods,              "ReferenceType.Methods" },
1473f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    6,  RT_GetValues,            "ReferenceType.GetValues" },
1474f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    7,  RT_SourceFile,           "ReferenceType.SourceFile" },
14757d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 2,    8,  nullptr,                 "ReferenceType.NestedTypes" },
1476f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    9,  RT_Status,               "ReferenceType.Status" },
1477f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    10, RT_Interfaces,           "ReferenceType.Interfaces" },
1478f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    11, RT_ClassObject,          "ReferenceType.ClassObject" },
14796e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 2,    12, RT_SourceDebugExtension, "ReferenceType.SourceDebugExtension" },
14806e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 2,    13, RT_SignatureWithGeneric, "ReferenceType.SignatureWithGeneric" },
1481f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    14, RT_FieldsWithGeneric,    "ReferenceType.FieldsWithGeneric" },
1482f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 2,    15, RT_MethodsWithGeneric,   "ReferenceType.MethodsWithGeneric" },
14833b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes  { 2,    16, RT_Instances,            "ReferenceType.Instances" },
14847d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 2,    17, nullptr,                 "ReferenceType.ClassFileVersion" },
14857d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 2,    18, nullptr,                 "ReferenceType.ConstantPool" },
1486872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1487872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ClassType command set (3) */
14886e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 3,    1,  CT_Superclass,    "ClassType.Superclass" },
14896e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 3,    2,  CT_SetValues,     "ClassType.SetValues" },
14906e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 3,    3,  CT_InvokeMethod,  "ClassType.InvokeMethod" },
14916e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 3,    4,  CT_NewInstance,   "ClassType.NewInstance" },
1492872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1493872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ArrayType command set (4) */
14946e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 4,    1,  AT_newInstance,   "ArrayType.NewInstance" },
1495872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1496872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* InterfaceType command set (5) */
149770fa1a5497c057eecf336c60975fbca015f8aebdAlex Light  { 5,    1, IT_InvokeMethod,  "InterfaceType.InvokeMethod" },
1498872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1499872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* Method command set (6) */
1500f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 6,    1,  M_LineTable,                "Method.LineTable" },
1501f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 6,    2,  M_VariableTable,            "Method.VariableTable" },
15029777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes  { 6,    3,  M_Bytecodes,                "Method.Bytecodes" },
15030a97fc6613d525370d9300819a3579f706d6fc67Sebastien Hertz  { 6,    4,  M_IsObsolete,               "Method.IsObsolete" },
15046e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 6,    5,  M_VariableTableWithGeneric, "Method.VariableTableWithGeneric" },
1505872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* Field command set (8) */
1507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1508872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ObjectReference command set (9) */
1509f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 9,    1,  OR_ReferenceType,     "ObjectReference.ReferenceType" },
1510f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 9,    2,  OR_GetValues,         "ObjectReference.GetValues" },
1511f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 9,    3,  OR_SetValues,         "ObjectReference.SetValues" },
15127d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 9,    4,  nullptr,              "ObjectReference.UNUSED" },
1513f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 9,    5,  OR_MonitorInfo,       "ObjectReference.MonitorInfo" },
1514f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 9,    6,  OR_InvokeMethod,      "ObjectReference.InvokeMethod" },
15156e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 9,    7,  OR_DisableCollection, "ObjectReference.DisableCollection" },
1516f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 9,    8,  OR_EnableCollection,  "ObjectReference.EnableCollection" },
1517f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes  { 9,    9,  OR_IsCollected,       "ObjectReference.IsCollected" },
15180cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes  { 9,    10, OR_ReferringObjects,  "ObjectReference.ReferringObjects" },
1519872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1520872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* StringReference command set (10) */
15216e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 10,   1,  SR_Value,         "StringReference.Value" },
1522872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1523872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ThreadReference command set (11) */
1524734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   1,  TR_Name,                        "ThreadReference.Name" },
1525734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   2,  TR_Suspend,                     "ThreadReference.Suspend" },
1526734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   3,  TR_Resume,                      "ThreadReference.Resume" },
1527734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   4,  TR_Status,                      "ThreadReference.Status" },
1528734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   5,  TR_ThreadGroup,                 "ThreadReference.ThreadGroup" },
1529734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   6,  TR_Frames,                      "ThreadReference.Frames" },
1530734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   7,  TR_FrameCount,                  "ThreadReference.FrameCount" },
1531734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   8,  TR_OwnedMonitors,               "ThreadReference.OwnedMonitors" },
1532734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   9,  TR_CurrentContendedMonitor,     "ThreadReference.CurrentContendedMonitor" },
15337d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 11,   10, nullptr,                        "ThreadReference.Stop" },
1534734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   11, TR_Interrupt,                   "ThreadReference.Interrupt" },
1535734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   12, TR_DebugSuspendCount,           "ThreadReference.SuspendCount" },
1536734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes  { 11,   13, TR_OwnedMonitorsStackDepthInfo, "ThreadReference.OwnedMonitorsStackDepthInfo" },
15377d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 11,   14, nullptr,                        "ThreadReference.ForceEarlyReturn" },
1538872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1539872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ThreadGroupReference command set (12) */
15406e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 12,   1,  TGR_Name,         "ThreadGroupReference.Name" },
15416e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 12,   2,  TGR_Parent,       "ThreadGroupReference.Parent" },
15426e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 12,   3,  TGR_Children,     "ThreadGroupReference.Children" },
1543872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1544872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ArrayReference command set (13) */
15456e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 13,   1,  AR_Length,        "ArrayReference.Length" },
15466e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 13,   2,  AR_GetValues,     "ArrayReference.GetValues" },
15476e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 13,   3,  AR_SetValues,     "ArrayReference.SetValues" },
1548872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1549872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ClassLoaderReference command set (14) */
15506e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 14,   1,  CLR_VisibleClasses, "ClassLoaderReference.VisibleClasses" },
1551872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1552872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* EventRequest command set (15) */
15536e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 15,   1,  ER_Set,           "EventRequest.Set" },
15546e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 15,   2,  ER_Clear,         "EventRequest.Clear" },
15557d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 15,   3,  nullptr,          "EventRequest.ClearAllBreakpoints" },
1556872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1557872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* StackFrame command set (16) */
15586e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 16,   1,  SF_GetValues,     "StackFrame.GetValues" },
15596e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 16,   2,  SF_SetValues,     "StackFrame.SetValues" },
15606e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 16,   3,  SF_ThisObject,    "StackFrame.ThisObject" },
15617d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 16,   4,  nullptr,          "StackFrame.PopFrames" },
1562872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1563872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* ClassObjectReference command set (17) */
15646e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 17,   1,  COR_ReflectedType, "ClassObjectReference.ReflectedType" },
1565872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1566872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* Event command set (64) */
15677d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz  { 64, 100,  nullptr, "Event.Composite" },  // sent from VM to debugger, never received by VM
1568872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
15696e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes  { 199,  1,  DDM_Chunk,        "DDM.Chunk" },
1570872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes};
1571872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1572c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic const char* GetCommandName(Request* request) {
1573cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes  for (size_t i = 0; i < arraysize(gHandlers); ++i) {
15747d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz    if (gHandlers[i].cmdSet == request->GetCommandSet() &&
15757d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz        gHandlers[i].cmd == request->GetCommand()) {
1576cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes      return gHandlers[i].name;
1577a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes    }
1578a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes  }
1579a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes  return "?UNKNOWN?";
1580a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes}
1581a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes
1582c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic std::string DescribeCommand(Request* request) {
1583a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes  std::string result;
158464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  result += "REQUEST: ";
1585cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes  result += GetCommandName(request);
1586c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  result += StringPrintf(" (length=%zu id=0x%06x)", request->GetLength(), request->GetId());
1587a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes  return result;
1588a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes}
1589a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes
1590cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz// Returns true if the given command_set and command identify an "invoke" command.
1591cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzstatic bool IsInvokeCommand(uint8_t command_set, uint8_t command) {
1592cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (command_set == kJDWPClassTypeCmdSet) {
1593cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    return command == kJDWPClassTypeInvokeMethodCmd || command == kJDWPClassTypeNewInstanceCmd;
1594cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  } else if (command_set == kJDWPObjectReferenceCmdSet) {
1595cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    return command == kJDWPObjectReferenceInvokeCmd;
159670fa1a5497c057eecf336c60975fbca015f8aebdAlex Light  } else if (command_set == kJDWPInterfaceTypeCmdSet) {
159770fa1a5497c057eecf336c60975fbca015f8aebdAlex Light    return command == kJDWPInterfaceTypeInvokeMethodCmd;
1598cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  } else {
1599cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    return false;
1600cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  }
1601cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz}
1602cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
1603872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1604cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz * Process a request from the debugger. The skip_reply flag is set to true to indicate to the
1605cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz * caller the reply must not be sent to the debugger. This is used for invoke commands where the
1606cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz * reply is sent by the event thread after completing the invoke.
1607872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1608872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * On entry, the JDWP thread is in VMWAIT.
1609872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1610cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzsize_t JdwpState::ProcessRequest(Request* request, ExpandBuf* pReply, bool* skip_reply) {
1611872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpError result = ERR_NONE;
1612cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  *skip_reply = false;
1613872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1614c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (request->GetCommandSet() != kJDWPDdmCmdSet) {
1615872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /*
1616872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * Activity from a debugger, not merely ddms.  Mark us as having an
1617872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * active debugger session, and zero out the last-activity timestamp
1618872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * so waitForDebugger() doesn't return if we stall for a bit here.
1619872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     */
1620a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    Dbg::GoActive();
162137f3c968ecd04e77802fe17bb82dabc07de21ca1Ian Rogers    last_activity_time_ms_.StoreSequentiallyConsistent(0);
1622872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1623872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1624872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1625872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If a debugger event has fired in another thread, wait until the
16262bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz   * initiating thread has suspended itself before processing commands
1627872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * from the debugger.  Otherwise we (the JDWP thread) could be told to
1628872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * resume the thread before it has suspended.
1629872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   *
1630872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Note that we MUST clear the event token before waking the event
1631872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * thread up, or risk waiting for the thread to suspend after we've
1632872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * told it to resume.
1633872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
16342bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz  AcquireJdwpTokenForCommand();
1635400a3a9d332ee17e69b876cbbfb47d9e576fc4f2Sebastien Hertz
1636400a3a9d332ee17e69b876cbbfb47d9e576fc4f2Sebastien Hertz  /*
1637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Tell the VM that we're running and shouldn't be interrupted by GC.
1638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Do this after anything that can stall indefinitely.
1639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
164000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
1641f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  ScopedObjectAccess soa(self);
1642872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1643872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAddSpace(pReply, kJDWPHeaderLen);
1644872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1645a3c24aaf30fcce6c4393c923beeaad385f1257dbElliott Hughes  size_t i;
1646cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes  for (i = 0; i < arraysize(gHandlers); ++i) {
16477d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz    if (gHandlers[i].cmdSet == request->GetCommandSet() &&
16487d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz        gHandlers[i].cmd == request->GetCommand() &&
16497d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz        gHandlers[i].func != nullptr) {
1650cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes      VLOG(jdwp) << DescribeCommand(request);
1651cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes      result = (*gHandlers[i].func)(this, request, pReply);
16524b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes      if (result == ERR_NONE) {
1653c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        request->CheckConsumed();
16544b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes      }
16552c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz      self->AssertNoPendingException();
1656872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
1657872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1658872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1659cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes  if (i == arraysize(gHandlers)) {
1660cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes    LOG(ERROR) << "Command not implemented: " << DescribeCommand(request);
1661c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    LOG(ERROR) << HexDump(request->data(), request->size(), false, "");
1662872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    result = ERR_NOT_IMPLEMENTED;
1663872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1664872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1665cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  size_t replyLength = 0U;
1666cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  if (result == ERR_NONE && IsInvokeCommand(request->GetCommandSet(), request->GetCommand())) {
1667cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // We successfully request an invoke in the event thread. It will send the reply once the
1668cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    // invoke completes so we must not send it now.
1669cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    *skip_reply = true;
1670cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz  } else {
1671cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    /*
1672cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz     * Set up the reply header.
1673cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz     *
1674cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz     * If we encountered an error, only send the header back.
1675cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz     */
1676cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    uint8_t* replyBuf = expandBufGetBuffer(pReply);
1677cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    replyLength = (result == ERR_NONE) ? expandBufGetLength(pReply) : kJDWPHeaderLen;
1678cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    Set4BE(replyBuf + kJDWPHeaderSizeOffset, replyLength);
1679cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    Set4BE(replyBuf + kJDWPHeaderIdOffset, request->GetId());
1680cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    Set1(replyBuf + kJDWPHeaderFlagsOffset, kJDWPFlagReply);
1681cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    Set2BE(replyBuf + kJDWPHeaderErrorCodeOffset, result);
1682cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
1683cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    CHECK_GT(expandBufGetLength(pReply), 0U) << GetCommandName(request) << " " << request->GetId();
1684cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz
1685cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    size_t respLen = expandBufGetLength(pReply) - kJDWPHeaderLen;
1686cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    VLOG(jdwp) << "REPLY: " << GetCommandName(request) << " " << result << " (length=" << respLen << ")";
1687cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    if (false) {
1688cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz      VLOG(jdwp) << HexDump(expandBufGetBuffer(pReply) + kJDWPHeaderLen, respLen, false, "");
1689cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz    }
1690872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1691872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1692cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes  VLOG(jdwp) << "----------";
1693cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes
1694872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1695872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Update last-activity timestamp.  We really only need this during
1696872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * the initial setup.  Only update if this is a non-DDMS packet.
1697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1698c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  if (request->GetCommandSet() != kJDWPDdmCmdSet) {
169937f3c968ecd04e77802fe17bb82dabc07de21ca1Ian Rogers    last_activity_time_ms_.StoreSequentiallyConsistent(MilliTime());
1700872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1701872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
170243c8d729556844d1a74449a8a300c795d6a5406aSebastien Hertz  return replyLength;
1703872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1704872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1705872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace JDWP
1706872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1707872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace art
1708