Esempio n. 1
0
static void
gum_gcc_backtracer_generate (GumBacktracer * backtracer,
                             const GumCpuContext * cpu_context,
                             GumReturnAddressArray * return_addresses)
{
  GumGccBacktraceCtx btctx;

  btctx.return_addresses = return_addresses;
  if (cpu_context != NULL)
  {
#ifdef HAVE_I386
    btctx.start_address = GSIZE_TO_POINTER (GUM_CPU_CONTEXT_XSP (cpu_context));
#else
    btctx.start_address = GSIZE_TO_POINTER (cpu_context->sp);
#endif
  }
  else
  {
    btctx.start_address = ((gsize *) &return_addresses) + 1;
  }

  return_addresses->len = 0;
  _Unwind_Backtrace (gum_gcc_backtracer_append_address, &btctx);
}
Esempio n. 2
0
static void
gum_x86_backtracer_generate (GumBacktracer * backtracer,
                             const GumCpuContext * cpu_context,
                             GumReturnAddressArray * return_addresses)
{
  GumX86Backtracer * self = GUM_X86_BACKTRACER_CAST (backtracer);
  GumX86BacktracerPrivate * priv = self->priv;
  GumInvocationStack * invocation_stack;
  gsize * start_address;
  gsize first_address = 0;
  guint i;
  gsize * p;

  invocation_stack = gum_interceptor_get_current_stack ();

  if (cpu_context != NULL)
    start_address = GSIZE_TO_POINTER (GUM_CPU_CONTEXT_XSP (cpu_context));
  else
    start_address = (gsize *) &backtracer;

  for (i = 0, p = start_address; p < start_address + 2048; p++)
  {
    gboolean valid = FALSE;
    gsize value;
    GumMemoryRange vr;

    if ((GPOINTER_TO_SIZE (p) & (4096 - 1)) == 0)
    {
      GumMemoryRange next_range;
      next_range.base_address = GUM_ADDRESS (p);
      next_range.size = 4096;
      if (!gum_memory_map_contains (priv->writable, &next_range))
        break;
    }

    value = *p;
    vr.base_address = value - 6;
    vr.size = 6;

    if (value != first_address && value > 4096 + 6 &&
        gum_memory_map_contains (priv->code, &vr))
    {
      gsize translated_value;

      translated_value = GPOINTER_TO_SIZE (gum_invocation_stack_translate (
          invocation_stack, GSIZE_TO_POINTER (value)));
      if (translated_value != value)
      {
        value = translated_value;
        valid = TRUE;
      }
      else
      {
        guint8 * code_ptr = GSIZE_TO_POINTER (value);

        if (*(code_ptr - 5) == OPCODE_CALL_NEAR_RELATIVE ||
            *(code_ptr - 6) == OPCODE_CALL_NEAR_ABS_INDIRECT ||
            *(code_ptr - 3) == OPCODE_CALL_NEAR_ABS_INDIRECT ||
            *(code_ptr - 2) == OPCODE_CALL_NEAR_ABS_INDIRECT)
        {
          valid = TRUE;
        }
      }
    }

    if (valid)
    {
      return_addresses->items[i++] = GSIZE_TO_POINTER (value);
      if (i == G_N_ELEMENTS (return_addresses->items))
        break;

      if (first_address == 0)
        first_address = value;
    }
  }

  return_addresses->len = i;
}