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

Commit 82866421 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Fix pc/function name for signal handler frame.

This refactors the step function slightly to split it up into
distinct pieces since the code needs to handle a signal handler
versus normal step slightly differently.

Add a new error for an invalid elf.

Modify libbacktrace code to handle new error code.

Bug: 130302288

Test: libbacktrace/libunwindstack unit tests.
Change-Id: I3fb9b00c02d2cf2cc5911541bba0346c6f39b8e6
Merged-In: I3fb9b00c02d2cf2cc5911541bba0346c6f39b8e6
(cherry picked from commit d11ed86d)
parent 1dd53f76
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -170,5 +170,7 @@ std::string Backtrace::GetErrorString(BacktraceUnwindError error) {
      return "Failed to unwind due to invalid unwind information";
    case BACKTRACE_UNWIND_ERROR_REPEATED_FRAME:
      return "Failed to unwind due to same sp/pc repeating";
    case BACKTRACE_UNWIND_ERROR_INVALID_ELF:
      return "Failed to unwind due to invalid elf";
  }
}
+4 −0
Original line number Diff line number Diff line
@@ -89,6 +89,10 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
      case unwindstack::ERROR_REPEATED_FRAME:
        error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME;
        break;

      case unwindstack::ERROR_INVALID_ELF:
        error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF;
        break;
    }
  }

+2 −0
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ enum BacktraceUnwindErrorCode : uint32_t {
  BACKTRACE_UNWIND_ERROR_UNWIND_INFO,
  // Unwind information stopped due to sp/pc repeating.
  BACKTRACE_UNWIND_ERROR_REPEATED_FRAME,
  // Unwind information stopped due to invalid elf.
  BACKTRACE_UNWIND_ERROR_INVALID_ELF,
};

struct BacktraceUnwindError {
+10 −9
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ ErrorCode Elf::GetLastErrorCode() {
  if (valid_) {
    return interface_->LastErrorCode();
  }
  return ERROR_NONE;
  return ERROR_INVALID_ELF;
}

uint64_t Elf::GetLastErrorAddress() {
@@ -170,22 +170,23 @@ uint64_t Elf::GetLastErrorAddress() {
  return 0;
}

// The relative pc is always relative to the start of the map from which it comes.
bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory,
               bool* finished) {
// The relative pc expectd by this function is relative to the start of the elf.
bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
  if (!valid_) {
    return false;
  }
  return regs->StepIfSignalHandler(rel_pc, this, process_memory);
}

  // The relative pc expectd by StepIfSignalHandler is relative to the start of the elf.
  if (regs->StepIfSignalHandler(rel_pc, this, process_memory)) {
    *finished = false;
    return true;
// The relative pc is always relative to the start of the map from which it comes.
bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) {
  if (!valid_) {
    return false;
  }

  // Lock during the step which can update information in the object.
  std::lock_guard<std::mutex> guard(lock_);
  return interface_->Step(adjusted_rel_pc, regs, process_memory, finished);
  return interface_->Step(rel_pc, regs, process_memory, finished);
}

bool Elf::IsValidElf(Memory* memory) {
+11 −13
Original line number Diff line number Diff line
@@ -111,6 +111,14 @@ bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_f
      pc_adjustment = 0;
    }
    step_pc -= pc_adjustment;

    bool finished = false;
    if (elf->StepIfSignalHandler(rel_pc, regs.get(), process_memory_.get())) {
      step_pc = rel_pc;
    } else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished)) {
      finished = true;
    }

    // Skip any locations that are within this library.
    if (num_frames != 0 || !ShouldSkipLibrary(map_info->name)) {
      // Add frame information.
@@ -124,22 +132,12 @@ bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_f
      }
      num_frames++;
    }
    if (!elf->valid()) {
      break;
    }
    if (frame_info->size() == max_frames) {
      break;
    }

    adjust_pc = true;
    bool finished;
    if (!elf->Step(rel_pc, step_pc, regs.get(), process_memory_.get(), &finished) || finished) {
      break;
    }
    // pc and sp are the same, terminate the unwind.
    if (cur_pc == regs->pc() && cur_sp == regs->sp()) {
    if (finished || frame_info->size() == max_frames ||
        (cur_pc == regs->pc() && cur_sp == regs->sp())) {
      break;
    }
    adjust_pc = true;
  }
  return num_frames != 0;
}
Loading