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

Commit f253fd07 authored by Christopher Ferris's avatar Christopher Ferris Committed by Android Git Automerger
Browse files

am 17077a28: Merge "Use the correct debuggerd given the tid."

* commit '17077a28':
  Use the correct debuggerd given the tid.
parents b51e3dbd 17077a28
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -23,10 +23,13 @@
extern "C" {
#endif

#if __LP64__
#define DEBUGGER_SOCKET_NAME "android:debuggerd64"
#define DEBUGGER32_SOCKET_NAME "android:debuggerd"
#define DEBUGGER64_SOCKET_NAME "android:debuggerd64"

#if defined(__LP64__)
#define DEBUGGER_SOCKET_NAME DEBUGGER64_SOCKET_NAME
#else
#define DEBUGGER_SOCKET_NAME "android:debuggerd"
#define DEBUGGER_SOCKET_NAME DEBUGGER32_SOCKET_NAME
#endif

typedef enum {
@@ -45,6 +48,16 @@ typedef struct {
    int32_t original_si_code;
} debugger_msg_t;

#if defined(__LP64__)
// For a 64 bit process to contact the 32 bit debuggerd.
typedef struct {
    debugger_action_t action;
    pid_t tid;
    uint32_t abort_msg_address;
    int32_t original_si_code;
} debugger32_msg_t;
#endif

/* Dumps a process backtrace, registers, and stack to a tombstone file (requires root).
 * Stores the tombstone path in the provided buffer.
 * Returns 0 on success, -1 on error.
+119 −57
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@
 * limitations under the License.
 */

#include <stdbool.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -21,70 +24,129 @@
#include <cutils/debugger.h>
#include <cutils/sockets.h>

int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen) {
    int s = socket_local_client(DEBUGGER_SOCKET_NAME,
            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
    if (s < 0) {
        return -1;
#if defined(__LP64__)
#include <elf.h>

static bool is32bit(pid_t tid) {
  char* exeline;
  if (asprintf(&exeline, "/proc/%d/exe", tid) == -1) {
    return false;
  }
  int fd = open(exeline, O_RDONLY | O_CLOEXEC);
  free(exeline);
  if (fd == -1) {
    return false;
  }

    debugger_msg_t msg;
    memset(&msg, 0, sizeof(msg));
    msg.tid = tid;
    msg.action = DEBUGGER_ACTION_DUMP_TOMBSTONE;
  char ehdr[EI_NIDENT];
  ssize_t bytes = read(fd, &ehdr, sizeof(ehdr));
  close(fd);
  if (bytes != (ssize_t) sizeof(ehdr) || memcmp(ELFMAG, ehdr, SELFMAG) != 0) {
    return false;
  }
  if (ehdr[EI_CLASS] == ELFCLASS32) {
    return true;
  }
  return false;
}
#endif

static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) {
  int result = 0;
    if (TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg))) != sizeof(msg)) {
  if (TEMP_FAILURE_RETRY(write(sock_fd, msg_ptr, msg_len)) != (ssize_t) msg_len) {
    result = -1;
  } else {
    char ack;
        if (TEMP_FAILURE_RETRY(read(s, &ack, 1)) != 1) {
            result = -1;
        } else {
            if (pathbuf && pathlen) {
                ssize_t n = TEMP_FAILURE_RETRY(read(s, pathbuf, pathlen - 1));
                if (n <= 0) {
    if (TEMP_FAILURE_RETRY(read(sock_fd, &ack, 1)) != 1) {
      result = -1;
                } else {
                    pathbuf[n] = '\0';
    }
  }
  return result;
}

static int make_dump_request(debugger_action_t action, pid_t tid) {
  const char* socket_name;
  debugger_msg_t msg;
  size_t msg_len;
  void* msg_ptr;

#if defined(__LP64__)
  debugger32_msg_t msg32;
  if (is32bit(tid)) {
    msg_len = sizeof(debugger32_msg_t);
    memset(&msg32, 0, msg_len);
    msg32.tid = tid;
    msg32.action = action;
    msg_ptr = &msg32;

    socket_name = DEBUGGER32_SOCKET_NAME;
  } else
#endif
  {
    msg_len = sizeof(debugger_msg_t);
    memset(&msg, 0, msg_len);
    msg.tid = tid;
    msg.action = action;
    msg_ptr = &msg;

    socket_name = DEBUGGER_SOCKET_NAME;
  }
    TEMP_FAILURE_RETRY(close(s));
    return result;

  int sock_fd = socket_local_client(socket_name, ANDROID_SOCKET_NAMESPACE_ABSTRACT,
      SOCK_STREAM | SOCK_CLOEXEC);
  if (sock_fd < 0) {
    return -1;
  }

int dump_backtrace_to_file(pid_t tid, int fd) {
    int s = socket_local_client(DEBUGGER_SOCKET_NAME,
            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
    if (s < 0) {
  if (send_request(sock_fd, msg_ptr, msg_len) < 0) {
    TEMP_FAILURE_RETRY(close(sock_fd));
    return -1;
  }

    debugger_msg_t msg;
    memset(&msg, 0, sizeof(msg));
    msg.tid = tid;
    msg.action = DEBUGGER_ACTION_DUMP_BACKTRACE;
  return sock_fd;
}

int dump_backtrace_to_file(pid_t tid, int fd) {
  int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_BACKTRACE, tid);
  if (sock_fd < 0) {
    return -1;
  }

  /* Write the data read from the socket to the fd. */
  int result = 0;
    if (TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg))) != sizeof(msg)) {
        result = -1;
    } else {
        char ack;
        if (TEMP_FAILURE_RETRY(read(s, &ack, 1)) != 1) {
            result = -1;
        } else {
            char buffer[4096];
  char buffer[1024];
  ssize_t n;
            while ((n = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)))) > 0) {
  while ((n = TEMP_FAILURE_RETRY(read(sock_fd, buffer, sizeof(buffer)))) > 0) {
    if (TEMP_FAILURE_RETRY(write(fd, buffer, n)) != n) {
      result = -1;
      break;
    }
  }
  TEMP_FAILURE_RETRY(close(sock_fd));
  return result;
}

int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen) {
  int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_TOMBSTONE, tid);
  if (sock_fd < 0) {
    return -1;
  }

  /* Read the tombstone file name. */
  char buffer[100]; /* This is larger than the largest tombstone path. */
  int result = 0;
  ssize_t n = TEMP_FAILURE_RETRY(read(sock_fd, buffer, sizeof(buffer) - 1));
  if (n <= 0) {
    result = -1;
  } else {
    if (pathbuf && pathlen) {
      if (n >= (ssize_t) pathlen) {
        n = pathlen - 1;
      }
      buffer[n] = '\0';
      memcpy(pathbuf, buffer, n + 1);
    }
  }
    TEMP_FAILURE_RETRY(close(s));
  TEMP_FAILURE_RETRY(close(sock_fd));
  return result;
}