Merge "debuggerd: a few generic improvements"
This commit is contained in:
commit
e97dad0d95
5 changed files with 106 additions and 131 deletions
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue