Merge "debuggerd: a few generic improvements"

This commit is contained in:
Elliott Hughes 2014-01-30 23:56:55 +00:00 committed by Gerrit Code Review
commit e97dad0d95
5 changed files with 106 additions and 131 deletions

View file

@ -38,65 +38,6 @@
#endif
#endif
static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) {
char code_buffer[64]; // actual 8+1+((8+1)*4) + 1 == 45
char ascii_buffer[32]; // actual 16 + 1 == 17
uintptr_t p, end;
p = addr & ~3;
p -= 32;
if (p > addr) {
// catch underflow
p = 0;
}
// Dump more memory content for the crashing thread.
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
// 00008d34 ef000000 e8bd0090 e1b00000 512fff1e ............../Q
// 00008d44 ea00b1f9 e92d0090 e3a070fc ef000000 ......-..p......
while (p < end) {
char* asc_out = ascii_buffer;
sprintf(code_buffer, "%08x ", p);
int i;
for (i = 0; i < 4; i++) {
// If we see (data == -1 && errno != 0), we know that the ptrace
// call failed, probably because we're dumping memory in an
// unmapped or inaccessible page. I don't know if there's
// value in making that explicit in the output -- it likely
// just complicates parsing and clarifies nothing for the
// enlightened reader.
long data = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(p), NULL);
sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
// Enable the following code blob to dump ASCII values
#if 0
int j;
for (j = 0; j < 4; 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 += 4;
}
*asc_out = '\0';
_LOG(log, scope_flags, " %s %s\n", code_buffer, ascii_buffer);
}
}
// If configured to do so, dump memory around *all* registers
// for the crashing thread.
void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) {

View file

@ -34,61 +34,6 @@
#define R(x) (static_cast<unsigned int>(x))
static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) {
char code_buffer[64]; // actual 8+1+((8+1)*4) + 1 == 45
char ascii_buffer[32]; // actual 16 + 1 == 17
uintptr_t p, end;
p = addr & ~3;
p -= 32;
if (p > addr) {
// catch underflow
p = 0;
}
end = p + 80;
// catch overflow; 'end - p' has to be multiples of 16
while (end < p)
end -= 16;
// Dump the code around PC as:
// addr contents ascii
// 00008d34 ef000000 e8bd0090 e1b00000 512fff1e ............../Q
// 00008d44 ea00b1f9 e92d0090 e3a070fc ef000000 ......-..p......
while (p < end) {
char* asc_out = ascii_buffer;
sprintf(code_buffer, "%08x ", p);
int i;
for (i = 0; i < 4; i++) {
// If we see (data == -1 && errno != 0), we know that the ptrace
// call failed, probably because we're dumping memory in an
// unmapped or inaccessible page. I don't know if there's
// value in making that explicit in the output -- it likely
// just complicates parsing and clarifies nothing for the
// enlightened reader.
long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL);
sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
int j;
for (j = 0; j < 4; 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++ = '.';
}
}
p += 4;
}
*asc_out = '\0';
_LOG(log, scope_flags, " %s %s\n", code_buffer, ascii_buffer);
}
}
// If configured to do so, dump memory around *all* registers
// for the crashing thread.
void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) {

View file

@ -14,18 +14,20 @@
* limitations under the License.
*/
#include <stddef.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <sys/un.h>
#include <private/android_filesystem_config.h>
@ -36,9 +38,6 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
#include <sys/socket.h>
#include <linux/un.h>
#include <selinux/android.h>
#include <UniquePtr.h>
@ -51,6 +50,7 @@
#define MAX_TOMBSTONES 10
#define TOMBSTONE_DIR "/data/tombstones"
#define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")
// Must match the path defined in NativeCrashListener.java
#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
@ -60,7 +60,6 @@
typeof(y) __dummy2; \
(void)(&__dummy1 == &__dummy2); }
static bool signal_has_address(int sig) {
switch (sig) {
case SIGILL:
@ -675,7 +674,7 @@ static char* find_and_open_tombstone(int* fd) {
char path[128];
int oldest = 0;
for (int i = 0; i < MAX_TOMBSTONES; i++) {
snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i);
snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, i);
if (!stat(path, &sb)) {
if (sb.st_mtime < mtime) {
@ -696,7 +695,7 @@ static char* find_and_open_tombstone(int* fd) {
}
// we didn't find an available file, so we clobber the oldest one
snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest);
snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, oldest);
*fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (*fd < 0) {
LOG("failed to open tombstone file '%s': %s\n", path, strerror(errno));
@ -739,8 +738,13 @@ static int activity_manager_connect() {
char* engrave_tombstone(
pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address, bool dump_sibling_threads,
bool quiet, bool* detach_failed, int* total_sleep_time_usec) {
mkdir(TOMBSTONE_DIR, 0755);
chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM);
if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) {
LOG("failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno));
}
if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) {
LOG("failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno));
}
if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) {
*detach_failed = false;

View file

@ -127,3 +127,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);
}
}

View file

@ -18,8 +18,9 @@
#ifndef _DEBUGGERD_UTILITY_H
#define _DEBUGGERD_UTILITY_H
#include <stddef.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
typedef struct {
/* tombstone file descriptor */
@ -60,7 +61,17 @@ void _LOG(log_t* log, int scopeFlags, const char *fmt, ...)
#define XLOG2(fmt...) do {} while(0)
#endif
#if __LP64__
#define PRIPTR "016" PRIxPTR
typedef uint64_t word_t;
#else
#define PRIPTR "08" PRIxPTR
typedef uint32_t word_t;
#endif
int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
void wait_for_stop(pid_t tid, int* total_sleep_time_usec);
void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags);
#endif // _DEBUGGERD_UTILITY_H