Wire up enough of the pieces that we can connect ddms or jdb.
(And die with an UNIMPLEMENTED as soon as they connect, of course.)
Change-Id: I9abb25d581384361c215b3cd96b8278c751e79ea
diff --git a/src/debugger.cc b/src/debugger.cc
index 1580c76..ef44816 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -144,13 +144,36 @@
return true;
}
-bool Dbg::DebuggerStartup() {
- UNIMPLEMENTED(FATAL);
- return false;
+void Dbg::StartJdwp() {
+ // 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";
+ }
+ }
+
+ // If a debugger has already attached, send the "welcome" message.
+ // This may cause us to suspend all threads.
+ if (JDWP::JdwpIsActive(gJdwpState)) {
+ //ScopedThreadStateChange(Thread::Current(), Thread::kRunnable);
+ if (!JDWP::PostVMStart(gJdwpState, gJdwpSuspend)) {
+ LOG(WARNING) << "failed to post 'start' message to debugger";
+ }
+ }
}
-void Dbg::DebuggerShutdown() {
- UNIMPLEMENTED(FATAL);
+void Dbg::StopJdwp() {
+ JDWP::JdwpShutdown(gJdwpState);
}
void Dbg::SetJdwpAllowed(bool allowed) {
@@ -190,13 +213,11 @@
}
int Dbg::ThreadRunning() {
- UNIMPLEMENTED(FATAL);
- return 0;
+ return static_cast<int>(Thread::Current()->SetState(Thread::kRunnable));
}
int Dbg::ThreadWaiting() {
- UNIMPLEMENTED(FATAL);
- return 0;
+ return static_cast<int>(Thread::Current()->SetState(Thread::kVmWait));
}
int Dbg::ThreadContinuing(int status) {
diff --git a/src/debugger.h b/src/debugger.h
index 2c2ade7..fa870b1 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -65,11 +65,11 @@
class Dbg {
public:
static bool ParseJdwpOptions(const std::string& options);
- static bool DebuggerStartup();
- static void DebuggerShutdown();
-
static void SetJdwpAllowed(bool allowed);
+ static void StartJdwp();
+ static void StopJdwp();
+
// Return the DebugInvokeReq for the current thread.
static DebugInvokeReq* GetInvokeReq();
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index 1c205bc..8455ba5 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -93,9 +93,8 @@
JdwpTransportType transport;
bool server;
bool suspend;
- char host[64];
+ std::string host;
short port;
- /* more will be here someday */
};
/*
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index f2ff937..c9dac64 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -311,7 +311,7 @@
android_atomic_release_store(true, &state->debug_thread_started_);
state->thread_start_lock_.Lock();
- state->thread_start_cond_.Wait(state->thread_start_lock_);
+ state->thread_start_cond_.Broadcast();
state->thread_start_lock_.Unlock();
/* set the thread state to VMWAIT so GCs don't wait for us */
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index b4062d0..55bc1b4 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -407,14 +407,14 @@
struct hostent he;
char auxBuf[128];
int error;
- int cc = gethostbyname_r(state->params.host, &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
+ int cc = gethostbyname_r(state->params.host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
if (cc != 0) {
LOG(WARNING) << "gethostbyname_r('" << state->params.host << "') failed: " << hstrerror(error);
return false;
}
#else
h_errno = 0;
- pEntry = gethostbyname(state->params.host);
+ pEntry = gethostbyname(state->params.host.c_str());
if (pEntry == NULL) {
PLOG(WARNING) << "gethostbyname('" << state->params.host << "') failed";
return false;
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 30b19a8..1a99820 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -11,7 +11,6 @@
namespace art {
std::string OatFile::DexFilenameToOatFilename(const std::string& location) {
- LOG(INFO) << "dexfilenametooatfilename " << location;
CHECK(IsValidDexFilename(location) || IsValidZipFilename(location));
std::string oat_location = location.substr(0, location.size()-3);
oat_location += "oat";
diff --git a/src/runtime.cc b/src/runtime.cc
index a144c44..5f2eddd 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -56,6 +56,8 @@
}
Runtime::~Runtime() {
+ Dbg::StopJdwp();
+
// Make sure our internal threads are dead before we start tearing down things they're using.
delete signal_catcher_;
// TODO: GC thread.
@@ -402,7 +404,9 @@
// come after ClassLinker::RunRootClinits.
started_ = true;
- StartSignalCatcher();
+ if (!is_zygote_) {
+ DidForkFromZygote();
+ }
StartDaemonThreads();
@@ -416,9 +420,13 @@
}
void Runtime::DidForkFromZygote() {
- CHECK(is_zygote_);
is_zygote_ = false;
+
StartSignalCatcher();
+
+ // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
+ // this will pause the runtime, so we probably want this to come last.
+ Dbg::StartJdwp();
}
void Runtime::StartSignalCatcher() {
diff --git a/src/runtime.h b/src/runtime.h
index 44dfacf..d29bd3a 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -221,8 +221,9 @@
bool Init(const Options& options, bool ignore_unrecognized);
void InitNativeMethods();
void RegisterRuntimeNativeMethods(JNIEnv*);
- void StartSignalCatcher();
+
void StartDaemonThreads();
+ void StartSignalCatcher();
bool verbose_startup_;
bool is_zygote_;
diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar
index ae1474a..53d7a76 100755
--- a/test/etc/push-and-run-test-jar
+++ b/test/etc/push-and-run-test-jar
@@ -98,7 +98,15 @@
fi
if [ "$DEBUG" = "y" ]; then
+ # This is for ddms:
DEX_DEBUG="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
+ # Connect by running 'ddms'.
+
+ # This is for jdb:
+ #DEX_DEBUG="-agentlib:jdwp=transport=dt_socket,address=12345,server=y,suspend=y"
+ # Connect thus:
+ # adb forward tcp:12345 tcp:12345
+ # jdb -attach localhost:12345
fi
if [ "$ZYGOTE" = "y" ]; then