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

Commit 283ca306 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Use Unwinder object for unwind tool."

parents 9e6c11da ae3b1365
Loading
Loading
Loading
Loading
+6 −108
Original line number Diff line number Diff line
@@ -26,17 +26,11 @@
#include <sys/types.h>
#include <unistd.h>

#include <memory>
#include <string>
#include <vector>

#include <android-base/stringprintf.h>

#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
#include <unwindstack/Unwinder.h>

static bool Attach(pid_t pid) {
  if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
@@ -55,66 +49,6 @@ static bool Attach(pid_t pid) {
  return false;
}

static bool Detach(pid_t pid) {
  return ptrace(PTRACE_DETACH, pid, 0, 0) == 0;
}

std::string GetFrameInfo(size_t frame_num, unwindstack::Regs* regs,
                         const std::shared_ptr<unwindstack::Memory>& process_memory,
                         unwindstack::MapInfo* map_info, uint64_t* rel_pc) {
  bool bits32;
  switch (regs->MachineType()) {
    case EM_ARM:
    case EM_386:
      bits32 = true;
      break;

    default:
      bits32 = false;
  }

  if (map_info == nullptr) {
    if (bits32) {
      return android::base::StringPrintf("  #%02zu pc %08" PRIx64, frame_num, regs->pc());
    } else {
      return android::base::StringPrintf("  #%02zu pc %016" PRIx64, frame_num, regs->pc());
    }
  }

  unwindstack::Elf* elf = map_info->GetElf(process_memory, true);
  *rel_pc = elf->GetRelPc(regs->pc(), map_info);
  uint64_t adjusted_rel_pc = *rel_pc;
  // Don't need to adjust the first frame pc.
  if (frame_num != 0) {
    adjusted_rel_pc = regs->GetAdjustedPc(*rel_pc, elf);
  }

  std::string line;
  if (bits32) {
    line = android::base::StringPrintf("  #%02zu pc %08" PRIx64, frame_num, adjusted_rel_pc);
  } else {
    line = android::base::StringPrintf("  #%02zu pc %016" PRIx64, frame_num, adjusted_rel_pc);
  }
  if (!map_info->name.empty()) {
    line += "  " + map_info->name;
    if (map_info->elf_offset != 0) {
      line += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", map_info->elf_offset);
    }
  } else {
    line += android::base::StringPrintf("  <anonymous:%" PRIx64 ">", map_info->offset);
  }
  uint64_t func_offset;
  std::string func_name;
  if (elf->GetFunctionName(adjusted_rel_pc, &func_name, &func_offset)) {
    line += " (" + func_name;
    if (func_offset != 0) {
      line += android::base::StringPrintf("+%" PRId64, func_offset);
    }
    line += ')';
  }
  return line;
}

void DoUnwind(pid_t pid) {
  unwindstack::RemoteMaps remote_maps(pid);
  if (!remote_maps.Parse()) {
@@ -149,48 +83,12 @@ void DoUnwind(pid_t pid) {
  printf("\n");

  auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
  bool return_address_attempt = false;
  std::vector<std::string> frames;
  for (size_t frame_num = 0; frame_num < 64; frame_num++) {
    unwindstack::MapInfo* map_info = remote_maps.Find(regs->pc());
    uint64_t rel_pc;
    frames.push_back(GetFrameInfo(frame_num, regs, process_memory, map_info, &rel_pc));
    bool stepped;
    if (map_info == nullptr) {
      stepped = false;
    } else {
      bool finished;
      stepped =
          map_info->elf->Step(rel_pc + map_info->elf_offset, regs, process_memory.get(), &finished);
      if (stepped && finished) {
        break;
      }
    }
    if (!stepped) {
      if (return_address_attempt) {
        // We tried the return address and it didn't work, remove the last
        // two frames. If this bad frame is the only frame, only remove
        // the last frame.
        frames.pop_back();
        if (frame_num != 1) {
          frames.pop_back();
        }
        break;
      } else {
        // Steping didn't work, try this secondary method.
        if (!regs->SetPcFromReturnAddress(process_memory.get())) {
          break;
        }
        return_address_attempt = true;
      }
    } else {
      return_address_attempt = false;
    }
  }
  unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory);
  unwinder.Unwind();

  // Print the frames.
  for (auto& frame : frames) {
    printf("%s\n", frame.c_str());
  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
    printf("%s\n", unwinder.FormatFrame(i).c_str());
  }
}

@@ -208,7 +106,7 @@ int main(int argc, char** argv) {

  DoUnwind(pid);

  Detach(pid);
  ptrace(PTRACE_DETACH, pid, 0, 0);

  return 0;
}