Skip to content

Commit

Permalink
Add QJS bindings for sampler
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed May 17, 2024
1 parent 3e755c9 commit 8b15ecc
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 0 deletions.
141 changes: 141 additions & 0 deletions bindings/gumjs/gumquicksampler.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright (C) 2022 Ole André Vadla Ravnås <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#include "gumquicksampler.h"

#include "gumquickmacros.h"

#include <gum/gum-prof.h>

GUMJS_DECLARE_CONSTRUCTOR (gumjs_sampler_construct)
GUMJS_DECLARE_FUNCTION (gumjs_sampler_sample)
GUMJS_DECLARE_FINALIZER (gumjs_sampler_finalize)

GUMJS_DECLARE_CONSTRUCTOR (gumjs_wallclock_sampler_construct)

static const JSClassDef gumjs_file_def =
{
.class_name = "Sampler",
.finalizer = gumjs_sampler_finalize,
};

static const JSCFunctionListEntry gumjs_sampler_functions[] =
{
JS_CFUNC_DEF ("sample", 0, gumjs_sampler_sample),
};

static const JSClassDef gumjs_native_wallclock_stream_def =
{
.class_name = "WallClockSampler",
};

void
_gum_quick_sampler_init (GumQuickSampler * self,
JSValue ns,
GumQuickCore * core)
{
JSContext * ctx = core->ctx;
JSValue proto, ctor;

self->core = core;

_gum_quick_core_store_module_data (core, "sampler", self);

_gum_quick_create_class (ctx, &gumjs_file_def, core, &self->sampler_class,
&proto);
ctor = JS_NewCFunction2 (ctx, gumjs_sampler_construct,
gumjs_file_def.class_name, 0, JS_CFUNC_constructor, 0);
JS_SetConstructor (ctx, ctor, proto);
JS_SetPropertyFunctionList (ctx, proto, gumjs_sampler_functions,
G_N_ELEMENTS (gumjs_sampler_functions));
JS_DefinePropertyValueStr (ctx, ns, gumjs_file_def.class_name, ctor,
JS_PROP_C_W_E);

_gum_quick_create_subclass (ctx, &gumjs_native_wallclock_stream_def,
self->sampler_class, proto, core,
&self->wallclock_sampler_class, &proto);
ctor = JS_NewCFunction2 (ctx, gumjs_wallclock_sampler_construct,
gumjs_native_wallclock_stream_def.class_name, 0, JS_CFUNC_constructor, 0);
JS_SetConstructor (ctx, ctor, proto);
JS_DefinePropertyValueStr (ctx, ns,
gumjs_native_wallclock_stream_def.class_name, ctor, JS_PROP_C_W_E);

_gum_quick_object_manager_init (&self->objects, self, core);
}

void
_gum_quick_sampler_flush (GumQuickSampler * self)
{
_gum_quick_object_manager_flush (&self->objects);
}

void
_gum_quick_sampler_dispose (GumQuickSampler * self)
{
_gum_quick_object_manager_free (&self->objects);
}

void
_gum_quick_sampler_finalize (GumQuickSampler * self)
{
}

GUMJS_DEFINE_FINALIZER (gumjs_sampler_finalize)
{
}

GUMJS_DEFINE_CONSTRUCTOR (gumjs_sampler_construct)
{
return _gum_quick_throw_literal (ctx, "not user-instantiable");
}

static GumQuickSampler *
gumjs_get_parent_module (GumQuickCore * core)
{
return _gum_quick_core_load_module_data (core, "sampler");
}

static gboolean
gum_sampler_get (JSContext * ctx,
JSValueConst val,
GumQuickCore * core,
GumSampler ** sampler)
{
return _gum_quick_unwrap (ctx, val,
gumjs_get_parent_module (core)->sampler_class, core,
(gpointer *) sampler);
}

GUMJS_DEFINE_FUNCTION (gumjs_sampler_sample)
{
GumSampler * self;
GumSample sample;

if (!gum_sampler_get (ctx, this_val, core, &self))
return JS_EXCEPTION;

sample = gum_sampler_sample (self);

return _gum_quick_uint64_new (ctx, sample, core);
}

GUMJS_DEFINE_CONSTRUCTOR (gumjs_wallclock_sampler_construct)
{
GumQuickSampler * parent;
GumSampler * sampler;

parent = gumjs_get_parent_module (core);

JSValue wrapper = JS_NewObjectClass (ctx, parent->sampler_class);

sampler = gum_wallclock_sampler_new ();

_gum_quick_object_manager_add (&parent->objects, ctx, wrapper, sampler);

JS_SetOpaque (wrapper, sampler);

return wrapper;
}
34 changes: 34 additions & 0 deletions bindings/gumjs/gumquicksampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2022 Ole André Vadla Ravnås <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#ifndef __GUM_QUICK_SAMPLER_H__
#define __GUM_QUICK_SAMPLER_H__

#include "gumquickobject.h"

G_BEGIN_DECLS

typedef struct _GumQuickSampler GumQuickSampler;

struct _GumQuickSampler
{
GumQuickCore * core;

JSClassID sampler_class;
JSClassID wallclock_sampler_class;

GumQuickObjectManager objects;
};

G_GNUC_INTERNAL void _gum_quick_sampler_init (GumQuickSampler * self,
JSValue ns, GumQuickCore * core);
G_GNUC_INTERNAL void _gum_quick_sampler_flush (GumQuickSampler * self);
G_GNUC_INTERNAL void _gum_quick_sampler_dispose (GumQuickSampler * self);
G_GNUC_INTERNAL void _gum_quick_sampler_finalize (GumQuickSampler * self);

G_END_DECLS

#endif
6 changes: 6 additions & 0 deletions bindings/gumjs/gumquickscript.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "gumquickmemory.h"
#include "gumquickmodule.h"
#include "gumquickprocess.h"
#include "gumquicksampler.h"
#include "gumquickscript-priv.h"
#include "gumquickscript-runtime.h"
#include "gumquickscriptbackend-priv.h"
Expand Down Expand Up @@ -78,6 +79,7 @@ struct _GumQuickScript
GumQuickInstruction instruction;
GumQuickCodeWriter code_writer;
GumQuickCodeRelocator code_relocator;
GumQuickSampler sampler;
GumQuickStalker stalker;
GumQuickCloak cloak;

Expand Down Expand Up @@ -495,6 +497,7 @@ gum_quick_script_create_context (GumQuickScript * self,
_gum_quick_code_writer_init (&self->code_writer, global_obj, core);
_gum_quick_code_relocator_init (&self->code_relocator, global_obj,
&self->code_writer, &self->instruction, core);
_gum_quick_sampler_init (&self->sampler, global_obj, core);
_gum_quick_stalker_init (&self->stalker, global_obj, &self->code_writer,
&self->instruction, core);
_gum_quick_cloak_init (&self->cloak, global_obj, core);
Expand Down Expand Up @@ -533,6 +536,7 @@ gum_quick_script_destroy_context (GumQuickScript * self)
_gum_quick_scope_enter (&scope, core);

_gum_quick_cloak_dispose (&self->cloak);
_gum_quick_sampler_dispose (&self->sampler);
_gum_quick_stalker_dispose (&self->stalker);
_gum_quick_code_relocator_dispose (&self->code_relocator);
_gum_quick_code_writer_dispose (&self->code_writer);
Expand Down Expand Up @@ -576,6 +580,7 @@ gum_quick_script_destroy_context (GumQuickScript * self)
}

_gum_quick_cloak_finalize (&self->cloak);
_gum_quick_sampler_finalize (&self->sampler);
_gum_quick_stalker_finalize (&self->stalker);
_gum_quick_code_relocator_finalize (&self->code_relocator);
_gum_quick_code_writer_finalize (&self->code_writer);
Expand Down Expand Up @@ -919,6 +924,7 @@ gum_quick_script_try_unload (GumQuickScript * self)

_gum_quick_scope_enter (&scope, &self->core);

_gum_quick_sampler_flush (&self->sampler);
_gum_quick_stalker_flush (&self->stalker);
_gum_quick_interceptor_flush (&self->interceptor);
_gum_quick_socket_flush (&self->socket);
Expand Down
1 change: 1 addition & 0 deletions bindings/gumjs/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ if quickjs_dep.found()
'gumquickmodule.c',
'gumquickfile.c',
'gumquickchecksum.c',
'gumquicksampler.c',
'gumquickstream.c',
'gumquicksocket.c',
'gumquickinterceptor.c',
Expand Down
13 changes: 13 additions & 0 deletions tests/gumjs/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ TESTLIST_BEGIN (script)
TESTENTRY (module_dependencies_can_be_enumerated)
TESTENTRY (module_base_address_can_be_found)
TESTENTRY (module_export_can_be_found_by_name)
TESTENTRY (wallclock_can_be_sampled)
TESTENTRY (module_can_be_loaded)
TESTENTRY (module_can_be_forcibly_initialized)
TESTGROUP_END ()
Expand Down Expand Up @@ -5957,6 +5958,18 @@ TESTCASE (api_resolver_can_be_used_to_find_sections)
#endif
}

TESTCASE (wallclock_can_be_sampled)
{
COMPILE_AND_LOAD_SCRIPT (
"var sampler = new WallClockSampler();"
"var a = sampler.sample();"
"Thread.sleep(0.05);"
"var b = sampler.sample();"
"send(b.compare(a) === 1);");
EXPECT_SEND_MESSAGE_WITH ("true");
EXPECT_NO_MESSAGES ();
}

TESTCASE (invalid_script_should_return_null)
{
GError * err = NULL;
Expand Down

0 comments on commit 8b15ecc

Please sign in to comment.