Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e97dad0d authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "debuggerd: a few generic improvements"

parents 8623972d 4bb47720
Loading
Loading
Loading
Loading
+0 −59
Original line number Diff line number Diff line
@@ -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) {
+0 −55
Original line number Diff line number Diff line
@@ -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) {
+18 −14
Original line number Diff line number Diff line
@@ -14,18 +14,20 @@
 * limitations under the License.
 */

#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 <signal.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.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;
+74 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+12 −1
Original line number Diff line number Diff line
@@ -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