summaryrefslogtreecommitdiffstats
path: root/debuggerd/utility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'debuggerd/utility.cpp')
-rw-r--r--debuggerd/utility.cpp121
1 files changed, 93 insertions, 28 deletions
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index 35f061e..9b20914 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -14,19 +14,17 @@
* limitations under the License.
*/
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
+#include "utility.h"
+
#include <errno.h>
-#include <unistd.h>
#include <signal.h>
-#include <log/logd.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <assert.h>
-#include "utility.h"
+#include <backtrace/Backtrace.h>
+#include <log/logd.h>
const int sleep_time_usec = 50000; // 0.05 seconds
const int max_total_sleep_usec = 10000000; // 10 seconds
@@ -34,7 +32,7 @@ const int max_total_sleep_usec = 10000000; // 10 seconds
static int write_to_am(int fd, const char* buf, int len) {
int to_write = len;
while (to_write > 0) {
- int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) );
+ int written = TEMP_FAILURE_RETRY(write(fd, buf + len - to_write, to_write));
if (written < 0) {
// hard failure
LOG("AM write failure (%d / %s)\n", errno, strerror(errno));
@@ -46,34 +44,28 @@ static int write_to_am(int fd, const char* buf, int len) {
}
void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) {
- char buf[512];
- bool want_tfd_write;
- bool want_log_write;
- bool want_amfd_write;
- int len = 0;
+ bool want_tfd_write = log && log->tfd >= 0;
+ bool want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
+ bool want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
+ char buf[512];
va_list ap;
va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
- // where is the information going to go?
- want_tfd_write = log && log->tfd >= 0;
- want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
- want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
-
- // if we're going to need the literal string, generate it once here
- if (want_tfd_write || want_amfd_write) {
- vsnprintf(buf, sizeof(buf), fmt, ap);
- len = strlen(buf);
+ size_t len = strlen(buf);
+ if (len <= 0) {
+ return;
}
if (want_tfd_write) {
- write(log->tfd, buf, len);
+ TEMP_FAILURE_RETRY(write(log->tfd, buf, len));
}
if (want_log_write) {
- // whatever goes to logcat also goes to the Activity Manager
- __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
- if (want_amfd_write && len > 0) {
+ __android_log_write(ANDROID_LOG_INFO, "DEBUG", buf);
+ if (want_amfd_write) {
int written = write_to_am(log->amfd, buf, len);
if (written <= 0) {
// timeout or other failure on write; stop informing the activity manager
@@ -81,7 +73,6 @@ void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) {
}
}
}
- va_end(ap);
}
int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
@@ -127,3 +118,77 @@ void wait_for_stop(pid_t tid, int* total_sleep_time_usec) {
*total_sleep_time_usec += sleep_time_usec;
}
}
+
+#if defined (__mips__)
+#define DUMP_MEMORY_AS_ASCII 1
+#else
+#define DUMP_MEMORY_AS_ASCII 0
+#endif
+
+void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) {
+ char code_buffer[64];
+ char ascii_buffer[32];
+ uintptr_t p, end;
+
+ p = addr & ~(sizeof(long) - 1);
+ /* Dump 32 bytes before addr */
+ p -= 32;
+ if (p > addr) {
+ /* catch underflow */
+ p = 0;
+ }
+ /* Dump 256 bytes */
+ end = p + 256;
+ /* catch overflow; 'end - p' has to be multiples of 16 */
+ while (end < p) {
+ end -= 16;
+ }
+
+ /* Dump the code around PC as:
+ * addr contents ascii
+ * 0000000000008d34 ef000000e8bd0090 e1b00000512fff1e ............../Q
+ * 0000000000008d44 ea00b1f9e92d0090 e3a070fcef000000 ......-..p......
+ * On 32-bit machines, there are still 16 bytes per line but addresses and
+ * words are of course presented differently.
+ */
+ while (p < end) {
+ char* asc_out = ascii_buffer;
+
+ int len = snprintf(code_buffer, sizeof(code_buffer), "%" PRIPTR " ", p);
+
+ for (size_t i = 0; i < 16/sizeof(long); i++) {
+ long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL);
+ if (data == -1 && errno != 0) {
+ // ptrace failed, probably because we're dumping memory in an
+ // unmapped or inaccessible page.
+#ifdef __LP64__
+ len += sprintf(code_buffer + len, "---------------- ");
+#else
+ len += sprintf(code_buffer + len, "-------- ");
+#endif
+ } else {
+ len += sprintf(code_buffer + len, "%" PRIPTR " ",
+ static_cast<uintptr_t>(data));
+ }
+
+#if DUMP_MEMORY_AS_ASCII
+ for (size_t j = 0; j < sizeof(long); j++) {
+ /*
+ * Our isprint() allows high-ASCII characters that display
+ * differently (often badly) in different viewers, so we
+ * just use a simpler test.
+ */
+ char val = (data >> (j*8)) & 0xff;
+ if (val >= 0x20 && val < 0x7f) {
+ *asc_out++ = val;
+ } else {
+ *asc_out++ = '.';
+ }
+ }
+#endif
+ p += sizeof(long);
+ }
+ *asc_out = '\0';
+ _LOG(log, scope_flags, " %s %s\n", code_buffer, ascii_buffer);
+ }
+}