Skip to content

Commit ea3a978

Browse files
committed
Wire up some more
1 parent f63e670 commit ea3a978

File tree

6 files changed

+122
-95
lines changed

6 files changed

+122
-95
lines changed

frida/extension.version

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
global:
3+
PyInit__frida;
4+
5+
local:
6+
*;
7+
};

frida/frida_bindgen/assets/codegen_gobject_methods.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,74 @@ PyGObject_class_init (void)
44
pygobject_type_spec_by_type = g_hash_table_new_full (NULL, NULL, NULL, NULL);
55
}
66

7+
static int
8+
PyGObject_init (PyGObject * self)
9+
{
10+
self->handle = NULL;
11+
self->type = PYFRIDA_TYPE (GObject);
12+
13+
self->signal_closures = NULL;
14+
15+
return 0;
16+
}
17+
18+
static void
19+
PyGObject_dealloc (PyGObject * self)
20+
{
21+
gpointer handle;
22+
23+
handle = PyGObject_steal_handle (self);
24+
if (handle != NULL)
25+
{
26+
Py_BEGIN_ALLOW_THREADS
27+
self->type->destroy (handle);
28+
Py_END_ALLOW_THREADS
29+
}
30+
31+
((freefunc) PyType_GetSlot (Py_TYPE (self), Py_tp_free)) (self);
32+
}
33+
34+
static void
35+
PyGObject_take_handle (PyGObject * self,
36+
gpointer handle,
37+
const PyGObjectType * type)
38+
{
39+
self->handle = handle;
40+
self->type = type;
41+
42+
if (handle != NULL)
43+
g_object_set_data (G_OBJECT (handle), "pyobject", self);
44+
}
45+
46+
static gpointer
47+
PyGObject_steal_handle (PyGObject * self)
48+
{
49+
gpointer handle = self->handle;
50+
GSList * entry;
51+
52+
if (handle == NULL)
53+
return NULL;
54+
55+
for (entry = self->signal_closures; entry != NULL; entry = entry->next)
56+
{
57+
PyGObjectSignalClosure * closure = entry->data;
58+
G_GNUC_UNUSED guint num_matches;
59+
60+
num_matches = g_signal_handlers_disconnect_matched (handle, G_SIGNAL_MATCH_CLOSURE, closure->signal_id, 0, &closure->parent, NULL, NULL);
61+
g_assert (num_matches == 1);
62+
}
63+
g_clear_pointer (&self->signal_closures, g_slist_free);
64+
65+
g_object_set_data (G_OBJECT (handle), "pyobject", NULL);
66+
67+
self->handle = NULL;
68+
69+
return handle;
70+
}
71+
772
static void
8-
PyGObject_register_type (GType instance_type, PyGObjectType * python_type)
73+
PyGObject_register_type (GType instance_type,
74+
PyGObjectType * python_type)
975
{
1076
g_hash_table_insert (pygobject_type_spec_by_type, GSIZE_TO_POINTER (instance_type), python_type);
1177
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
static void PyGObject_class_init (void);
2+
static int PyGObject_init (PyGObject * self);
3+
static void PyGObject_dealloc (PyGObject * self);
4+
static gpointer PyGObject_steal_handle (PyGObject * self);
25
static void PyGObject_register_type (GType instance_type, PyGObjectType * python_type);
Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +0,0 @@
1-
static void
2-
PyGObject_register_type (GType instance_type, PyGObjectType * python_type)
3-
{
4-
g_hash_table_insert (pygobject_type_spec_by_type, GSIZE_TO_POINTER (instance_type), python_type);
5-
}

frida/frida_bindgen/codegen.py

Lines changed: 40 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -532,17 +532,19 @@ def generate_extension_c(model: Model) -> str:
532532
#code += generate_commit_constructors_function(object_types)
533533

534534
for otype in object_types:
535-
pass
536-
#if otype.is_frida_options:
537-
# code += generate_options_conversion_functions(otype)
538-
# continue
539-
#if otype.is_frida_list:
540-
# code += generate_list_conversion_functions(otype)
541-
# continue
535+
if otype.name == "Object":
536+
code += "\n" + CODEGEN_GOBJECT_METHODS
537+
continue
538+
if otype.is_frida_options:
539+
#code += generate_options_conversion_functions(otype)
540+
continue
541+
if otype.is_frida_list:
542+
#code += generate_list_conversion_functions(otype)
543+
continue
542544

543545
#code += generate_object_type_registration_code(otype, model)
544546
#code += generate_object_type_conversion_functions(otype)
545-
#code += generate_object_type_constructor(otype)
547+
code += generate_object_type_constructor(otype)
546548
#code += generate_object_type_finalizer(otype)
547549
#code += generate_object_type_cleanup_code(otype)
548550

@@ -559,8 +561,6 @@ def generate_extension_c(model: Model) -> str:
559561
# for method in otype.methods:
560562
# code += generate_abstract_base_method_code(method)
561563

562-
if otype.name == "Object":
563-
code += CODEGEN_GOBJECT_METHODS
564564

565565
#for enum in enumerations:
566566
# code += generate_enum_registration_code(enum)
@@ -649,17 +649,17 @@ def generate_prototypes(model: Model) -> str:
649649
for otype in model.regular_object_types:
650650
otype_cprefix = otype.c_symbol_prefix
651651

652-
prototypes += [
653-
"",
654-
f"static int {otype_cprefix}_init ({otype_cprefix} * self, PyObject * args, PyObject * kw);",
655-
f"static void {otype_cprefix}_dealloc ({otype_cprefix} * self);",
656-
]
657-
658652
if otype.name == "Object":
659653
prototypes += [
660654
"",
661655
CODEGEN_GOBJECT_PROTOTYPES.rstrip(),
662656
]
657+
else:
658+
prototypes += [
659+
"",
660+
f"static int {otype_cprefix}_init ({otype_cprefix} * self, PyObject * args, PyObject * kw);",
661+
f"static void {otype_cprefix}_dealloc ({otype_cprefix} * self);",
662+
]
663663

664664
return "\n".join(prototypes)
665665

@@ -669,6 +669,9 @@ def generate_shared_globals() -> str:
669669
[
670670
"",
671671
'static struct PyModuleDef PyFrida_moduledef = { PyModuleDef_HEAD_INIT, "_frida", "Frida", -1, NULL, };',
672+
"",
673+
"static initproc PyGObject_tp_init;",
674+
"static destructor PyGObject_tp_dealloc;",
672675
]
673676
)
674677

@@ -790,6 +793,11 @@ def generate_init_function(
790793
791794
module = PyModule_Create (&PyFrida_moduledef);
792795
796+
PyModule_AddStringConstant (module, "__version__", frida_version_string ());
797+
798+
PyGObject_tp_init = PyType_GetSlot ((PyTypeObject *) PYFRIDA_TYPE_OBJECT (GObject), Py_tp_init);
799+
PyGObject_tp_dealloc = PyType_GetSlot ((PyTypeObject *) PYFRIDA_TYPE_OBJECT (GObject), Py_tp_dealloc);
800+
793801
{object_type_registration_calls}
794802
795803
return module;
@@ -982,13 +990,8 @@ def calculate_indent(suffix: str) -> str:
982990
def generate_object_type_constructor(otype: ObjectType) -> str:
983991
otype_cprefix = otype.c_symbol_prefix
984992

985-
def calculate_indent(suffix: str) -> str:
986-
return " " * (len(otype_cprefix) + len(suffix) + 2)
987-
988993
ctor = next(iter(otype.constructors), None)
989994

990-
n_parameters = max(len(ctor.parameters) if ctor is not None else 0, 1)
991-
992995
storage_prefix = ""
993996
invalid_arg_label = "propagate_error"
994997
error_check = ""
@@ -998,13 +1001,9 @@ def calculate_indent(suffix: str) -> str:
9981001
param_declarations = generate_parameter_variable_declarations(
9991002
ctor, initialize=True
10001003
)
1001-
if ctor.parameters:
1002-
param_conversions = generate_input_parameter_conversions_code(
1003-
ctor, storage_prefix, invalid_arg_label
1004-
)
1005-
else:
1006-
param_conversions = """if (argc != 0)
1007-
goto invalid_handle;"""
1004+
param_conversions = generate_input_parameter_conversions_code(
1005+
ctor, storage_prefix, invalid_arg_label
1006+
)
10081007
param_destructions = generate_parameter_destructions_code(ctor, storage_prefix)
10091008

10101009
call_args = generate_call_arguments_code(ctor, storage_prefix)
@@ -1038,78 +1037,32 @@ def calculate_indent(suffix: str) -> str:
10381037
}}
10391038
"""
10401039

1041-
if ctor is not None and ctor.parameters:
1042-
invalid_handle_logic = ""
1043-
else:
1044-
invalid_handle_logic = f"""invalid_handle:
1045-
{{
1046-
napi_throw_type_error (env, NULL, "expected a {otype.js_name} handle");
1047-
goto propagate_error;
1048-
}}
1049-
"""
1050-
1051-
custom = otype.customizations
1052-
1053-
finalizer = "fdn_object_finalize"
1054-
1055-
cleanup_code = ""
1056-
if custom is not None and custom.cleanup is not None:
1057-
cleanup_code = f"""
1058-
1059-
napi_add_env_cleanup_hook (env, {otype_cprefix}_handle_cleanup, handle);
1060-
g_object_set_data (G_OBJECT (handle), "fdn-cleanup-hook", {otype_cprefix}_handle_cleanup);"""
1061-
finalizer = f"{otype_cprefix}_finalize"
1062-
1063-
keep_alive_code = ""
1064-
if custom is not None and custom.keep_alive is not None:
1065-
keep_alive = custom.keep_alive
1066-
method = next(
1067-
(
1068-
method
1069-
for method in otype.methods
1070-
if method.name == keep_alive.is_destroyed_function
1071-
)
1072-
)
1073-
keep_alive_code = f"""
1074-
1075-
fdn_keep_alive_until (env, jsthis, G_OBJECT (handle), (FdnIsDestroyedFunc) {method.c_identifier}, "{keep_alive.destroy_signal_name}");"""
1040+
def calculate_indent(suffix: str) -> str:
1041+
return " " * (len(otype_cprefix) + len(suffix) + 2)
10761042

10771043
one_newline = "\n"
10781044
two_newlines = "\n\n"
10791045

10801046
return f"""
1081-
static napi_value
1082-
{otype_cprefix}_construct (napi_env env,
1083-
{calculate_indent("_construct")}napi_callback_info info)
1047+
static int
1048+
{otype_cprefix}_init ({otype_cprefix} * self,
1049+
{calculate_indent("_init")}PyObject * args,
1050+
{calculate_indent("_init")}PyObject * kw)
10841051
{{
1085-
napi_value result = NULL;
1086-
size_t argc = {n_parameters};
1087-
napi_value args[{n_parameters}], jsthis;
1088-
bool is_instance;{indent_c_code(param_declarations, 1, prologue=one_newline)}
1052+
int result = -1;{indent_c_code(param_declarations, 1, prologue=one_newline)}
10891053
{otype.c_type} * handle = NULL;
10901054
1091-
if (napi_get_cb_info (env, info, &argc, args, &jsthis, NULL) != napi_ok)
1055+
if ({otype.parent_c_symbol_prefix}_tp_init ((PyObject *) self, args, kw) < 0)
10921056
goto propagate_error;
10931057
1094-
if (argc != 0 && napi_check_object_type_tag (env, args[0], &fdn_handle_wrapper_type_tag, &is_instance) == napi_ok && is_instance)
1095-
{{
1096-
if (napi_get_value_external (env, args[0], (void **) &handle) != napi_ok)
1097-
goto propagate_error;
1058+
{indent_c_code(param_conversions, 1)}{indent_c_code(constructor_call, 1, prologue=two_newlines)}{indent_c_code(error_check, 1, prologue=one_newline)}
10981059
1099-
g_object_ref (handle);
1100-
}}
1101-
else
1102-
{{
1103-
{indent_c_code(param_conversions, 2)}{indent_c_code(constructor_call, 2, prologue=two_newlines)}{indent_c_code(error_check, 2, prologue=one_newline)}
1104-
}}
1105-
1106-
if (!fdn_object_wrap (env, jsthis, G_OBJECT (handle), {finalizer}))
1107-
goto propagate_error;{cleanup_code}{keep_alive_code}
1060+
PyGObject_take_handle ((PyGObject *) self, g_steal_pointer (&handle), PYFRIDA_TYPE ({otype.py_name}));
11081061
1109-
result = jsthis;
1062+
result = 0;
11101063
goto beach;
11111064
1112-
{unconstructable_logic}{invalid_handle_logic}{construction_failed_logic}propagate_error:
1065+
{unconstructable_logic}{construction_failed_logic}propagate_error:
11131066
{{
11141067
g_clear_object (&handle);
11151068
goto beach;
@@ -1532,11 +1485,9 @@ def generate_object_type_structs(model: Model) -> str:
15321485
for otype in model.regular_object_types:
15331486
if otype.name == "Object":
15341487
continue
1535-
parent = otype.parent
1536-
parent_type = parent.c_symbol_prefix if parent is not None else "PyGObject"
15371488
structs.append(f"""struct _{otype.c_symbol_prefix}
15381489
{{
1539-
{parent_type} parent;
1490+
{otype.parent_c_symbol_prefix} parent;
15401491
}};""")
15411492

15421493
return "\n\n".join(structs)

frida/frida_bindgen/model.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ def customizations(self) -> Optional[ObjectTypeCustomizations]:
197197
def c_symbol_prefix(self) -> str:
198198
return f"Py{self.py_name}"
199199

200+
@cached_property
201+
def parent_c_symbol_prefix(self) -> str:
202+
parent = self.parent
203+
return parent.c_symbol_prefix if parent is not None else "PyGObject"
204+
200205
@cached_property
201206
def abstract_base_c_symbol_prefix(self) -> str:
202207
return f"PyAbstract{self.name}"

0 commit comments

Comments
 (0)