示例#1
0
bool UnwindPtrace::Init() {
  if (upt_info_) {
    return true;
  }

  if (addr_space_) {
    // If somehow the addr_space_ gets initialized but upt_info_ doesn't,
    // then that indicates there is some kind of failure.
    return false;
  }

  addr_space_ = unw_create_addr_space(&_UPT_accessors, 0);
  if (!addr_space_) {
    BACK_LOGW("unw_create_addr_space failed.");
    error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
    return false;
  }

  UnwindMap* map = static_cast<UnwindMap*>(GetMap());
  unw_map_set(addr_space_, map->GetMapCursor());

  upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid()));
  if (!upt_info_) {
    BACK_LOGW("Failed to create upt info.");
    error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
    return false;
  }

  return true;
}
示例#2
0
UnwindPtrace::~UnwindPtrace() {
  if (upt_info_) {
    _UPT_destroy(upt_info_);
    upt_info_ = NULL;
  }
  if (addr_space_) {
    // Remove the map from the address space before destroying it.
    // It will be freed in the UnwindMap destructor.
    unw_map_set(addr_space_, NULL);

    unw_destroy_addr_space(addr_space_);
    addr_space_ = NULL;
  }
}
示例#3
0
bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
  if (ucontext) {
    BACK_LOGW("Unwinding from a specified context not supported yet.");
    return false;
  }

  addr_space_ = unw_create_addr_space(&_UPT_accessors, 0);
  if (!addr_space_) {
    BACK_LOGW("unw_create_addr_space failed.");
    return false;
  }

  UnwindMap* map = static_cast<UnwindMap*>(GetMap());
  if (NULL == map) {
    BACK_LOGW("GetMap before unwinding failed.");
    return false;
  }
  unw_map_set(addr_space_, map->GetMapCursor());

  upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid()));
  if (!upt_info_) {
    BACK_LOGW("Failed to create upt info.");
    return false;
  }

  unw_cursor_t cursor;
  if(num_ignore_frames==0xdeaddead)
  	{
  		cursor.opaque[0]=0xdeaddead; //add for tell libunwind to unwind for kernel unwind userspace backtrace,lhd
  		BACK_LOGW(" K2U_bt call into UnwindPtrace::Unwind.");
		num_ignore_frames=0;
  	}
  int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
  if (ret < 0) {
    BACK_LOGW("unw_init_remote failed %d", ret);
    return false;
  }

  std::vector<backtrace_frame_data_t>* frames = GetFrames();
  frames->reserve(MAX_BACKTRACE_FRAMES);
  size_t num_frames = 0;
  do {
    unw_word_t pc;
    ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
    if (ret < 0) {
      BACK_LOGW("Failed to read IP %d", ret);
      break;
    }
    unw_word_t sp;
    ret = unw_get_reg(&cursor, UNW_REG_SP, &sp);
    if (ret < 0) {
      BACK_LOGW("Failed to read SP %d", ret);
      break;
    }

    if (num_ignore_frames == 0) {
      frames->resize(num_frames+1);
      backtrace_frame_data_t* frame = &frames->at(num_frames);
      frame->num = num_frames;
      frame->pc = static_cast<uintptr_t>(pc);
      frame->sp = static_cast<uintptr_t>(sp);
      frame->stack_size = 0;

      if (num_frames > 0) {
        backtrace_frame_data_t* prev = &frames->at(num_frames-1);
        prev->stack_size = frame->sp - prev->sp;
      }

      frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);

      frame->map = FindMap(frame->pc);

      num_frames++;
    } else {
      num_ignore_frames--;
    }
    ret = unw_step (&cursor);
  } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);

  return true;
}
bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
  if (GetMap() == nullptr) {
    // Without a map object, we can't do anything.
    return false;
  }

  if (ucontext) {
    BACK_LOGW("Unwinding from a specified context not supported yet.");
    return false;
  }

  addr_space_ = unw_create_addr_space(&_UPT_accessors, 0);
  if (!addr_space_) {
    BACK_LOGW("unw_create_addr_space failed.");
    return false;
  }

  UnwindMap* map = static_cast<UnwindMap*>(GetMap());
  unw_map_set(addr_space_, map->GetMapCursor());

  upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid()));
  if (!upt_info_) {
    BACK_LOGW("Failed to create upt info.");
    return false;
  }

  unw_cursor_t cursor;
  int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
  if (ret < 0) {
    BACK_LOGW("unw_init_remote failed %d", ret);
    return false;
  }

  size_t num_frames = 0;
  do {
    unw_word_t pc;
    ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
    if (ret < 0) {
      BACK_LOGW("Failed to read IP %d", ret);
      break;
    }
    unw_word_t sp;
    ret = unw_get_reg(&cursor, UNW_REG_SP, &sp);
    if (ret < 0) {
      BACK_LOGW("Failed to read SP %d", ret);
      break;
    }

    if (num_ignore_frames == 0) {
      frames_.resize(num_frames+1);
      backtrace_frame_data_t* frame = &frames_.at(num_frames);
      frame->num = num_frames;
      frame->pc = static_cast<uintptr_t>(pc);
      frame->sp = static_cast<uintptr_t>(sp);
      frame->stack_size = 0;

      if (num_frames > 0) {
        backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
        prev->stack_size = frame->sp - prev->sp;
      }

      frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);

      FillInMap(frame->pc, &frame->map);

      num_frames++;
    } else {
      num_ignore_frames--;
    }
    ret = unw_step (&cursor);
  } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);

  return true;
}
size_t StackCorkscrewLibunwind::Unwind (pid_t ppid, pid_t tid, size_t ignoreDepth, size_t maxDepth)
{
  assert (ppid > 0);

  assert (tid >= ppid);

  (void) ignoreDepth;

  m_frames.clear ();

  if (maxDepth == 0)
  {
    return 0;
  }

  static unw_addr_space_t addr_space;

  (void) addr_space;

#if UNWIND_SUPPORTED && UNWIND_REMOTE_SUPPORTED

  addr_space = unw_create_addr_space (&_UPT_accessors, 0);

  if (!addr_space)
  {
    fprintf (stderr, "unw_create_addr_space failed.\n");

    fflush (stderr);

    return 0;
  }

#endif

#if UNWIND_MAP_SUPPORTED && UNWIND_FUNCTION_NAME

  unw_map_cursor_t map_cursor;

  if (unw_map_cursor_create (&map_cursor, tid) < 0)
  {
    fprintf (stderr, "Failed to create map cursor.\n");

    fflush (stderr);

    return 0;
  }

  unw_map_set (addr_space, &map_cursor);

#endif

#if UNWIND_REMOTE_SUPPORTED

  struct UPT_info* upt_info = reinterpret_cast<struct UPT_info*> (_UPT_create (tid));

  if (!upt_info)
  {
    fprintf (stderr, "Failed to create upt info.\n");

    fflush (stderr);

    return 0;
  }

  unw_cursor_t cursor;

  {
    int error = unw_init_remote (&cursor, addr_space, upt_info);

    if (error < 0)
    {
      fprintf (stderr, "unw_init_remote failed (%d)\n", error);

      fflush (stderr);

      return 0;
    }
  }

#endif

  bool shouldContinue = false;

  size_t numFrames = 0;

  do
  {
    //
    // Evaluate instruction pointer / program counter address.
    //

#if UNWIND_REMOTE_SUPPORTED

    uint64_t pc = 0;

    {
      unw_word_t unwound_pc;

      int error = unw_get_reg (&cursor, UNW_REG_IP, &unwound_pc);

      if (error < 0)
      {
        fprintf (stderr, "Failed to read IP (%d)\n", error);

        fflush (stderr);

        break;
      }

      pc = unwound_pc;
    }

#if UNWIND_STACK_POINTER

    uint64_t sp = 0;

    {
      unw_word_t unwound_sp;

      int error = unw_get_reg (&cursor, UNW_REG_SP, &unwound_sp);

      if (error < 0)
      {
        fprintf (stderr, "Failed to read SP (%d)\n", error);

        fflush (stderr);

        break;
      }

      sp = unwound_sp;
    }

#endif

    if (ignoreDepth == 0)
    {
      const char *function = "??";

#if UNWIND_FUNCTION_NAME

      uintptr_t offset = 0;

      char buffer [128];

      unw_word_t value;

      const int result = unw_get_proc_name_by_ip (addr_space, pc, buffer, sizeof (buffer), &value, upt_info);

      if (result >= 0 && buffer [0] != '\0')
      {
        function = buffer;

        offset = static_cast<uintptr_t>(value);
      }

#endif

      StackFrame frame;

      frame.m_level = numFrames;

      frame.m_pc = pc;

#if UNWIND_STACK_POINTER

      frame.m_sp = sp;

#endif

      strncpy (frame.m_function, function, sizeof (frame.m_function));

      m_frames.push_back (frame);

      numFrames++;
    }
    else
    {
      ignoreDepth--;
    }

    shouldContinue = (unw_step (&cursor) > 0);

#endif
  }
  while (shouldContinue && numFrames < maxDepth);

#if UNWIND_REMOTE_SUPPORTED

  _UPT_destroy (upt_info);

#endif

#if UNWIND_MAP_SUPPORTED && UNWIND_FUNCTION_NAME

  unw_map_cursor_destroy (&map_cursor);

  unw_map_cursor_clear (&map_cursor);

#endif

  return m_frames.size ();
}