예제 #1
0
static void
gum_sanity_checker_print_instance_leaks_details (GumSanityChecker * self,
                                                 GumList * stale)
{
  GumList * instances, * walk;

  instances = gum_list_copy (stale);
  instances = gum_list_sort_with_data (instances,
      gum_sanity_checker_compare_instances, self);

  gum_sanity_checker_print (self, "\tAddress\t\tRefCount\tGType\n");
  gum_sanity_checker_print (self, "\t--------\t--------\t-----\n");

  for (walk = instances; walk != NULL; walk = walk->next)
  {
    GumInstanceDetails details;

    gum_sanity_checker_details_from_instance (self, &details, walk->data);

    gum_sanity_checker_printf (self, "\t%p\t%d%s\t%s\n",
        details.address,
        details.ref_count,
        details.ref_count <= 9 ? "\t" : "",
        details.type_name);
  }

  gum_list_free (instances);
}
예제 #2
0
static void
gum_sanity_checker_print_block_leaks_summary (GumSanityChecker * self,
                                              GumList * block_groups)
{
  GumList * groups, * walk;

  groups = gum_list_copy (block_groups);
  groups = gum_list_sort_with_data (groups,
      gum_sanity_checker_compare_groups, self);

  gum_sanity_checker_print (self, "\tCount\tSize\n");
  gum_sanity_checker_print (self, "\t-----\t----\n");

  for (walk = groups; walk != NULL; walk = walk->next)
  {
    GumAllocationGroup * group = (GumAllocationGroup *) walk->data;

    if (group->alive_now == 0)
      continue;

    gum_sanity_checker_printf (self, "\t%u\t%u\n",
        group->alive_now, group->size);
  }

  gum_list_free (groups);
}
예제 #3
0
static void
gum_sanity_checker_print_instance_leaks_summary (GumSanityChecker * self,
                                                 GumList * stale)
{
  GumHashTable * count_by_type;
  GumList * walk, * keys;

  count_by_type = gum_sanity_checker_count_leaks_by_type_name (self, stale);

  keys = gum_hash_table_get_keys (count_by_type);
  keys = gum_list_sort_with_data (keys,
      gum_sanity_checker_compare_type_names, count_by_type);

  gum_sanity_checker_print (self, "\tCount\tGType\n");
  gum_sanity_checker_print (self, "\t-----\t-----\n");

  for (walk = keys; walk != NULL; walk = walk->next)
  {
    const gchar * type_name = (const gchar *) walk->data;
    guint count;

    count = GPOINTER_TO_UINT (gum_hash_table_lookup (count_by_type,
        type_name));
    gum_sanity_checker_printf (self, "\t%u\t%s\n", count, type_name);
  }

  gum_list_free (keys);

  gum_hash_table_unref (count_by_type);
}
예제 #4
0
void
gum_code_allocator_free (GumCodeAllocator * allocator)
{
  gum_list_foreach (allocator->pages, (GFunc) gum_code_page_free, NULL);
  gum_list_free (allocator->pages);
  allocator->pages = NULL;
}
예제 #5
0
void
gum_cobject_list_free (GumList * cobject_list)
{
  GumList * walk;

  for (walk = cobject_list; walk != NULL; walk = walk->next)
  {
    GumCObject * cobject = walk->data;
    gum_cobject_free (cobject);
  }

  gum_list_free (cobject_list);
}
예제 #6
0
void
gum_allocation_block_list_free (GumList * block_list)
{
  GumList * cur;

  for (cur = block_list; cur != NULL; cur = cur->next)
  {
    GumAllocationBlock * block = cur->data;
    gum_allocation_block_free (block);
  }

  gum_list_free (block_list);
}
예제 #7
0
static void
gum_sanity_checker_print_block_leaks_details (GumSanityChecker * self,
                                              GumList * stale)
{
  GumList * blocks, * walk;

  blocks = gum_list_copy (stale);
  blocks = gum_list_sort_with_data (blocks,
      gum_sanity_checker_compare_blocks, self);

  gum_sanity_checker_print (self, "\tAddress\t\tSize\n");
  gum_sanity_checker_print (self, "\t--------\t----\n");

  for (walk = blocks; walk != NULL; walk = walk->next)
  {
    GumAllocationBlock * block = (GumAllocationBlock *) walk->data;
    guint i;

    gum_sanity_checker_printf (self, "\t%p\t%u\n",
        block->address, block->size);

    for (i = 0; i != block->return_addresses.len; i++)
    {
      GumReturnAddress addr = block->return_addresses.items[i];
      GumReturnAddressDetails rad;

      if (gum_return_address_details_from_address (addr, &rad))
      {
        gchar * file_basename;

        file_basename = g_path_get_basename (rad.file_name);
        gum_sanity_checker_printf (self, "\t    %p %s!%s %s:%u\n",
            rad.address,
            rad.module_name, rad.function_name,
            file_basename, rad.line_number);
        g_free (file_basename);
      }
      else
      {
        gum_sanity_checker_printf (self, "\t    %p\n", addr);
      }
    }
  }

  gum_list_free (blocks);
}
예제 #8
0
gboolean
gum_sanity_checker_end (GumSanityChecker * self)
{
  GumSanityCheckerPrivate * priv = self->priv;
  gboolean all_checks_passed = TRUE;

  if (priv->bounds_checker != NULL)
  {
    gum_bounds_checker_detach (priv->bounds_checker);

    g_object_unref (priv->bounds_checker);
    priv->bounds_checker = NULL;
  }

  if (priv->instance_tracker != NULL)
  {
    GumList * stale_instances;

    gum_instance_tracker_end (priv->instance_tracker);

    stale_instances =
        gum_instance_tracker_peek_instances (priv->instance_tracker);

    if (stale_instances != NULL)
    {
      all_checks_passed = FALSE;

      gum_sanity_checker_printf (self, "Instance leaks detected:\n\n");
      gum_sanity_checker_print_instance_leaks_summary (self, stale_instances);
      gum_sanity_checker_print (self, "\n");
      gum_sanity_checker_print_instance_leaks_details (self, stale_instances);

      gum_list_free (stale_instances);
    }

    g_object_unref (priv->instance_tracker);
    priv->instance_tracker = NULL;
  }

  if (priv->alloc_probe != NULL)
  {
    GumList * stale_blocks;

    gum_allocator_probe_detach (priv->alloc_probe);

    stale_blocks =
        gum_allocation_tracker_peek_block_list (priv->alloc_tracker);

    if (stale_blocks != NULL)
    {
      if (all_checks_passed)
      {
        GumList * block_groups;

        block_groups =
            gum_allocation_tracker_peek_block_groups (priv->alloc_tracker);

        gum_sanity_checker_printf (self, "Block leaks detected:\n\n");
        gum_sanity_checker_print_block_leaks_summary (self, block_groups);
        gum_sanity_checker_print (self, "\n");
        gum_sanity_checker_print_block_leaks_details (self, stale_blocks);

        gum_allocation_group_list_free (block_groups);
      }

      all_checks_passed = FALSE;

      gum_allocation_block_list_free (stale_blocks);
    }

    g_object_unref (priv->alloc_probe);
    priv->alloc_probe = NULL;

    g_object_unref (priv->alloc_tracker);
    priv->alloc_tracker = NULL;
  }

  return all_checks_passed;
}