Skip to content

Instantly share code, notes, and snippets.

@s1341
Created June 9, 2021 04:04
Show Gist options
  • Select an option

  • Save s1341/d7357e8c5a6e84a2ed6ea00f77ceead8 to your computer and use it in GitHub Desktop.

Select an option

Save s1341/d7357e8c5a6e84a2ed6ea00f77ceead8 to your computer and use it in GitHub Desktop.

Revisions

  1. s1341 created this gist Jun 9, 2021.
    144 changes: 144 additions & 0 deletions stalker-arm64x.cxx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,144 @@
    /*
    * Copyright (C) 2008-2010 Ole André Vadla Ravnås <[email protected]>
    *
    * Licence: wxWindows Library Licence, Version 3.1
    */

    #include "stalker-arm64-fixture.c"
    #include <functional>

    #define PRINT_BACKTRACES 1

    G_BEGIN_DECLS

    TESTLIST_BEGIN (stalker_cxx)
    TESTENTRY (unwind_exception)
    TESTENTRY (backtrace)
    TESTLIST_END ()

    static void copying_transform (GumStalkerIterator * iterator, GumStalkerOutput * output,
    gpointer user_data);
    static void frame_zero (GumReturnAddressArray * return_addresses);
    static void frame_one (GumReturnAddressArray * return_addresses);
    static void frame_two (GumReturnAddressArray * return_addresses);
    static void do_backtrace (GumReturnAddressArray * return_addresses);
    extern "C" int exception_func ();
    #ifdef PRINT_BACKTRACES
    static void print_backtrace (GumReturnAddressArray * ret_addrs);
    #endif

    __attribute__((optnone))
    TESTCASE (unwind_exception)
    {
    GumMemoryRange range_before, range_after;

    range_after.base_address = (GumAddress) ((guint64) exception_func + 0x100);
    range_after.size = 0xffffffffffffffff - range_after.base_address;
    gum_stalker_exclude (fixture->stalker, &range_after);

    gum_stalker_set_trust_threshold (fixture->stalker, 0);
    gum_stalker_follow_me (fixture->stalker, fixture->transformer, NULL);

    g_assert_cmpint (exception_func(), ==, 42);

    gum_stalker_unfollow_me (fixture->stalker);
    }

    extern "C" int
    __attribute__((optnone))
    exception_func () {
    try {
    throw "5";
    }
    catch (int ex_int) {
    g_print("caught an unhandled int exception:\n%d\n", ex_int);
    }
    catch (const std::exception& ex) {
    g_print("caught an unhandled C++ exception:\n%s\n", ex.what());
    }
    catch(...) {
    g_print("caught an unhandled C++ exception!\n");
    }
    return 42;
    }

    __attribute__((optnone))
    TESTCASE (backtrace)
    {
    GumReturnAddressArray return_addresses = { 0, };
    GumMemoryRange range_before, range_after;

    range_after.base_address = (GumAddress) ((guint64) do_backtrace + 0x200);
    range_after.size = 0xffffffffffffffff - range_after.base_address;
    gum_stalker_exclude (fixture->stalker, &range_after);

    gum_stalker_set_trust_threshold (fixture->stalker, 0);
    gum_stalker_follow_me (fixture->stalker, fixture->transformer, NULL);

    frame_zero (&return_addresses);
    g_assert_cmpint (return_addresses.len, >, 3);

    gum_stalker_unfollow_me (fixture->stalker);
    }

    static void
    __attribute__((optnone))
    do_backtrace (GumReturnAddressArray * return_addresses)
    {
    GumBacktracer * backtracer = gum_backtracer_make_accurate ();
    gum_backtracer_generate (backtracer, NULL, return_addresses);
    #ifdef PRINT_BACKTRACES
    print_backtrace(return_addresses);
    #endif
    }

    static void
    __attribute__((optnone))
    frame_zero (GumReturnAddressArray * return_addresses)
    {
    frame_one (return_addresses);
    }

    static void
    __attribute__((optnone))
    frame_one (GumReturnAddressArray * return_addresses)
    {
    frame_two (return_addresses);
    }

    static void
    __attribute__((optnone))
    frame_two (GumReturnAddressArray * return_addresses)
    {
    do_backtrace (return_addresses);
    }

    #ifdef PRINT_BACKTRACES
    static void
    print_backtrace (GumReturnAddressArray * ret_addrs)
    {
    guint i;

    g_print ("\n\nBacktrace (%d return addresses):\n", ret_addrs->len);

    for (i = 0; i != ret_addrs->len; i++)
    {
    GumReturnAddress * ra = &ret_addrs->items[i];
    GumReturnAddressDetails rad;

    if (gum_return_address_details_from_address (*ra, &rad))
    {
    g_print (" %p %s!%s %s:%d\n", rad.address, rad.module_name,
    rad.function_name, rad.file_name, rad.line_number);
    }
    else
    {
    g_print (" %p <unknown>\n", ra);
    }
    }

    g_print ("\n\n");
    }
    #endif

    G_END_DECLS