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

Commit 92317d82 authored by Josh Gao's avatar Josh Gao
Browse files

libdebuggerd: add protobuf implementation.

This commit implements protobuf output for tombstones, along with a
translator that should emit bytewise identical output to the existing
tombstone dumping code, except for ancillary data from GWP-ASan and
Scudo, which haven't been implemented yet.

Test: setprop debug.debuggerd.translate.translate_proto_to_text 1 &&
        /data/nativetest64/debuggerd_test/debuggerd_test
Test: for TOMBSTONE in /data/tombstones/tombstone_??; do
        pbtombstone $TOMBSTONE.pb | diff $TOMBSTONE -
      done
Change-Id: Ieeece6e6d1c26eb608b00ec24e2e725e161c8c92
parent 1091d24c
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -176,6 +176,8 @@ cc_library_static {
        "libdebuggerd/open_files_list.cpp",
        "libdebuggerd/scudo.cpp",
        "libdebuggerd/tombstone.cpp",
        "libdebuggerd/tombstone_proto.cpp",
        "libdebuggerd/tombstone_proto_to_text.cpp",
        "libdebuggerd/utility.cpp",
    ],

@@ -206,6 +208,8 @@ cc_library_static {
    whole_static_libs: [
        "gwp_asan_crash_handler",
        "libscudo",
        "libtombstone_proto",
        "libprotobuf-cpp-lite",
    ],

    target: {
@@ -228,6 +232,20 @@ cc_library_static {
    },
}

cc_binary {
    name: "pbtombstone",
    defaults: ["debuggerd_defaults"],
    srcs: ["pbtombstone.cpp"],
    static_libs: [
        "libbase",
        "libdebuggerd",
        "liblog",
        "libprotobuf-cpp-lite",
        "libtombstone_proto",
        "libunwindstack",
    ],
}

cc_test {
    name: "debuggerd_test",
    defaults: ["debuggerd_defaults"],
@@ -332,6 +350,9 @@ cc_binary {
        "libtombstoned_client_static",
        "libdebuggerd",
        "libcutils",

        "libtombstone_proto",
        "libprotobuf-cpp-lite",
    ],

    shared_libs: [
+22 −6
Original line number Diff line number Diff line
@@ -194,6 +194,7 @@ static pid_t g_target_thread = -1;
static bool g_tombstoned_connected = false;
static unique_fd g_tombstoned_socket;
static unique_fd g_output_fd;
static unique_fd g_proto_fd;

static void DefuseSignalHandlers() {
  // Don't try to dump ourselves.
@@ -214,7 +215,7 @@ static void Initialize(char** argv) {
    // If we abort before we get an output fd, contact tombstoned to let any
    // potential listeners know that we failed.
    if (!g_tombstoned_connected) {
      if (!tombstoned_connect(g_target_thread, &g_tombstoned_socket, &g_output_fd,
      if (!tombstoned_connect(g_target_thread, &g_tombstoned_socket, &g_output_fd, &g_proto_fd,
                              kDebuggerdAnyIntercept)) {
        // We failed to connect, not much we can do.
        LOG(ERROR) << "failed to connected to tombstoned to report failure";
@@ -247,10 +248,20 @@ static void ParseArgs(int argc, char** argv, pid_t* pseudothread_tid, DebuggerdD
  }

  int dump_type_int;
  if (!android::base::ParseInt(argv[3], &dump_type_int, 0, 1)) {
  if (!android::base::ParseInt(argv[3], &dump_type_int, 0)) {
    LOG(FATAL) << "invalid requested dump type: " << argv[3];
  }

  *dump_type = static_cast<DebuggerdDumpType>(dump_type_int);
  switch (*dump_type) {
    case kDebuggerdNativeBacktrace:
    case kDebuggerdTombstone:
    case kDebuggerdTombstoneProto:
      break;

    default:
      LOG(FATAL) << "invalid requested dump type: " << dump_type_int;
  }
}

static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
@@ -477,6 +488,11 @@ int main(int argc, char** argv) {
      info.process_name = process_name;
      info.thread_name = get_thread_name(thread);

      unique_fd attr_fd(openat(target_proc_fd, "attr/current", O_RDONLY | O_CLOEXEC));
      if (!android::base::ReadFdToString(attr_fd, &info.selinux_label)) {
        PLOG(WARNING) << "failed to read selinux label";
      }

      if (!ptrace_interrupt(thread, &info.signo)) {
        PLOG(WARNING) << "failed to ptrace interrupt thread " << thread;
        ptrace(PTRACE_DETACH, thread, 0, 0);
@@ -555,8 +571,8 @@ int main(int argc, char** argv) {
  {
    ATRACE_NAME("tombstoned_connect");
    LOG(INFO) << "obtaining output fd from tombstoned, type: " << dump_type;
    g_tombstoned_connected =
        tombstoned_connect(g_target_thread, &g_tombstoned_socket, &g_output_fd, dump_type);
    g_tombstoned_connected = tombstoned_connect(g_target_thread, &g_tombstoned_socket, &g_output_fd,
                                                &g_proto_fd, dump_type);
  }

  if (g_tombstoned_connected) {
@@ -609,8 +625,8 @@ int main(int argc, char** argv) {

    {
      ATRACE_NAME("engrave_tombstone");
      engrave_tombstone(std::move(g_output_fd), &unwinder, thread_info, g_target_thread, process_info,
                        &open_files, &amfd_data);
      engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
                        g_target_thread, process_info, &open_files, &amfd_data);
    }
  }

+10 −9
Original line number Diff line number Diff line
@@ -92,15 +92,15 @@ static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
  __linker_disable_fallback_allocator();
}

static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo,
                                         void* abort_message) {
static void debuggerd_fallback_tombstone(int output_fd, int proto_fd, ucontext_t* ucontext,
                                         siginfo_t* siginfo, void* abort_message) {
  if (!__linker_enable_fallback_allocator()) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use");
    return;
  }

  engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo,
                             ucontext);
  engrave_tombstone_ucontext(output_fd, proto_fd, reinterpret_cast<uintptr_t>(abort_message),
                             siginfo, ucontext);
  __linker_disable_fallback_allocator();
}

@@ -232,7 +232,8 @@ static void trace_handler(siginfo_t* info, ucontext_t* ucontext) {

  // Fetch output fd from tombstoned.
  unique_fd tombstone_socket, output_fd;
  if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdNativeBacktrace)) {
  if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd, nullptr,
                          kDebuggerdNativeBacktrace)) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc",
                          "missing crash_dump_fallback() in selinux policy?");
    goto exit;
@@ -325,10 +326,10 @@ static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_mes
    _exit(1);
  }

  unique_fd tombstone_socket, output_fd;
  bool tombstoned_connected =
      tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdTombstone);
  debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message);
  unique_fd tombstone_socket, output_fd, proto_fd;
  bool tombstoned_connected = tombstoned_connect(getpid(), &tombstone_socket, &output_fd, &proto_fd,
                                                 kDebuggerdTombstoneProto);
  debuggerd_fallback_tombstone(output_fd.get(), proto_fd.get(), ucontext, info, abort_message);
  if (tombstoned_connected) {
    tombstoned_notify_completion(tombstone_socket.get());
  }
+1 −1
Original line number Diff line number Diff line
@@ -313,7 +313,7 @@ static DebuggerdDumpType get_dump_type(const debugger_thread_info* thread_info)
    return kDebuggerdNativeBacktrace;
  }

  return kDebuggerdTombstone;
  return kDebuggerdTombstoneProto;
}

static int debuggerd_dispatch_pseudothread(void* arg) {
+14 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <stddef.h>
#include <sys/types.h>

#include <functional>
#include <map>
#include <string>

@@ -30,6 +31,8 @@
#include "types.h"

// Forward declarations
class Tombstone;

namespace unwindstack {
class Unwinder;
}
@@ -44,13 +47,21 @@ constexpr size_t kMaxFrames = 256;
int open_tombstone(std::string* path);

/* Creates a tombstone file and writes the crash dump to it. */
void engrave_tombstone(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique_fd proto_fd,
                       unwindstack::Unwinder* unwinder,
                       const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
                       const ProcessInfo& process_info, OpenFilesList* open_files,
                       std::string* amfd_data);

void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo,
                                ucontext_t* ucontext);
void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
                                siginfo_t* siginfo, ucontext_t* ucontext);

void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
                             const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
                             const ProcessInfo& process_info, const OpenFilesList* open_files);

bool tombstone_proto_to_text(
    const Tombstone& tombstone,
    std::function<void(const std::string& line, bool should_log)> callback);

#endif  // _DEBUGGERD_TOMBSTONE_H
Loading