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

Commit 742fc190 authored by Yabin Cui's avatar Yabin Cui Committed by Gerrit Code Review
Browse files

Merge "libbacktrace: export offline unwinding failures."

parents e05d6afb f8808281
Loading
Loading
Loading
Loading
+28 −17
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
}

std::string Backtrace::GetErrorString(BacktraceUnwindError error) {
  switch (error) {
  switch (error.error_code) {
    case BACKTRACE_UNWIND_NO_ERROR:
      return "No error";
    case BACKTRACE_UNWIND_ERROR_SETUP_FAILED:
@@ -159,5 +159,16 @@ std::string Backtrace::GetErrorString(BacktraceUnwindError error) {
      return "Attempt to use an unsupported feature";
    case BACKTRACE_UNWIND_ERROR_NO_CONTEXT:
      return "Attempt to do an offline unwind without a context";
    case BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT:
      return "Exceed MAX_BACKTRACE_FRAMES limit";
    case BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED:
      return android::base::StringPrintf("Failed to read memory at addr 0x%" PRIx64,
                                         error.error_info.addr);
    case BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED:
      return android::base::StringPrintf("Failed to read register %" PRIu64, error.error_info.regno);
    case BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED:
      return "Failed to find a function in debug sections";
    case BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED:
      return "Failed to execute dwarf instructions in debug sections";
  }
}
+7 −7
Original line number Diff line number Diff line
@@ -67,11 +67,11 @@ size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
  if (GetMap() == nullptr) {
    // Without a map object, we can't do anything.
    error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
    error_.error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
    return false;
  }

  error_ = BACKTRACE_UNWIND_NO_ERROR;
  error_.error_code = BACKTRACE_UNWIND_NO_ERROR;
  if (ucontext) {
    return UnwindFromContext(num_ignore_frames, ucontext);
  }
@@ -163,7 +163,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
    BACK_ASYNC_SAFE_LOGE("sigaction failed: %s", strerror(errno));
    ThreadEntry::Remove(entry);
    pthread_mutex_unlock(&g_sigaction_mutex);
    error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
    error_.error_code = BACKTRACE_UNWIND_ERROR_INTERNAL;
    return false;
  }

@@ -171,9 +171,9 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
    // Do not emit an error message, this might be expected. Set the
    // error and let the caller decide.
    if (errno == ESRCH) {
      error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
      error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
    } else {
      error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
      error_.error_code = BACKTRACE_UNWIND_ERROR_INTERNAL;
    }

    sigaction(THREAD_SIGNAL, &oldact, nullptr);
@@ -218,9 +218,9 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
  } else {
    // Check to see if the thread has disappeared.
    if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) {
      error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
      error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
    } else {
      error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT;
      error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT;
      BACK_ASYNC_SAFE_LOGE("Timed out waiting for signal handler to get ucontext data.");
    }
  }
+30 −6
Original line number Diff line number Diff line
@@ -174,11 +174,11 @@ static unw_accessors_t accessors = {
bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
  if (context == nullptr) {
    BACK_LOGW("The context is needed for offline backtracing.");
    error_ = BACKTRACE_UNWIND_ERROR_NO_CONTEXT;
    error_.error_code = BACKTRACE_UNWIND_ERROR_NO_CONTEXT;
    return false;
  }
  context_ = context;
  error_ = BACKTRACE_UNWIND_NO_ERROR;
  error_.error_code = BACKTRACE_UNWIND_NO_ERROR;

  unw_addr_space_t addr_space = unw_create_addr_space(&accessors, 0);
  unw_cursor_t cursor;
@@ -186,11 +186,11 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
  if (ret != 0) {
    BACK_LOGW("unw_init_remote failed %d", ret);
    unw_destroy_addr_space(addr_space);
    error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
    error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
    return false;
  }
  size_t num_frames = 0;
  do {
  while (true) {
    unw_word_t pc;
    ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
    if (ret < 0) {
@@ -224,7 +224,17 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
    }
    is_debug_frame_used_ = false;
    ret = unw_step(&cursor);
  } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
    if (ret <= 0) {
      if (error_.error_code == BACKTRACE_UNWIND_NO_ERROR) {
        error_.error_code = BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED;
      }
      break;
    }
    if (num_frames == MAX_BACKTRACE_FRAMES) {
      error_.error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT;
      break;
    }
  }

  unw_destroy_addr_space(addr_space);
  context_ = nullptr;
@@ -259,21 +269,30 @@ size_t BacktraceOffline::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
    return read_size;
  }
  read_size = stack_space_.Read(addr, buffer, bytes);
  if (read_size != 0) {
    return read_size;
  }
  error_.error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED;
  error_.error_info.addr = addr;
  return 0;
}

bool BacktraceOffline::FindProcInfo(unw_addr_space_t addr_space, uint64_t ip,
                                    unw_proc_info_t* proc_info, int need_unwind_info) {
  backtrace_map_t map;
  FillInMap(ip, &map);
  if (!BacktraceMap::IsValid(map)) {
    error_.error_code = BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED;
    return false;
  }
  const std::string& filename = map.name;
  DebugFrameInfo* debug_frame = GetDebugFrameInFile(filename);
  if (debug_frame == nullptr) {
    error_.error_code = BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED;
    return false;
  }
  // Each FindProcInfo() is a new attempt to unwind, so reset the reason.
  error_.error_code = BACKTRACE_UNWIND_NO_ERROR;

  eh_frame_hdr_space_.Clear();
  eh_frame_space_.Clear();
@@ -367,6 +386,7 @@ bool BacktraceOffline::FindProcInfo(unw_addr_space_t addr_space, uint64_t ip,
      }
    }
  }
  error_.error_code = BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED;
  return false;
}

@@ -548,6 +568,10 @@ bool BacktraceOffline::ReadReg(size_t reg, uint64_t* value) {
  UNUSED(value);
  result = false;
#endif
  if (!result) {
    error_.error_code = BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED;
    error_.error_info.regno = reg;
  }
  return result;
}

+1 −3
Original line number Diff line number Diff line
@@ -32,9 +32,7 @@ struct Space {
  uint64_t end;
  const uint8_t* data;

  Space() {
    Clear();
  }
  Space() { Clear(); }

  void Clear();
  size_t Read(uint64_t addr, uint8_t* buffer, size_t size);
+2 −2
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon
    int ret = unw_getcontext(&context_);
    if (ret < 0) {
      BACK_LOGW("unw_getcontext failed %d", ret);
      error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
      error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
      return false;
    }
  } else {
@@ -93,7 +93,7 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon
  int ret = unw_init_local(cursor.get(), &context_);
  if (ret < 0) {
    BACK_LOGW("unw_init_local failed %d", ret);
    error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
    error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
    return false;
  }
  initialized_ = true;
Loading