Merge "Turn free functions that take a JdwpState* into member functions." into dalvik-dev
diff --git a/src/debugger.cc b/src/debugger.cc
index ef44816..f8b52bc 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -27,11 +27,7 @@
static bool gJdwpConfigured = false;
// Broken-down JDWP options. (Only valid if gJdwpConfigured is true.)
-static JDWP::JdwpTransportType gJdwpTransport;
-static bool gJdwpServer;
-static bool gJdwpSuspend;
-static std::string gJdwpHost;
-static int gJdwpPort;
+static JDWP::JdwpOptions gJdwpOptions;
// Runtime JDWP state.
static JDWP::JdwpState* gJdwpState = NULL;
@@ -58,27 +54,27 @@
static bool ParseJdwpOption(const std::string& name, const std::string& value) {
if (name == "transport") {
if (value == "dt_socket") {
- gJdwpTransport = JDWP::kJdwpTransportSocket;
+ gJdwpOptions.transport = JDWP::kJdwpTransportSocket;
} else if (value == "dt_android_adb") {
- gJdwpTransport = JDWP::kJdwpTransportAndroidAdb;
+ gJdwpOptions.transport = JDWP::kJdwpTransportAndroidAdb;
} else {
LOG(ERROR) << "JDWP transport not supported: " << value;
return false;
}
} else if (name == "server") {
if (value == "n") {
- gJdwpServer = false;
+ gJdwpOptions.server = false;
} else if (value == "y") {
- gJdwpServer = true;
+ gJdwpOptions.server = true;
} else {
LOG(ERROR) << "JDWP option 'server' must be 'y' or 'n'";
return false;
}
} else if (name == "suspend") {
if (value == "n") {
- gJdwpSuspend = false;
+ gJdwpOptions.suspend = false;
} else if (value == "y") {
- gJdwpSuspend = true;
+ gJdwpOptions.suspend = true;
} else {
LOG(ERROR) << "JDWP option 'suspend' must be 'y' or 'n'";
return false;
@@ -86,10 +82,10 @@
} else if (name == "address") {
/* this is either <port> or <host>:<port> */
std::string port_string;
- gJdwpHost.clear();
+ gJdwpOptions.host.clear();
std::string::size_type colon = value.find(':');
if (colon != std::string::npos) {
- gJdwpHost = value.substr(0, colon);
+ gJdwpOptions.host = value.substr(0, colon);
port_string = value.substr(colon + 1);
} else {
port_string = value;
@@ -104,7 +100,7 @@
LOG(ERROR) << "JDWP address has junk in port field: " << value;
return false;
}
- gJdwpPort = port;
+ gJdwpOptions.port = port;
} else if (name == "launch" || name == "onthrow" || name == "oncaught" || name == "timeout") {
/* valid but unsupported */
LOG(INFO) << "Ignoring JDWP option '" << name << "'='" << value << "'";
@@ -132,10 +128,10 @@
ParseJdwpOption(pairs[i].substr(0, equals), pairs[i].substr(equals + 1));
}
- if (gJdwpTransport == JDWP::kJdwpTransportUnknown) {
+ if (gJdwpOptions.transport == JDWP::kJdwpTransportUnknown) {
LOG(ERROR) << "Must specify JDWP transport: " << options;
}
- if (!gJdwpServer && (gJdwpHost.empty() || gJdwpPort == 0)) {
+ if (!gJdwpOptions.server && (gJdwpOptions.host.empty() || gJdwpOptions.port == 0)) {
LOG(ERROR) << "Must specify JDWP host and port when server=n: " << options;
return false;
}
@@ -145,35 +141,31 @@
}
void Dbg::StartJdwp() {
+ if (!gJdwpAllowed || !gJdwpConfigured) {
+ // No JDWP for you!
+ return;
+ }
+
// Init JDWP if the debugger is enabled. This may connect out to a
// debugger, passively listen for a debugger, or block waiting for a
// debugger.
- if (gJdwpAllowed && gJdwpConfigured) {
- JDWP::JdwpStartupParams params;
- params.host = gJdwpHost;
- params.transport = gJdwpTransport;
- params.server = gJdwpServer;
- params.suspend = gJdwpSuspend;
- params.port = gJdwpPort;
-
- gJdwpState = JDWP::JdwpStartup(¶ms);
- if (gJdwpState == NULL) {
- LOG(WARNING) << "debugger thread failed to initialize";
- }
+ gJdwpState = JDWP::JdwpState::Create(&gJdwpOptions);
+ if (gJdwpState == NULL) {
+ LOG(WARNING) << "debugger thread failed to initialize";
}
// If a debugger has already attached, send the "welcome" message.
// This may cause us to suspend all threads.
- if (JDWP::JdwpIsActive(gJdwpState)) {
+ if (gJdwpState->IsActive()) {
//ScopedThreadStateChange(Thread::Current(), Thread::kRunnable);
- if (!JDWP::PostVMStart(gJdwpState, gJdwpSuspend)) {
+ if (!gJdwpState->PostVMStart()) {
LOG(WARNING) << "failed to post 'start' message to debugger";
}
}
}
void Dbg::StopJdwp() {
- JDWP::JdwpShutdown(gJdwpState);
+ delete gJdwpState;
}
void Dbg::SetJdwpAllowed(bool allowed) {
@@ -600,7 +592,7 @@
if (gJdwpState == NULL) {
LOG(VERBOSE) << "Debugger thread not active, ignoring DDM send: " << type;
} else {
- JDWP::DdmSendChunkV(gJdwpState, type, iov, iovcnt);
+ gJdwpState->DdmSendChunkV(type, iov, iovcnt);
}
}
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index 8455ba5..cd2bfa7 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -20,6 +20,7 @@
#include "jdwp/jdwp_bits.h"
#include "jdwp/jdwp_constants.h"
#include "jdwp/jdwp_expand_buf.h"
+#include "../mutex.h" // TODO: fix our include path!
#include <pthread.h>
#include <stddef.h>
@@ -32,8 +33,6 @@
namespace JDWP {
-struct JdwpState; /* opaque */
-
/*
* Fundamental types.
*
@@ -65,7 +64,6 @@
static inline void expandBufAddRefTypeId(ExpandBuf* pReply, RefTypeId id) { expandBufAdd8BE(pReply, id); }
static inline void expandBufAddFrameId(ExpandBuf* pReply, FrameId id) { expandBufAdd8BE(pReply, id); }
-
/*
* Holds a JDWP "location".
*/
@@ -86,10 +84,7 @@
};
std::ostream& operator<<(std::ostream& os, const JdwpTransportType& rhs);
-/*
- * Holds collection of JDWP initialization parameters.
- */
-struct JdwpStartupParams {
+struct JdwpOptions {
JdwpTransportType transport;
bool server;
bool suspend;
@@ -97,121 +92,208 @@
short port;
};
-/*
- * Perform one-time initialization.
- *
- * Among other things, this binds to a port to listen for a connection from
- * the debugger.
- *
- * Returns a newly-allocated JdwpState struct on success, or NULL on failure.
- */
-JdwpState* JdwpStartup(const JdwpStartupParams* params);
+struct JdwpEvent;
+struct JdwpNetState;
+struct JdwpReqHeader;
+struct JdwpTransport;
/*
- * Shut everything down.
+ * State for JDWP functions.
*/
-void JdwpShutdown(JdwpState* state);
+struct JdwpState {
+ /*
+ * Perform one-time initialization.
+ *
+ * Among other things, this binds to a port to listen for a connection from
+ * the debugger.
+ *
+ * Returns a newly-allocated JdwpState struct on success, or NULL on failure.
+ */
+ static JdwpState* Create(const JdwpOptions* options);
-/*
- * Returns "true" if a debugger or DDM is connected.
- */
-bool JdwpIsActive(JdwpState* state);
+ ~JdwpState();
-/*
- * Return the debugger thread's handle, or 0 if the debugger thread isn't
- * running.
- */
-pthread_t GetDebugThread(JdwpState* state);
+ /*
+ * Returns "true" if a debugger or DDM is connected.
+ */
+ bool IsActive();
-/*
- * Get time, in milliseconds, since the last debugger activity.
- */
-int64_t LastDebuggerActivity(JdwpState* state);
+ /*
+ * Return the debugger thread's handle, or 0 if the debugger thread isn't
+ * running.
+ */
+ pthread_t GetDebugThread();
-/*
- * When we hit a debugger event that requires suspension, it's important
- * that we wait for the thread to suspend itself before processing any
- * additional requests. (Otherwise, if the debugger immediately sends a
- * "resume thread" command, the resume might arrive before the thread has
- * suspended itself.)
- *
- * The thread should call the "set" function before sending the event to
- * the debugger. The main JDWP handler loop calls "get" before processing
- * an event, and will wait for thread suspension if it's set. Once the
- * thread has suspended itself, the JDWP handler calls "clear" and
- * continues processing the current event. This works in the suspend-all
- * case because the event thread doesn't suspend itself until everything
- * else has suspended.
- *
- * It's possible that multiple threads could encounter thread-suspending
- * events at the same time, so we grab a mutex in the "set" call, and
- * release it in the "clear" call.
- */
-//ObjectId GetWaitForEventThread(JdwpState* state);
-void SetWaitForEventThread(JdwpState* state, ObjectId threadId);
-void ClearWaitForEventThread(JdwpState* state);
+ /*
+ * Get time, in milliseconds, since the last debugger activity.
+ */
+ int64_t LastDebuggerActivity();
-/*
- * These notify the debug code that something interesting has happened. This
- * could be a thread starting or ending, an exception, or an opportunity
- * for a breakpoint. These calls do not mean that an event the debugger
- * is interested has happened, just that something has happened that the
- * debugger *might* be interested in.
- *
- * The item of interest may trigger multiple events, some or all of which
- * are grouped together in a single response.
- *
- * The event may cause the current thread or all threads (except the
- * JDWP support thread) to be suspended.
- */
+ /*
+ * When we hit a debugger event that requires suspension, it's important
+ * that we wait for the thread to suspend itself before processing any
+ * additional requests. (Otherwise, if the debugger immediately sends a
+ * "resume thread" command, the resume might arrive before the thread has
+ * suspended itself.)
+ *
+ * The thread should call the "set" function before sending the event to
+ * the debugger. The main JDWP handler loop calls "get" before processing
+ * an event, and will wait for thread suspension if it's set. Once the
+ * thread has suspended itself, the JDWP handler calls "clear" and
+ * continues processing the current event. This works in the suspend-all
+ * case because the event thread doesn't suspend itself until everything
+ * else has suspended.
+ *
+ * It's possible that multiple threads could encounter thread-suspending
+ * events at the same time, so we grab a mutex in the "set" call, and
+ * release it in the "clear" call.
+ */
+ //ObjectId GetWaitForEventThread();
+ void SetWaitForEventThread(ObjectId threadId);
+ void ClearWaitForEventThread();
-/*
- * The VM has finished initializing. Only called when the debugger is
- * connected at the time initialization completes.
- */
-bool PostVMStart(JdwpState* state, bool suspend);
+ /*
+ * These notify the debug code that something interesting has happened. This
+ * could be a thread starting or ending, an exception, or an opportunity
+ * for a breakpoint. These calls do not mean that an event the debugger
+ * is interested has happened, just that something has happened that the
+ * debugger *might* be interested in.
+ *
+ * The item of interest may trigger multiple events, some or all of which
+ * are grouped together in a single response.
+ *
+ * The event may cause the current thread or all threads (except the
+ * JDWP support thread) to be suspended.
+ */
-/*
- * A location of interest has been reached. This is used for breakpoints,
- * single-stepping, and method entry/exit. (JDWP requires that these four
- * events are grouped together in a single response.)
- *
- * In some cases "*pLoc" will just have a method and class name, e.g. when
- * issuing a MethodEntry on a native method.
- *
- * "eventFlags" indicates the types of events that have occurred.
- */
-bool PostLocationEvent(JdwpState* state, const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags);
+ /*
+ * The VM has finished initializing. Only called when the debugger is
+ * connected at the time initialization completes.
+ */
+ bool PostVMStart();
-/*
- * An exception has been thrown.
- *
- * Pass in a zeroed-out "*pCatchLoc" if the exception wasn't caught.
- */
-bool PostException(JdwpState* state, const JdwpLocation* pThrowLoc,
- ObjectId excepId, RefTypeId excepClassId, const JdwpLocation* pCatchLoc,
- ObjectId thisPtr);
+ /*
+ * A location of interest has been reached. This is used for breakpoints,
+ * single-stepping, and method entry/exit. (JDWP requires that these four
+ * events are grouped together in a single response.)
+ *
+ * In some cases "*pLoc" will just have a method and class name, e.g. when
+ * issuing a MethodEntry on a native method.
+ *
+ * "eventFlags" indicates the types of events that have occurred.
+ */
+ bool PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags);
-/*
- * A thread has started or stopped.
- */
-bool PostThreadChange(JdwpState* state, ObjectId threadId, bool start);
+ /*
+ * An exception has been thrown.
+ *
+ * Pass in a zeroed-out "*pCatchLoc" if the exception wasn't caught.
+ */
+ bool PostException(const JdwpLocation* pThrowLoc, ObjectId excepId, RefTypeId excepClassId, const JdwpLocation* pCatchLoc, ObjectId thisPtr);
-/*
- * Class has been prepared.
- */
-bool PostClassPrepare(JdwpState* state, int tag, RefTypeId refTypeId,
- const char* signature, int status);
+ /*
+ * A thread has started or stopped.
+ */
+ bool PostThreadChange(ObjectId threadId, bool start);
-/*
- * The VM is about to stop.
- */
-bool PostVMDeath(JdwpState* state);
+ /*
+ * Class has been prepared.
+ */
+ bool PostClassPrepare(int tag, RefTypeId refTypeId, const char* signature, int status);
-/*
- * Send up a chunk of DDM data.
- */
-void DdmSendChunkV(JdwpState* state, int type, const iovec* iov, int iovcnt);
+ /*
+ * The VM is about to stop.
+ */
+ bool PostVMDeath();
+
+ /*
+ * Send up a chunk of DDM data.
+ */
+ void DdmSendChunkV(int type, const iovec* iov, int iovcnt);
+
+ /*
+ * Process a request from the debugger.
+ *
+ * "buf" points past the header, to the content of the message. "dataLen"
+ * can therefore be zero.
+ */
+ void ProcessRequest(const JdwpReqHeader* pHeader, const uint8_t* buf, int dataLen, ExpandBuf* pReply);
+
+ /*
+ * Send an event, formatted into "pReq", to the debugger.
+ *
+ * (Messages are sent asynchronously, and do not receive a reply.)
+ */
+ bool SendRequest(ExpandBuf* pReq);
+
+ void ResetState();
+
+ /* atomic ops to get next serial number */
+ uint32_t NextRequestSerial();
+ uint32_t NextEventSerial();
+
+ void Run();
+
+ private:
+ JdwpState(const JdwpOptions* options);
+ bool IsConnected();
+
+public: // TODO: fix privacy
+ const JdwpOptions* options_;
+private:
+
+ /* wait for creation of the JDWP thread */
+ Mutex thread_start_lock_;
+ ConditionVariable thread_start_cond_;
+
+ volatile int32_t debug_thread_started_;
+ pthread_t debugThreadHandle;
+public: // TODO: fix privacy
+ ObjectId debugThreadId;
+private:
+ bool run;
+
+ const JdwpTransport* transport;
+public: // TODO: fix privacy
+ JdwpNetState* netState;
+private:
+
+ /* for wait-for-debugger */
+ Mutex attach_lock_;
+ ConditionVariable attach_cond_;
+
+ /* time of last debugger activity, in milliseconds */
+ int64_t lastActivityWhen;
+
+ /* global counters and a mutex to protect them */
+ uint32_t requestSerial;
+ uint32_t eventSerial;
+ Mutex serial_lock_;
+
+ /*
+ * Events requested by the debugger (breakpoints, class prep, etc).
+ */
+public: // TODO: fix privacy
+ int numEvents; /* #of elements in eventList */
+ JdwpEvent* eventList; /* linked list of events */
+ Mutex event_lock_; /* guards numEvents/eventList */
+private:
+
+ /*
+ * Synchronize suspension of event thread (to avoid receiving "resume"
+ * events before the thread has finished suspending itself).
+ */
+ Mutex event_thread_lock_;
+ ConditionVariable event_thread_cond_;
+ ObjectId eventThreadId;
+
+ /*
+ * DDM support.
+ */
+public: // TODO: fix privacy
+ bool ddmActive;
+private:
+};
} // namespace JDWP
diff --git a/src/jdwp/jdwp_adb.cc b/src/jdwp/jdwp_adb.cc
index 3a89f34..bd5e6e6 100644
--- a/src/jdwp/jdwp_adb.cc
+++ b/src/jdwp/jdwp_adb.cc
@@ -118,8 +118,8 @@
* runs in the main thread, before the JDWP thread starts, so it shouldn't
* do anything that might block forever.
*/
-static bool startup(JdwpState* state, const JdwpStartupParams* pParams) {
- JdwpNetState* netState;
+static bool startup(JdwpState* state, const JdwpOptions*) {
+ JdwpNetState* netState;
LOG(VERBOSE) << "ADB transport startup";
@@ -445,7 +445,7 @@
hdr.id = id;
hdr.cmdSet = cmdSet;
hdr.cmd = cmd;
- ProcessRequest(state, &hdr, buf, dataLen, pReply);
+ state->ProcessRequest(&hdr, buf, dataLen, pReply);
if (expandBufGetLength(pReply) > 0) {
ssize_t cc = netState->writePacket(pReply);
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 3a2d73e..835b182 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -120,24 +120,6 @@
};
/*
- * Get the next "request" serial number. We use this when sending
- * packets to the debugger.
- */
-uint32_t NextRequestSerial(JdwpState* state) {
- MutexLock mu(state->serial_lock_);
- return state->requestSerial++;
-}
-
-/*
- * Get the next "event" serial number. We use this in the response to
- * message type EventRequest.Set.
- */
-uint32_t NextEventSerial(JdwpState* state) {
- MutexLock mu(state->serial_lock_);
- return state->eventSerial++;
-}
-
-/*
* Lock the "event" mutex, which guards the list of registered events.
*/
static void lockEventMutex(JdwpState* state) {
@@ -584,7 +566,7 @@
}
/* grab this before posting/suspending again */
- SetWaitForEventThread(state, Dbg::GetThreadSelfId());
+ state->SetWaitForEventThread(Dbg::GetThreadSelfId());
/* leave pReq->invokeNeeded raised so we can check reentrancy */
LOG(VERBOSE) << "invoking method...";
@@ -623,47 +605,47 @@
* This could go to sleep waiting for another thread, so it's important
* that the thread be marked as VMWAIT before calling here.
*/
-void SetWaitForEventThread(JdwpState* state, ObjectId threadId) {
+void JdwpState::SetWaitForEventThread(ObjectId threadId) {
bool waited = false;
/* this is held for very brief periods; contention is unlikely */
- MutexLock mu(state->event_thread_lock_);
+ MutexLock mu(event_thread_lock_);
/*
* If another thread is already doing stuff, wait for it. This can
* go to sleep indefinitely.
*/
- while (state->eventThreadId != 0) {
- LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", state->eventThreadId, threadId);
+ while (eventThreadId != 0) {
+ LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", eventThreadId, threadId);
waited = true;
- state->event_thread_cond_.Wait(state->event_thread_lock_);
+ event_thread_cond_.Wait(event_thread_lock_);
}
if (waited || threadId != 0) {
LOG(VERBOSE) << StringPrintf("event token grabbed (0x%llx)", threadId);
}
if (threadId != 0) {
- state->eventThreadId = threadId;
+ eventThreadId = threadId;
}
}
/*
* Clear the threadId and signal anybody waiting.
*/
-void ClearWaitForEventThread(JdwpState* state) {
+void JdwpState::ClearWaitForEventThread() {
/*
* Grab the mutex. Don't try to go in/out of VMWAIT mode, as this
* function is called by dvmSuspendSelf(), and the transition back
* to RUNNING would confuse it.
*/
- MutexLock mu(state->event_thread_lock_);
+ MutexLock mu(event_thread_lock_);
- CHECK_NE(state->eventThreadId, 0U);
- LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", state->eventThreadId);
+ CHECK_NE(eventThreadId, 0U);
+ LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", eventThreadId);
- state->eventThreadId = 0;
+ eventThreadId = 0;
- state->event_thread_cond_.Signal();
+ event_thread_cond_.Signal();
}
@@ -686,12 +668,12 @@
uint8_t* buf = expandBufGetBuffer(pReq);
set4BE(buf, expandBufGetLength(pReq));
- set4BE(buf+4, NextRequestSerial(state));
+ set4BE(buf+4, state->NextRequestSerial());
set1(buf+8, 0); /* flags */
set1(buf+9, kJdwpEventCommandSet);
set1(buf+10, kJdwpCompositeCommand);
- SendRequest(state, pReq);
+ state->SendRequest(pReq);
expandBufFree(pReq);
}
@@ -705,18 +687,18 @@
* any application code has been executed". The thread ID in the message
* must be for the main thread.
*/
-bool PostVMStart(JdwpState* state, bool suspend) {
+bool JdwpState::PostVMStart() {
JdwpSuspendPolicy suspendPolicy;
ObjectId threadId = Dbg::GetThreadSelfId();
- if (suspend) {
+ if (options_->suspend) {
suspendPolicy = SP_ALL;
} else {
suspendPolicy = SP_NONE;
}
/* probably don't need this here */
- lockEventMutex(state);
+ lockEventMutex(this);
ExpandBuf* pReq = NULL;
if (true) {
@@ -732,19 +714,19 @@
expandBufAdd8BE(pReq, threadId);
}
- unlockEventMutex(state);
+ unlockEventMutex(this);
/* send request and possibly suspend ourselves */
if (pReq != NULL) {
- int oldStatus = Dbg::ThreadWaiting();
+ int old_state = Dbg::ThreadWaiting();
if (suspendPolicy != SP_NONE) {
- SetWaitForEventThread(state, threadId);
+ SetWaitForEventThread(threadId);
}
- eventFinish(state, pReq);
+ eventFinish(this, pReq);
- suspendByPolicy(state, suspendPolicy);
- Dbg::ThreadContinuing(oldStatus);
+ suspendByPolicy(this, suspendPolicy);
+ Dbg::ThreadContinuing(old_state);
}
return true;
@@ -861,15 +843,15 @@
/* send request and possibly suspend ourselves */
if (pReq != NULL) {
- int oldStatus = Dbg::ThreadWaiting();
+ int old_state = Dbg::ThreadWaiting();
if (suspendPolicy != SP_NONE) {
- SetWaitForEventThread(state, basket.threadId);
+ state->SetWaitForEventThread(basket.threadId);
}
eventFinish(state, pReq);
suspendByPolicy(state, suspendPolicy);
- Dbg::ThreadContinuing(oldStatus);
+ Dbg::ThreadContinuing(old_state);
}
free(nameAlloc);
@@ -934,14 +916,14 @@
/* send request and possibly suspend ourselves */
if (pReq != NULL) {
- int oldStatus = Dbg::ThreadWaiting();
+ int old_state = Dbg::ThreadWaiting();
if (suspendPolicy != SP_NONE) {
- SetWaitForEventThread(state, basket.threadId);
+ state->SetWaitForEventThread(basket.threadId);
}
eventFinish(state, pReq);
suspendByPolicy(state, suspendPolicy);
- Dbg::ThreadContinuing(oldStatus);
+ Dbg::ThreadContinuing(old_state);
}
return matchCount != 0;
@@ -952,7 +934,7 @@
*
* Skips the usual "event token" stuff.
*/
-bool PostVMDeath(JdwpState* state) {
+bool JdwpState::PostVMDeath() {
LOG(VERBOSE) << "EVENT: " << EK_VM_DEATH;
ExpandBuf* pReq = eventPrep();
@@ -961,7 +943,7 @@
expandBufAdd1(pReq, EK_VM_DEATH);
expandBufAdd4BE(pReq, 0);
- eventFinish(state, pReq);
+ eventFinish(this, pReq);
return true;
}
@@ -1054,15 +1036,15 @@
/* send request and possibly suspend ourselves */
if (pReq != NULL) {
- int oldStatus = Dbg::ThreadWaiting();
+ int old_state = Dbg::ThreadWaiting();
if (suspendPolicy != SP_NONE) {
- SetWaitForEventThread(state, basket.threadId);
+ state->SetWaitForEventThread(basket.threadId);
}
eventFinish(state, pReq);
suspendByPolicy(state, suspendPolicy);
- Dbg::ThreadContinuing(oldStatus);
+ Dbg::ThreadContinuing(old_state);
}
free(nameAlloc);
@@ -1143,24 +1125,20 @@
/* send request and possibly suspend ourselves */
if (pReq != NULL) {
- int oldStatus = Dbg::ThreadWaiting();
+ int old_state = Dbg::ThreadWaiting();
if (suspendPolicy != SP_NONE) {
- SetWaitForEventThread(state, basket.threadId);
+ state->SetWaitForEventThread(basket.threadId);
}
eventFinish(state, pReq);
suspendByPolicy(state, suspendPolicy);
- Dbg::ThreadContinuing(oldStatus);
+ Dbg::ThreadContinuing(old_state);
}
free(nameAlloc);
return matchCount != 0;
}
-bool SendBufferedRequest(JdwpState* state, const iovec* iov, int iovcnt) {
- return (*state->transport->sendBufferedRequest)(state, iov, iovcnt);
-}
-
/*
* Send up a chunk of DDM data.
*
@@ -1168,7 +1146,7 @@
* other debugger traffic, and can't suspend the VM, so we skip all of
* the fun event token gymnastics.
*/
-void DdmSendChunkV(JdwpState* state, int type, const iovec* iov, int iovcnt) {
+void JdwpState::DdmSendChunkV(int type, const iovec* iov, int iovcnt) {
uint8_t header[kJDWPHeaderLen + 8];
size_t dataLen = 0;
@@ -1188,7 +1166,7 @@
/* form the header (JDWP plus DDMS) */
set4BE(header, sizeof(header) + dataLen);
- set4BE(header+4, NextRequestSerial(state));
+ set4BE(header+4, NextRequestSerial());
set1(header+8, 0); /* flags */
set1(header+9, kJDWPDdmCmdSet);
set1(header+10, kJDWPDdmCmd);
@@ -1201,9 +1179,9 @@
/*
* Make sure we're in VMWAIT in case the write blocks.
*/
- int oldStatus = Dbg::ThreadWaiting();
- SendBufferedRequest(state, wrapiov, iovcnt+1);
- Dbg::ThreadContinuing(oldStatus);
+ int old_state = Dbg::ThreadWaiting();
+ (*transport->sendBufferedRequest)(this, wrapiov, iovcnt + 1);
+ Dbg::ThreadContinuing(old_state);
}
} // namespace JDWP
diff --git a/src/jdwp/jdwp_event.h b/src/jdwp/jdwp_event.h
index 2b957fb..81a1eba 100644
--- a/src/jdwp/jdwp_event.h
+++ b/src/jdwp/jdwp_event.h
@@ -123,13 +123,6 @@
*/
void UnregisterAll(JdwpState* state);
-/*
- * Send an event, formatted into "pReq", to the debugger.
- *
- * (Messages are sent asynchronously, and do not receive a reply.)
- */
-bool SendRequest(JdwpState* state, ExpandBuf* pReq);
-
} // namespace JDWP
} // namespace art
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 8fe3c3f..5e566ae 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -1412,7 +1412,7 @@
/*
* We reply with an integer "requestID".
*/
- uint32_t requestId = NextEventSerial(state);
+ uint32_t requestId = state->NextEventSerial();
expandBufAdd4BE(pReply, requestId);
pEvent->requestId = requestId;
@@ -1722,7 +1722,7 @@
*
* On entry, the JDWP thread is in VMWAIT.
*/
-void ProcessRequest(JdwpState* state, const JdwpReqHeader* pHeader, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
+void JdwpState::ProcessRequest(const JdwpReqHeader* pHeader, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
JdwpError result = ERR_NONE;
int i, respLen;
@@ -1733,7 +1733,7 @@
* so waitForDebugger() doesn't return if we stall for a bit here.
*/
Dbg::Active();
- QuasiAtomicSwap64(0, &state->lastActivityWhen);
+ QuasiAtomicSwap64(0, &lastActivityWhen);
}
/*
@@ -1752,7 +1752,7 @@
* thread up, or risk waiting for the thread to suspend after we've
* told it to resume.
*/
- SetWaitForEventThread(state, 0);
+ SetWaitForEventThread(0);
/*
* Tell the VM that we're running and shouldn't be interrupted by GC.
@@ -1765,7 +1765,7 @@
for (i = 0; i < (int) arraysize(gHandlerMap); i++) {
if (gHandlerMap[i].cmdSet == pHeader->cmdSet && gHandlerMap[i].cmd == pHeader->cmd) {
LOG(VERBOSE) << StringPrintf("REQ: %s (cmd=%d/%d dataLen=%d id=0x%06x)", gHandlerMap[i].descr, pHeader->cmdSet, pHeader->cmd, dataLen, pHeader->id);
- result = (*gHandlerMap[i].func)(state, buf, dataLen, pReply);
+ result = (*gHandlerMap[i].func)(this, buf, dataLen, pReply);
break;
}
}
@@ -1806,7 +1806,7 @@
* the initial setup. Only update if this is a non-DDMS packet.
*/
if (pHeader->cmdSet != kJDWPDdmCmdSet) {
- QuasiAtomicSwap64(GetNowMsec(), &state->lastActivityWhen);
+ QuasiAtomicSwap64(GetNowMsec(), &lastActivityWhen);
}
/* tell the VM that GC is okay again */
diff --git a/src/jdwp/jdwp_handler.h b/src/jdwp/jdwp_handler.h
index 6fa75d7..0159701 100644
--- a/src/jdwp/jdwp_handler.h
+++ b/src/jdwp/jdwp_handler.h
@@ -35,15 +35,6 @@
uint8_t cmd;
};
-/*
- * Process a request from the debugger.
- *
- * "buf" points past the header, to the content of the message. "dataLen"
- * can therefore be zero.
- */
-void ProcessRequest(JdwpState* state, const JdwpReqHeader* pHeader,
- const uint8_t* buf, int dataLen, ExpandBuf* pReply);
-
/* helper function */
void AddLocation(ExpandBuf* pReply, const JdwpLocation* pLoc);
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index c9dac64..31337fd 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -33,7 +33,7 @@
namespace JDWP {
-static void* jdwpThreadStart(void* arg);
+static void* StartJdwpThread(void* arg);
/*
* JdwpNetStateBase class implementation
@@ -58,56 +58,35 @@
return writev(clientSock, iov, iovcnt);
}
-bool NetStartup(JdwpState* state, const JdwpStartupParams* pParams) {
- return (*state->transport->startup)(state, pParams);
+bool JdwpState::IsConnected() {
+ return (*transport->isConnected)(this);
}
-bool AcceptConnection(JdwpState* state) {
- return (*state->transport->accept)(state);
+bool JdwpState::SendRequest(ExpandBuf* pReq) {
+ return (*transport->sendRequest)(this, pReq);
}
-bool EstablishConnection(JdwpState* state) {
- return (*state->transport->establish)(state);
+/*
+ * Get the next "request" serial number. We use this when sending
+ * packets to the debugger.
+ */
+uint32_t JdwpState::NextRequestSerial() {
+ MutexLock mu(serial_lock_);
+ return requestSerial++;
}
-void CloseConnection(JdwpState* state) {
- (*state->transport->close)(state);
+/*
+ * Get the next "event" serial number. We use this in the response to
+ * message type EventRequest.Set.
+ */
+uint32_t JdwpState::NextEventSerial() {
+ MutexLock mu(serial_lock_);
+ return eventSerial++;
}
-void NetShutdown(JdwpState* state) {
- (*state->transport->shutdown)(state);
-}
-
-void NetFree(JdwpState* state) {
- (*state->transport->free)(state);
-}
-
-bool IsTransportDefined(JdwpState* state) {
- return state != NULL && state->transport != NULL;
-}
-
-bool JdwpIsConnected(JdwpState* state) {
- return state != NULL && (*state->transport->isConnected)(state);
-}
-
-bool AwaitingHandshake(JdwpState* state) {
- return (*state->transport->awaitingHandshake)(state);
-}
-
-bool ProcessIncoming(JdwpState* state) {
- return (*state->transport->processIncoming)(state);
-}
-
-bool SendRequest(JdwpState* state, ExpandBuf* pReq) {
- return (*state->transport->sendRequest)(state, pReq);
-}
-
-static void CreateJdwpThread(JdwpState* state) {
- CHECK_PTHREAD_CALL(pthread_create, (&state->debugThreadHandle, NULL, jdwpThreadStart, state), "JDWP thread");
-}
-
-JdwpState::JdwpState()
- : thread_start_lock_("JDWP thread start lock"),
+JdwpState::JdwpState(const JdwpOptions* options)
+ : options_(options),
+ thread_start_lock_("JDWP thread start lock"),
thread_start_cond_("JDWP thread start condition variable"),
debug_thread_started_(false),
debugThreadId(0),
@@ -135,15 +114,12 @@
* Does not return until JDWP thread is running, but may return before
* the thread is accepting network connections.
*/
-JdwpState* JdwpStartup(const JdwpStartupParams* pParams) {
+JdwpState* JdwpState::Create(const JdwpOptions* options) {
/* comment this out when debugging JDWP itself */
//android_setMinPriority(LOG_TAG, ANDROID_LOG_DEBUG);
- JdwpState* state = new JdwpState;
-
- state->params = *pParams;
-
- switch (pParams->transport) {
+ JdwpState* state = new JdwpState(options);
+ switch (options->transport) {
case kJdwpTransportSocket:
// LOGD("prepping for JDWP over TCP");
state->transport = SocketTransport();
@@ -155,10 +131,10 @@
break;
#endif
default:
- LOG(FATAL) << "Unknown transport: " << pParams->transport;
+ LOG(FATAL) << "Unknown transport: " << options->transport;
}
- if (!NetStartup(state, pParams)) {
+ if (!(*state->transport->startup)(state, options)) {
goto fail;
}
@@ -167,7 +143,7 @@
* won't signal the cond var before we're waiting.
*/
state->thread_start_lock_.Lock();
- if (pParams->suspend) {
+ if (options->suspend) {
state->attach_lock_.Lock();
}
@@ -175,7 +151,7 @@
* We have bound to a port, or are trying to connect outbound to a
* debugger. Create the JDWP thread and let it continue the mission.
*/
- CreateJdwpThread(state);
+ CHECK_PTHREAD_CALL(pthread_create, (&state->debugThreadHandle, NULL, StartJdwpThread, state), "JDWP thread");
/*
* Wait until the thread finishes basic initialization.
@@ -192,7 +168,7 @@
* times out (for timeout=xxx), so we have to check to see what happened
* when we wake up.
*/
- if (pParams->suspend) {
+ if (options->suspend) {
{
ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
@@ -200,7 +176,7 @@
state->attach_lock_.Unlock();
}
- if (!JdwpIsActive(state)) {
+ if (!state->IsActive()) {
LOG(ERROR) << "JDWP connection failed";
goto fail;
}
@@ -217,7 +193,7 @@
return state;
fail:
- JdwpShutdown(state); // frees state
+ delete state; // frees state
return NULL;
}
@@ -228,17 +204,17 @@
*
* This includes freeing up the debugger event list.
*/
-void ResetState(JdwpState* state) {
+void JdwpState::ResetState() {
/* could reset the serial numbers, but no need to */
- UnregisterAll(state);
- CHECK(state->eventList == NULL);
+ UnregisterAll(this);
+ CHECK(eventList == NULL);
/*
* Should not have one of these in progress. If the debugger went away
* mid-request, though, we could see this.
*/
- if (state->eventThreadId != 0) {
+ if (eventThreadId != 0) {
LOG(WARNING) << "resetting state while event in progress";
DCHECK(false);
}
@@ -247,72 +223,71 @@
/*
* Tell the JDWP thread to shut down. Frees "state".
*/
-void JdwpShutdown(JdwpState* state) {
- void* threadReturn;
-
- if (state == NULL) {
- return;
- }
-
- if (IsTransportDefined(state)) {
- if (JdwpIsConnected(state)) {
- PostVMDeath(state);
+JdwpState::~JdwpState() {
+ if (transport != NULL) {
+ if (IsConnected()) {
+ PostVMDeath();
}
/*
* Close down the network to inspire the thread to halt.
*/
LOG(DEBUG) << "JDWP shutting down net...";
- NetShutdown(state);
+ (*transport->shutdown)(this);
- if (state->debug_thread_started_) {
- state->run = false;
- if (pthread_join(state->debugThreadHandle, &threadReturn) != 0) {
+ if (debug_thread_started_) {
+ run = false;
+ void* threadReturn;
+ if (pthread_join(debugThreadHandle, &threadReturn) != 0) {
LOG(WARNING) << "JDWP thread join failed";
}
}
LOG(DEBUG) << "JDWP freeing netstate...";
- NetFree(state);
- state->netState = NULL;
+ (*transport->free)(this);
+ netState = NULL;
}
- CHECK(state->netState == NULL);
+ CHECK(netState == NULL);
- ResetState(state);
- free(state);
+ ResetState();
}
/*
* Are we talking to a debugger?
*/
-bool JdwpIsActive(JdwpState* state) {
- return JdwpIsConnected(state);
+bool JdwpState::IsActive() {
+ return IsConnected();
}
/*
* Entry point for JDWP thread. The thread was created through the VM
* mechanisms, so there is a java/lang/Thread associated with us.
*/
-static void* jdwpThreadStart(void* arg) {
+static void* StartJdwpThread(void* arg) {
JdwpState* state = reinterpret_cast<JdwpState*>(arg);
CHECK(state != NULL);
+ state->Run();
+ return NULL;
+}
+
+void JdwpState::Run() {
Runtime* runtime = Runtime::Current();
runtime->AttachCurrentThread("JDWP", true);
LOG(VERBOSE) << "JDWP: thread running";
/*
- * Finish initializing "state", then notify the creating thread that
+ * Finish initializing, then notify the creating thread that
* we're running.
*/
- state->debugThreadHandle = pthread_self();
- state->run = true;
- android_atomic_release_store(true, &state->debug_thread_started_);
+ debugThreadHandle = pthread_self();
+ run = true;
+ android_atomic_release_store(true, &debug_thread_started_);
- state->thread_start_lock_.Lock();
- state->thread_start_cond_.Broadcast();
- state->thread_start_lock_.Unlock();
+ thread_start_lock_.Lock();
+ thread_start_cond_.Broadcast();
+ thread_start_lock_.Unlock();
/* set the thread state to VMWAIT so GCs don't wait for us */
Dbg::ThreadWaiting();
@@ -325,15 +300,13 @@
* We broadcast a notification when a debugger attaches, after we
* successfully process the handshake.
*/
- while (state->run) {
- bool first;
-
- if (state->params.server) {
+ while (run) {
+ if (options_->server) {
/*
* Block forever, waiting for a connection. To support the
* "timeout=xxx" option we'll need to tweak this.
*/
- if (!AcceptConnection(state)) {
+ if (!(*transport->accept)(this)) {
break;
}
} else {
@@ -343,10 +316,10 @@
* have a timeout if the handshake reply isn't received in a
* reasonable amount of time.
*/
- if (!EstablishConnection(state)) {
+ if (!(*transport->establish)(this)) {
/* wake anybody who was waiting for us to succeed */
- MutexLock mu(state->attach_lock_);
- state->attach_cond_.Broadcast();
+ MutexLock mu(attach_lock_);
+ attach_cond_.Broadcast();
break;
}
}
@@ -355,7 +328,7 @@
Dbg::Connected();
/* process requests until the debugger drops */
- first = true;
+ bool first = true;
while (true) {
// sanity check -- shouldn't happen?
if (Thread::Current()->GetState() != Thread::kVmWait) {
@@ -363,28 +336,28 @@
Dbg::ThreadWaiting();
}
- if (!ProcessIncoming(state)) {
+ if (!(*transport->processIncoming)(this)) {
/* blocking read */
break;
}
- if (first && !AwaitingHandshake(state)) {
+ if (first && !(*transport->awaitingHandshake)(this)) {
/* handshake worked, tell the interpreter that we're active */
first = false;
/* set thread ID; requires object registry to be active */
- state->debugThreadId = Dbg::GetThreadSelfId();
+ debugThreadId = Dbg::GetThreadSelfId();
/* wake anybody who's waiting for us */
- MutexLock mu(state->attach_lock_);
- state->attach_cond_.Broadcast();
+ MutexLock mu(attach_lock_);
+ attach_cond_.Broadcast();
}
}
- CloseConnection(state);
+ (*transport->close)(this);
- if (state->ddmActive) {
- state->ddmActive = false;
+ if (ddmActive) {
+ ddmActive = false;
/* broadcast the disconnect; must be in RUNNING state */
Dbg::ThreadRunning();
@@ -393,7 +366,7 @@
}
/* release session state, e.g. remove breakpoint instructions */
- ResetState(state);
+ ResetState();
/* tell the interpreter that the debugger is no longer around */
Dbg::Disconnected();
@@ -402,8 +375,8 @@
Dbg::UndoDebuggerSuspensions();
/* if we connected out, this was a one-shot deal */
- if (!state->params.server) {
- state->run = false;
+ if (!options_->server) {
+ run = false;
}
}
@@ -411,18 +384,10 @@
Dbg::ThreadRunning();
LOG(VERBOSE) << "JDWP: thread exiting";
- return NULL;
}
-
-/*
- * Return the thread handle, or (pthread_t)0 if the debugger isn't running.
- */
-pthread_t GetDebugThread(JdwpState* state) {
- if (state == NULL) {
- return 0;
- }
- return state->debugThreadHandle;
+pthread_t JdwpState::GetDebugThread() {
+ return debugThreadHandle;
}
/*
@@ -466,13 +431,13 @@
* Returns -1 if no debugger is attached, or 0 if we're in the middle of
* processing a debugger request.
*/
-int64_t LastDebuggerActivity(JdwpState* state) {
+int64_t JdwpState::LastDebuggerActivity() {
if (!Dbg::IsDebuggerConnected()) {
LOG(DEBUG) << "no active debugger";
return -1;
}
- int64_t last = QuasiAtomicRead64(&state->lastActivityWhen);
+ int64_t last = QuasiAtomicRead64(&lastActivityWhen);
/* initializing or in the middle of something? */
if (last == 0) {
diff --git a/src/jdwp/jdwp_priv.h b/src/jdwp/jdwp_priv.h
index 60169dd..46f79b8 100644
--- a/src/jdwp/jdwp_priv.h
+++ b/src/jdwp/jdwp_priv.h
@@ -24,7 +24,6 @@
#include "debugger.h"
#include "jdwp/jdwp.h"
#include "jdwp/jdwp_event.h"
-#include "../mutex.h" // TODO: fix our include path!
#include <pthread.h>
#include <sys/uio.h>
@@ -53,7 +52,7 @@
* Transport functions.
*/
struct JdwpTransport {
- bool (*startup)(JdwpState* state, const JdwpStartupParams* pParams);
+ bool (*startup)(JdwpState* state, const JdwpOptions* options);
bool (*accept)(JdwpState* state);
bool (*establish)(JdwpState* state);
void (*close)(JdwpState* state);
@@ -69,60 +68,6 @@
const JdwpTransport* SocketTransport();
const JdwpTransport* AndroidAdbTransport();
-
-/*
- * State for JDWP functions.
- */
-struct JdwpState {
- JdwpState();
-
- JdwpStartupParams params;
-
- /* wait for creation of the JDWP thread */
- Mutex thread_start_lock_;
- ConditionVariable thread_start_cond_;
-
- volatile int32_t debug_thread_started_;
- pthread_t debugThreadHandle;
- ObjectId debugThreadId;
- bool run;
-
- const JdwpTransport* transport;
- JdwpNetState* netState;
-
- /* for wait-for-debugger */
- Mutex attach_lock_;
- ConditionVariable attach_cond_;
-
- /* time of last debugger activity, in milliseconds */
- int64_t lastActivityWhen;
-
- /* global counters and a mutex to protect them */
- uint32_t requestSerial;
- uint32_t eventSerial;
- Mutex serial_lock_;
-
- /*
- * Events requested by the debugger (breakpoints, class prep, etc).
- */
- int numEvents; /* #of elements in eventList */
- JdwpEvent* eventList; /* linked list of events */
- Mutex event_lock_; /* guards numEvents/eventList */
-
- /*
- * Synchronize suspension of event thread (to avoid receiving "resume"
- * events before the thread has finished suspending itself).
- */
- Mutex event_thread_lock_;
- ConditionVariable event_thread_cond_;
- ObjectId eventThreadId;
-
- /*
- * DDM support.
- */
- bool ddmActive;
-};
-
/*
* Base class for JdwpNetState
*/
@@ -138,14 +83,6 @@
Mutex socket_lock_;
};
-
-/* reset all session-specific data */
-void ResetState(JdwpState* state);
-
-/* atomic ops to get next serial number */
-uint32_t NextRequestSerial(JdwpState* state);
-uint32_t NextEventSerial(JdwpState* state);
-
/* get current time, in msec */
int64_t GetNowMsec();
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index 55bc1b4..28786ed 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -68,8 +68,7 @@
unsigned char inputBuffer[kInputBufferSize];
int inputCount;
- JdwpNetState()
- {
+ JdwpNetState() {
listenPort = 0;
listenSock = -1;
wakePipe[0] = -1;
@@ -86,13 +85,13 @@
/*
* Set up some stuff for transport=dt_socket.
*/
-static bool prepareSocket(JdwpState* state, const JdwpStartupParams* pParams) {
+static bool prepareSocket(JdwpState* state, const JdwpOptions* options) {
unsigned short port;
- if (pParams->server) {
- if (pParams->port != 0) {
+ if (options->server) {
+ if (options->port != 0) {
/* try only the specified port */
- port = pParams->port;
+ port = options->port;
state->netState = netStartup(port);
} else {
/* scan through a range of ports, binding to the first available */
@@ -104,18 +103,18 @@
}
}
if (state->netState == NULL) {
- LOG(ERROR) << "JDWP net startup failed (req port=" << pParams->port << ")";
+ LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")";
return false;
}
} else {
- port = pParams->port; // used in a debug msg later
+ port = options->port; // used in a debug msg later
state->netState = netStartup(-1);
}
- if (pParams->suspend) {
+ if (options->suspend) {
LOG(INFO) << "JDWP will wait for debugger on port " << port;
} else {
- LOG(INFO) << "JDWP will " << (pParams->server ? "listen" : "connect") << " on port " << port;
+ LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port;
}
return true;
@@ -394,9 +393,9 @@
struct hostent* pEntry;
CHECK(state != NULL && state->netState != NULL);
- CHECK(!state->params.server);
- CHECK_NE(state->params.host[0], '\0');
- CHECK_NE(state->params.port, 0);
+ CHECK(!state->options_->server);
+ CHECK(!state->options_->host.empty());
+ CHECK_NE(state->options_->port, 0);
/*
* Start by resolving the host name.
@@ -407,16 +406,16 @@
struct hostent he;
char auxBuf[128];
int error;
- int cc = gethostbyname_r(state->params.host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
+ int cc = gethostbyname_r(state->options_->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
if (cc != 0) {
- LOG(WARNING) << "gethostbyname_r('" << state->params.host << "') failed: " << hstrerror(error);
+ LOG(WARNING) << "gethostbyname_r('" << state->options_->host << "') failed: " << hstrerror(error);
return false;
}
#else
h_errno = 0;
- pEntry = gethostbyname(state->params.host.c_str());
+ pEntry = gethostbyname(state->options_->host.c_str());
if (pEntry == NULL) {
- PLOG(WARNING) << "gethostbyname('" << state->params.host << "') failed";
+ PLOG(WARNING) << "gethostbyname('" << state->options_->host << "') failed";
return false;
}
#endif
@@ -425,7 +424,7 @@
memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
addr.addrInet.sin_family = pEntry->h_addrtype;
- addr.addrInet.sin_port = htons(state->params.port);
+ addr.addrInet.sin_port = htons(state->options_->port);
LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
@@ -450,7 +449,7 @@
return false;
}
- LOG(INFO) << "Connection established to " << state->params.host << " (" << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
+ LOG(INFO) << "Connection established to " << state->options_->host << " (" << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
netState->awaitingHandshake = true;
netState->inputCount = 0;
@@ -522,102 +521,99 @@
* Dump the contents of a packet to stdout.
*/
#if 0
-static void dumpPacket(const unsigned char* packetBuf)
-{
- const unsigned char* buf = packetBuf;
- uint32_t length, id;
- uint8_t flags, cmdSet, cmd;
- uint16_t error;
- bool reply;
- int dataLen;
+static void dumpPacket(const unsigned char* packetBuf) {
+ const unsigned char* buf = packetBuf;
+ uint32_t length, id;
+ uint8_t flags, cmdSet, cmd;
+ uint16_t error;
+ bool reply;
+ int dataLen;
- cmd = cmdSet = 0xcc;
+ cmd = cmdSet = 0xcc;
- length = read4BE(&buf);
- id = read4BE(&buf);
- flags = read1(&buf);
- if ((flags & kJDWPFlagReply) != 0) {
- reply = true;
- error = read2BE(&buf);
- } else {
- reply = false;
- cmdSet = read1(&buf);
- cmd = read1(&buf);
- }
+ length = read4BE(&buf);
+ id = read4BE(&buf);
+ flags = read1(&buf);
+ if ((flags & kJDWPFlagReply) != 0) {
+ reply = true;
+ error = read2BE(&buf);
+ } else {
+ reply = false;
+ cmdSet = read1(&buf);
+ cmd = read1(&buf);
+ }
- dataLen = length - (buf - packetBuf);
+ dataLen = length - (buf - packetBuf);
- LOG(VERBOSE) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
- reply ? "reply" : "req",
- dataLen, id, flags, cmdSet, cmd);
- if (dataLen > 0) {
- HexDump(buf, dataLen);
- }
+ LOG(VERBOSE) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
+ reply ? "reply" : "req", dataLen, id, flags, cmdSet, cmd);
+ if (dataLen > 0) {
+ HexDump(buf, dataLen);
+ }
}
#endif
/*
* Handle a packet. Returns "false" if we encounter a connection-fatal error.
*/
-static bool handlePacket(JdwpState* state)
-{
- JdwpNetState* netState = state->netState;
- const unsigned char* buf = netState->inputBuffer;
- JdwpReqHeader hdr;
- uint32_t length, id;
- uint8_t flags, cmdSet, cmd;
- uint16_t error;
- bool reply;
- int dataLen;
+static bool handlePacket(JdwpState* state) {
+ JdwpNetState* netState = state->netState;
+ const unsigned char* buf = netState->inputBuffer;
+ JdwpReqHeader hdr;
+ uint32_t length, id;
+ uint8_t flags, cmdSet, cmd;
+ uint16_t error;
+ bool reply;
+ int dataLen;
- cmd = cmdSet = 0; // shut up gcc
+ cmd = cmdSet = 0; // shut up gcc
- /*dumpPacket(netState->inputBuffer);*/
+ /*dumpPacket(netState->inputBuffer);*/
- length = read4BE(&buf);
- id = read4BE(&buf);
- flags = read1(&buf);
- if ((flags & kJDWPFlagReply) != 0) {
- reply = true;
- error = read2BE(&buf);
- } else {
- reply = false;
- cmdSet = read1(&buf);
- cmd = read1(&buf);
- }
+ length = read4BE(&buf);
+ id = read4BE(&buf);
+ flags = read1(&buf);
+ if ((flags & kJDWPFlagReply) != 0) {
+ reply = true;
+ error = read2BE(&buf);
+ } else {
+ reply = false;
+ cmdSet = read1(&buf);
+ cmd = read1(&buf);
+ }
- CHECK_LE((int) length, netState->inputCount);
- dataLen = length - (buf - netState->inputBuffer);
+ CHECK_LE((int) length, netState->inputCount);
+ dataLen = length - (buf - netState->inputBuffer);
- if (!reply) {
- ExpandBuf* pReply = expandBufAlloc();
+ if (!reply) {
+ ExpandBuf* pReply = expandBufAlloc();
- hdr.length = length;
- hdr.id = id;
- hdr.cmdSet = cmdSet;
- hdr.cmd = cmd;
- ProcessRequest(state, &hdr, buf, dataLen, pReply);
- if (expandBufGetLength(pReply) > 0) {
- ssize_t cc = netState->writePacket(pReply);
+ hdr.length = length;
+ hdr.id = id;
+ hdr.cmdSet = cmdSet;
+ hdr.cmd = cmd;
+ state->ProcessRequest(&hdr, buf, dataLen, pReply);
+ if (expandBufGetLength(pReply) > 0) {
+ ssize_t cc = netState->writePacket(pReply);
- if (cc != (ssize_t) expandBufGetLength(pReply)) {
- PLOG(ERROR) << "Failed sending reply to debugger";
- expandBufFree(pReply);
- return false;
- }
- } else {
- LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
- }
+ if (cc != (ssize_t) expandBufGetLength(pReply)) {
+ PLOG(ERROR) << "Failed sending reply to debugger";
expandBufFree(pReply);
+ return false;
+ }
} else {
- LOG(ERROR) << "reply?!";
- DCHECK(false);
+ LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
}
+ expandBufFree(pReply);
+ } else {
+ LOG(ERROR) << "reply?!";
+ DCHECK(false);
+ }
- LOG(VERBOSE) << "----------";
+ LOG(VERBOSE) << "----------";
- consumeBytes(netState, length);
- return true;
+ consumeBytes(netState, length);
+ return true;
}
/*