/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "jdwp/jdwp.h" #include <inttypes.h> #include "base/stringprintf.h" #include "jdwp/jdwp_priv.h" namespace art { namespace JDWP { Request::Request(const uint8_t* bytes, uint32_t available) : p_(bytes) { byte_count_ = Read4BE(); end_ = bytes + byte_count_; CHECK_LE(byte_count_, available); id_ = Read4BE(); int8_t flags = Read1(); if ((flags & kJDWPFlagReply) != 0) { LOG(FATAL) << "reply?!"; } command_set_ = Read1(); command_ = Read1(); } Request::~Request() { } void Request::CheckConsumed() { if (p_ < end_) { CHECK(p_ == end_) << "read too few bytes: " << (end_ - p_); } else if (p_ > end_) { CHECK(p_ == end_) << "read too many bytes: " << (p_ - end_); } } std::string Request::ReadUtf8String() { uint32_t length = Read4BE(); std::string s; s.resize(length); memcpy(&s[0], p_, length); p_ += length; VLOG(jdwp) << " string \"" << s << "\""; return s; } // Helper function: read a variable-width value from the input buffer. uint64_t Request::ReadValue(size_t width) { uint64_t value = -1; switch (width) { case 1: value = Read1(); break; case 2: value = Read2BE(); break; case 4: value = Read4BE(); break; case 8: value = Read8BE(); break; default: LOG(FATAL) << width; break; } return value; } int32_t Request::ReadSigned32(const char* what) { int32_t value = static_cast<int32_t>(Read4BE()); VLOG(jdwp) << " " << what << " " << value; return value; } uint32_t Request::ReadUnsigned32(const char* what) { uint32_t value = Read4BE(); VLOG(jdwp) << " " << what << " " << value; return value; } FieldId Request::ReadFieldId() { FieldId id = Read4BE(); VLOG(jdwp) << " field id " << DescribeField(id); return id; } MethodId Request::ReadMethodId() { MethodId id = Read4BE(); VLOG(jdwp) << " method id " << DescribeMethod(id); return id; } ObjectId Request::ReadObjectId(const char* specific_kind) { ObjectId id = Read8BE(); VLOG(jdwp) << StringPrintf(" %s id %#" PRIx64, specific_kind, id); return id; } ObjectId Request::ReadArrayId() { return ReadObjectId("array"); } ObjectId Request::ReadObjectId() { return ReadObjectId("object"); } ObjectId Request::ReadThreadId() { return ReadObjectId("thread"); } ObjectId Request::ReadThreadGroupId() { return ReadObjectId("thread group"); } RefTypeId Request::ReadRefTypeId() { RefTypeId id = Read8BE(); VLOG(jdwp) << " ref type id " << DescribeRefTypeId(id); return id; } FrameId Request::ReadFrameId() { FrameId id = Read8BE(); VLOG(jdwp) << " frame id " << id; return id; } JdwpTag Request::ReadTag() { return ReadEnum1<JdwpTag>("tag"); } JdwpTypeTag Request::ReadTypeTag() { return ReadEnum1<JdwpTypeTag>("type tag"); } JdwpLocation Request::ReadLocation() { JdwpLocation location; memset(&location, 0, sizeof(location)); // Allows memcmp(3) later. location.type_tag = ReadTypeTag(); location.class_id = ReadObjectId("class"); location.method_id = ReadMethodId(); location.dex_pc = Read8BE(); VLOG(jdwp) << " location " << location; return location; } JdwpModKind Request::ReadModKind() { return ReadEnum1<JdwpModKind>("mod kind"); } uint8_t Request::Read1() { return *p_++; } uint16_t Request::Read2BE() { uint16_t result = p_[0] << 8 | p_[1]; p_ += 2; return result; } uint32_t Request::Read4BE() { uint32_t result = p_[0] << 24; result |= p_[1] << 16; result |= p_[2] << 8; result |= p_[3]; p_ += 4; return result; } uint64_t Request::Read8BE() { uint64_t high = Read4BE(); uint64_t low = Read4BE(); return (high << 32) | low; } } // namespace JDWP } // namespace art