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

Commit 8926f1a9 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Replace libbacktrace with libunwindstack directly."

parents 083797ad 60eb1979
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -114,7 +114,6 @@ cc_library_static {
        "libasync_safe",
        "libbase",
        "libdebuggerd",
        "libbacktrace",
        "libunwindstack",
        "libdexfile",  // libunwindstack dependency
        "libdexfile_external",  // libunwindstack dependency
@@ -124,7 +123,6 @@ cc_library_static {
    ],
    target: {
        recovery: {
            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
            exclude_static_libs: [
                "libartbase",
                "libdexfile",
@@ -164,7 +162,6 @@ cc_library_static {

    srcs: [
        "libdebuggerd/backtrace.cpp",
        "libdebuggerd/elf_utils.cpp",
        "libdebuggerd/open_files_list.cpp",
        "libdebuggerd/tombstone.cpp",
        "libdebuggerd/utility.cpp",
@@ -177,7 +174,6 @@ cc_library_static {
    include_dirs: ["bionic/libc"],

    static_libs: [
        "libbacktrace",
        "libdexfile_external",  // libunwindstack dependency
        "libdexfile_support",  // libunwindstack dependency
        "libunwindstack",
@@ -223,7 +219,6 @@ cc_test {
    },

    shared_libs: [
        "libbacktrace",
        "libbase",
        "libcutils",
        "libdebuggerd_client",
@@ -291,7 +286,6 @@ cc_binary {
    ],

    shared_libs: [
        "libbacktrace",
        "libbase",
        "liblog",
        "libprocinfo",
+15 −16
Original line number Diff line number Diff line
@@ -48,7 +48,12 @@
#define ATRACE_TAG ATRACE_TAG_BIONIC
#include <utils/Trace.h>

#include <unwindstack/DexFiles.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
#include <unwindstack/Unwinder.h>

#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/tombstone.h"
@@ -63,8 +68,6 @@
using android::base::unique_fd;
using android::base::StringPrintf;

using unwindstack::Regs;

static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
  struct stat st;
  std::string task_path = StringPrintf("task/%d", tid);
@@ -287,7 +290,8 @@ static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
    case 1:
      *abort_msg_address = crash_info->data.v1.abort_msg_address;
      *siginfo = crash_info->data.v1.siginfo;
      regs->reset(Regs::CreateFromUcontext(Regs::CurrentArch(), &crash_info->data.v1.ucontext));
      regs->reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(),
                                                        &crash_info->data.v1.ucontext));
      break;

    default:
@@ -469,7 +473,7 @@ int main(int argc, char** argv) {
        info.siginfo = &siginfo;
        info.signo = info.siginfo->si_signo;
      } else {
        info.registers.reset(Regs::RemoteGet(thread));
        info.registers.reset(unwindstack::Regs::RemoteGet(thread));
        if (!info.registers) {
          PLOG(WARNING) << "failed to fetch registers for thread " << thread;
          ptrace(PTRACE_DETACH, thread, 0, 0);
@@ -562,30 +566,25 @@ int main(int argc, char** argv) {
  }

  // TODO: Use seccomp to lock ourselves down.
  std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(vm_pid, false));
  if (!map) {
    LOG(FATAL) << "failed to create backtrace map";
  }

  std::shared_ptr<unwindstack::Memory> process_memory = map->GetProcessMemory();
  if (!process_memory) {
    LOG(FATAL) << "failed to get unwindstack::Memory handle";
  unwindstack::UnwinderFromPid unwinder(256, vm_pid);
  if (!unwinder.Init(unwindstack::Regs::CurrentArch())) {
    LOG(FATAL) << "Failed to init unwinder object.";
  }

  std::string amfd_data;
  if (backtrace) {
    ATRACE_NAME("dump_backtrace");
    dump_backtrace(std::move(g_output_fd), map.get(), thread_info, g_target_thread);
    dump_backtrace(std::move(g_output_fd), &unwinder, thread_info, g_target_thread);
  } else {
    {
      ATRACE_NAME("fdsan table dump");
      populate_fdsan_table(&open_files, process_memory, fdsan_table_address);
      populate_fdsan_table(&open_files, unwinder.GetProcessMemory(), fdsan_table_address);
    }

    {
      ATRACE_NAME("engrave_tombstone");
      engrave_tombstone(std::move(g_output_fd), map.get(), process_memory.get(), thread_info,
                        g_target_thread, abort_msg_address, &open_files, &amfd_data);
      engrave_tombstone(std::move(g_output_fd), &unwinder, thread_info, g_target_thread,
                        abort_msg_address, &open_files, &amfd_data);
    }
  }

+13 −6
Original line number Diff line number Diff line
@@ -42,9 +42,12 @@
#include <android-base/file.h>
#include <android-base/unique_fd.h>
#include <async_safe/log.h>
#include <backtrace/BacktraceMap.h>
#include <unwindstack/DexFiles.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
#include <unwindstack/Unwinder.h>

#include "debuggerd/handler.h"
#include "handler/fallback.h"
@@ -55,7 +58,6 @@
#include "libdebuggerd/tombstone.h"

using android::base::unique_fd;
using unwindstack::Regs;

extern "C" bool __linker_enable_fallback_allocator();
extern "C" void __linker_disable_fallback_allocator();
@@ -73,17 +75,22 @@ static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
  }

  {
    std::unique_ptr<Regs> regs;
    std::unique_ptr<unwindstack::Regs> regs;

    ThreadInfo thread;
    thread.pid = getpid();
    thread.tid = gettid();
    thread.thread_name = get_thread_name(gettid());
    thread.registers.reset(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext));
    unwindstack::ArchEnum arch = unwindstack::Regs::CurrentArch();
    thread.registers.reset(unwindstack::Regs::CreateFromUcontext(arch, ucontext));

    // TODO: Create this once and store it in a global?
    std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid()));
    dump_backtrace_thread(output_fd, map.get(), thread);
    unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid());
    if (unwinder.Init(arch)) {
      dump_backtrace_thread(output_fd, &unwinder, thread);
    } else {
      async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Unable to init unwinder.");
    }
  }
  __linker_disable_fallback_allocator();
}
+11 −9
Original line number Diff line number Diff line
@@ -35,8 +35,8 @@
#include <string>

#include <android-base/unique_fd.h>
#include <backtrace/Backtrace.h>
#include <log/log.h>
#include <unwindstack/Unwinder.h>

#include "libdebuggerd/types.h"
#include "libdebuggerd/utility.h"
@@ -59,25 +59,27 @@ static void dump_process_footer(log_t* log, pid_t pid) {
  _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
}

void dump_backtrace_thread(int output_fd, BacktraceMap* map, const ThreadInfo& thread) {
void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
                           const ThreadInfo& thread) {
  log_t log;
  log.tfd = output_fd;
  log.amfd_data = nullptr;

  _LOG(&log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread.thread_name.c_str(), thread.tid);

  std::vector<backtrace_frame_data_t> frames;
  if (!Backtrace::Unwind(thread.registers.get(), map, &frames, 0, nullptr)) {
  unwinder->SetRegs(thread.registers.get());
  unwinder->Unwind();
  if (unwinder->NumFrames() == 0) {
    _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d", thread.tid);
    return;
  }

  for (auto& frame : frames) {
    _LOG(&log, logtype::BACKTRACE, "  %s\n", Backtrace::FormatFrameData(&frame).c_str());
  for (size_t i = 0; i < unwinder->NumFrames(); i++) {
    _LOG(&log, logtype::BACKTRACE, "  %s\n", unwinder->FormatFrame(i).c_str());
  }
}

void dump_backtrace(android::base::unique_fd output_fd, BacktraceMap* map,
void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
                    const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread) {
  log_t log;
  log.tfd = output_fd.get();
@@ -91,10 +93,10 @@ void dump_backtrace(android::base::unique_fd output_fd, BacktraceMap* map,

  dump_process_header(&log, target->second.pid, target->second.process_name.c_str());

  dump_backtrace_thread(output_fd.get(), map, target->second);
  dump_backtrace_thread(output_fd.get(), unwinder, target->second);
  for (const auto& [tid, info] : thread_info) {
    if (tid != target_thread) {
      dump_backtrace_thread(output_fd.get(), map, info);
      dump_backtrace_thread(output_fd.get(), unwinder, info);
    }
  }

+0 −121
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "DEBUG"

#include "libdebuggerd/elf_utils.h"

#include <elf.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include <string>

#include <android-base/stringprintf.h>
#include <log/log.h>
#include <unwindstack/Memory.h>

#define NOTE_ALIGN(size)  (((size) + 3) & ~3)

template <typename HdrType, typename PhdrType, typename NhdrType>
static bool get_build_id(unwindstack::Memory* memory, uintptr_t base_addr, uint8_t* e_ident,
                         std::string* build_id) {
  HdrType hdr;

  memcpy(&hdr.e_ident[0], e_ident, EI_NIDENT);

  // First read the rest of the header.
  if (memory->Read(base_addr + EI_NIDENT, reinterpret_cast<uint8_t*>(&hdr) + EI_NIDENT,
                   sizeof(HdrType) - EI_NIDENT) != sizeof(HdrType) - EI_NIDENT) {
    return false;
  }

  for (size_t i = 0; i < hdr.e_phnum; i++) {
    PhdrType phdr;
    if (memory->Read(base_addr + hdr.e_phoff + i * hdr.e_phentsize,
                     reinterpret_cast<uint8_t*>(&phdr), sizeof(phdr)) != sizeof(phdr)) {
      return false;
    }
    // Looking for the .note.gnu.build-id note.
    if (phdr.p_type == PT_NOTE) {
      size_t hdr_size = phdr.p_filesz;
      uintptr_t addr = base_addr + phdr.p_offset;
      while (hdr_size >= sizeof(NhdrType)) {
        NhdrType nhdr;
        if (memory->Read(addr, reinterpret_cast<uint8_t*>(&nhdr), sizeof(nhdr)) != sizeof(nhdr)) {
          return false;
        }
        addr += sizeof(nhdr);
        if (nhdr.n_type == NT_GNU_BUILD_ID) {
          // Skip the name (which is the owner and should be "GNU").
          addr += NOTE_ALIGN(nhdr.n_namesz);
          uint8_t build_id_data[160];
          if (nhdr.n_descsz > sizeof(build_id_data)) {
            ALOGE("Possible corrupted note, desc size value is too large: %u",
                  nhdr.n_descsz);
            return false;
          }
          if (memory->Read(addr, build_id_data, nhdr.n_descsz) != nhdr.n_descsz) {
            return false;
          }

          build_id->clear();
          for (size_t bytes = 0; bytes < nhdr.n_descsz; bytes++) {
            *build_id += android::base::StringPrintf("%02x", build_id_data[bytes]);
          }

          return true;
        } else {
          // Move past the extra note data.
          hdr_size -= sizeof(nhdr);
          size_t skip_bytes = NOTE_ALIGN(nhdr.n_namesz) + NOTE_ALIGN(nhdr.n_descsz);
          addr += skip_bytes;
          if (hdr_size < skip_bytes) {
            break;
          }
          hdr_size -= skip_bytes;
        }
      }
    }
  }
  return false;
}

bool elf_get_build_id(unwindstack::Memory* memory, uintptr_t addr, std::string* build_id) {
  // Read and verify the elf magic number first.
  uint8_t e_ident[EI_NIDENT];
  if (memory->Read(addr, e_ident, SELFMAG) != SELFMAG) {
    return false;
  }

  if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
    return false;
  }

  // Read the rest of EI_NIDENT.
  if (memory->Read(addr + SELFMAG, e_ident + SELFMAG, EI_NIDENT - SELFMAG) != EI_NIDENT - SELFMAG) {
    return false;
  }

  if (e_ident[EI_CLASS] == ELFCLASS32) {
    return get_build_id<Elf32_Ehdr, Elf32_Phdr, Elf32_Nhdr>(memory, addr, e_ident, build_id);
  } else if (e_ident[EI_CLASS] == ELFCLASS64) {
    return get_build_id<Elf64_Ehdr, Elf64_Phdr, Elf64_Nhdr>(memory, addr, e_ident, build_id);
  }

  return false;
}
Loading