size_t Call6(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
  std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
  unwindstack::RegsGetLocal(regs.get());
  unwindstack::Unwinder unwinder(32, maps, regs.get(), process_memory);
  unwinder.Unwind();
  return unwinder.NumFrames();
}
Ejemplo n.º 2
0
void DoUnwind(pid_t pid) {
  unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
  if (regs == nullptr) {
    printf("Unable to get remote reg data\n");
    return;
  }

  printf("ABI: ");
  switch (regs->Arch()) {
    case unwindstack::ARCH_ARM:
      printf("arm");
      break;
    case unwindstack::ARCH_X86:
      printf("x86");
      break;
    case unwindstack::ARCH_ARM64:
      printf("arm64");
      break;
    case unwindstack::ARCH_X86_64:
      printf("x86_64");
      break;
    case unwindstack::ARCH_MIPS:
      printf("mips");
      break;
    case unwindstack::ARCH_MIPS64:
      printf("mips64");
      break;
    default:
      printf("unknown\n");
      return;
  }
  printf("\n");

  unwindstack::UnwinderFromPid unwinder(1024, pid);
  if (!unwinder.Init(regs->Arch())) {
    printf("Failed to init unwinder object.\n");
    return;
  }

  unwinder.SetRegs(regs);
  unwinder.Unwind();

  // Print the frames.
  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
    printf("%s\n", unwinder.FormatFrame(i).c_str());
  }
}
Ejemplo n.º 3
0
void DoUnwind(pid_t pid) {
  unwindstack::RemoteMaps remote_maps(pid);
  if (!remote_maps.Parse()) {
    printf("Failed to parse map data.\n");
    return;
  }

  unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
  if (regs == nullptr) {
    printf("Unable to get remote reg data\n");
    return;
  }

  printf("ABI: ");
  switch (regs->MachineType()) {
    case EM_ARM:
      printf("arm");
      break;
    case EM_386:
      printf("x86");
      break;
    case EM_AARCH64:
      printf("arm64");
      break;
    case EM_X86_64:
      printf("x86_64");
      break;
    default:
      printf("unknown\n");
      return;
  }
  printf("\n");

  auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
  unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory);
  unwinder.Unwind();

  // Print the frames.
  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
    printf("%s\n", unwinder.FormatFrame(i).c_str());
  }
}
int SaveData(pid_t pid) {
  unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
  if (regs == nullptr) {
    printf("Unable to get remote reg data.\n");
    return 1;
  }

  // Save the current state of the registers.
  if (!SaveRegs(regs)) {
    return 1;
  }

  // Do an unwind so we know how much of the stack to save, and what
  // elf files are involved.
  unwindstack::UnwinderFromPid unwinder(1024, pid);
  if (!unwinder.Init(regs->Arch())) {
    printf("Unable to init unwinder object.\n");
    return 1;
  }
  unwinder.SetRegs(regs);
  uint64_t sp = regs->sp();
  unwinder.Unwind();

  std::unordered_map<uint64_t, map_info_t> maps_by_start;
  std::vector<std::pair<uint64_t, uint64_t>> stacks;
  unwindstack::Maps* maps = unwinder.GetMaps();
  uint64_t sp_map_start = 0;
  unwindstack::MapInfo* map_info = maps->Find(sp);
  if (map_info != nullptr) {
    stacks.emplace_back(std::make_pair(sp, map_info->end));
    sp_map_start = map_info->start;
  }

  for (const auto& frame : unwinder.frames()) {
    map_info = maps->Find(frame.sp);
    if (map_info != nullptr && sp_map_start != map_info->start) {
      stacks.emplace_back(std::make_pair(frame.sp, map_info->end));
      sp_map_start = map_info->start;
    }

    if (maps_by_start.count(frame.map_start) == 0) {
      map_info = maps->Find(frame.map_start);

      auto info = FillInAndGetMapInfo(maps_by_start, map_info);
      bool file_copied = false;
      SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);

      // If you are using a a linker that creates two maps (one read-only, one
      // read-executable), it's necessary to capture the previous map
      // information if needed.
      unwindstack::MapInfo* prev_map = map_info->prev_map;
      if (prev_map != nullptr && map_info->offset != 0 && prev_map->offset == 0 &&
          prev_map->flags == PROT_READ && map_info->name == prev_map->name &&
          maps_by_start.count(prev_map->start) == 0) {
        info = FillInAndGetMapInfo(maps_by_start, prev_map);
        SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
      }
    }
  }

  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
    printf("%s\n", unwinder.FormatFrame(i).c_str());
  }

  if (!SaveStack(pid, stacks)) {
    return 1;
  }

  std::vector<std::pair<uint64_t, map_info_t>> sorted_maps(maps_by_start.begin(),
                                                           maps_by_start.end());
  std::sort(sorted_maps.begin(), sorted_maps.end(),
            [](auto& a, auto& b) { return a.first < b.first; });

  std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("maps.txt", "w+"), &fclose);
  if (fp == nullptr) {
    perror("Failed to create maps.txt");
    return false;
  }

  for (auto& element : sorted_maps) {
    char perms[5] = {"---p"};
    map_info_t& map = element.second;
    if (map.flags & PROT_READ) {
      perms[0] = 'r';
    }
    if (map.flags & PROT_WRITE) {
      perms[1] = 'w';
    }
    if (map.flags & PROT_EXEC) {
      perms[2] = 'x';
    }
    fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " 00:00 0", map.start, map.end, perms,
            map.offset);
    if (!map.name.empty()) {
      fprintf(fp.get(), "   %s", map.name.c_str());
    }
    fprintf(fp.get(), "\n");
  }

  return 0;
}
Ejemplo n.º 5
0
bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
                       std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
                       std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
  UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
  auto process_memory = stack_map->process_memory();
  unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
                                 regs, stack_map->process_memory());
  unwinder.SetResolveNames(stack_map->ResolveNames());
  stack_map->SetArch(regs->Arch());
  if (stack_map->GetJitDebug() != nullptr) {
    unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
  }
#if !defined(NO_LIBDEXFILE_SUPPORT)
  if (stack_map->GetDexFiles() != nullptr) {
    unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch());
  }
#endif
  unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
  if (error != nullptr) {
    switch (unwinder.LastErrorCode()) {
      case unwindstack::ERROR_NONE:
        error->error_code = BACKTRACE_UNWIND_NO_ERROR;
        break;

      case unwindstack::ERROR_MEMORY_INVALID:
        error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED;
        error->error_info.addr = unwinder.LastErrorAddress();
        break;

      case unwindstack::ERROR_UNWIND_INFO:
        error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO;
        break;

      case unwindstack::ERROR_UNSUPPORTED:
        error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
        break;

      case unwindstack::ERROR_INVALID_MAP:
        error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
        break;

      case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
        error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT;
        break;

      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;
    }
  }

  if (num_ignore_frames >= unwinder.NumFrames()) {
    frames->resize(0);
    return true;
  }

  auto unwinder_frames = unwinder.frames();
  frames->resize(unwinder.NumFrames() - num_ignore_frames);
  size_t cur_frame = 0;
  for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) {
    auto frame = &unwinder_frames[i];

    backtrace_frame_data_t* back_frame = &frames->at(cur_frame);

    back_frame->num = cur_frame++;

    back_frame->rel_pc = frame->rel_pc;
    back_frame->pc = frame->pc;
    back_frame->sp = frame->sp;

    back_frame->func_name = demangle(frame->function_name.c_str());
    back_frame->func_offset = frame->function_offset;

    back_frame->map.name = frame->map_name;
    back_frame->map.start = frame->map_start;
    back_frame->map.end = frame->map_end;
    back_frame->map.offset = frame->map_elf_start_offset;
    back_frame->map.load_bias = frame->map_load_bias;
    back_frame->map.flags = frame->map_flags;
  }

  return true;
}