std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
  *offset = 0;
  char buf[512];
  unw_word_t value;
  if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf),
                              &value, &context_) >= 0 && buf[0] != '\0') {
    *offset = static_cast<uintptr_t>(value);
    return buf;
  }
  return "";
}
Beispiel #2
0
std::string UnwindPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
  *offset = 0;
  char buf[512];
  unw_word_t value;
  if (unw_get_proc_name_by_ip(addr_space_, pc, buf, sizeof(buf), &value,
                              upt_info_) >= 0 && buf[0] != '\0') {
    *offset = static_cast<uintptr_t>(value);
    return buf;
  }
  return "";
}
char* local_get_proc_name(const backtrace_t* backtrace, uintptr_t pc,
                          uintptr_t* offset) {
  unw_context_t* context = (unw_context_t*)backtrace->private_data;
  char buf[512];

  *offset = 0;
  unw_word_t value;
  if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf),
                              &value, context) >= 0 && buf[0] != '\0') {
    *offset = (uintptr_t)value;
    char* symbol = demangle_symbol_name(buf);
    if (!symbol) {
      symbol = strdup(buf);
    }
    return symbol;
  }
  return NULL;
}
std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
  if (!initialized_) {
    // If init local is not called, then trying to get a function name will
    // fail, so try to initialize first.
    std::unique_ptr<unw_cursor_t> cursor(new unw_cursor_t);
    if (unw_init_local(cursor.get(), &context_) < 0) {
      return "";
    }
    initialized_ = true;
  }

  *offset = 0;
  char buf[512];
  unw_word_t value;
  if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf),
                              &value, &context_) >= 0 && buf[0] != '\0') {
    *offset = static_cast<uintptr_t>(value);
    return buf;
  }
  return "";
}
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 ();
}