mirror of
https://github.com/radareorg/r2unity.git
synced 2026-11-07 06:36:00 -10:00
Register class inheritance and fields using r2 6.1.6 commands
This commit is contained in:
1 parent
d9fae9a6f0
commit
ca5867eb5c
2 files changed
+415
-18
No files matched your search
+3
-18
@@ -231,9 +231,6 @@ static void section_free(void *p) {
|
||||
|
||||
static RBinSection *new_section(const char *name, ut64 off, ut64 size, bool has_strings) {
|
||||
RBinSection *sec = R_NEW0 (RBinSection);
|
||||
if (!sec) {
|
||||
return NULL;
|
||||
}
|
||||
init_section (sec, name, off, size, has_strings);
|
||||
return sec;
|
||||
}
|
||||
@@ -511,7 +508,7 @@ static bool symbols_vec(RBinFile *bf) {
|
||||
#else
|
||||
static RList *symbols(RBinFile *bf) {
|
||||
RList *ret = r_list_newf ((RListFree)r_bin_symbol_free);
|
||||
if (!ret || !symbols_fill (bf, ret)) {
|
||||
if (!symbols_fill (bf, ret)) {
|
||||
r_list_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
@@ -606,10 +603,6 @@ static void append_bin_string(R2UnityStringSink *ret, char *text, ut64 paddr, ut
|
||||
return;
|
||||
}
|
||||
RBinString *str = R_NEW0 (RBinString);
|
||||
if (!str) {
|
||||
free (text);
|
||||
return;
|
||||
}
|
||||
str->string = text;
|
||||
str->paddr = paddr;
|
||||
str->vaddr = paddr;
|
||||
@@ -681,9 +674,6 @@ static RList *strings(RBinFile *bf) {
|
||||
R2UnityBinObj *obj = get_obj (bf);
|
||||
R_RETURN_VAL_IF_FAIL (obj, NULL);
|
||||
RList *ret = r_list_newf ((RListFree)r_bin_string_free);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ut32 ordinal = 0;
|
||||
add_metadata_strings (obj, ret, &ordinal);
|
||||
add_literal_strings (obj, ret, &ordinal);
|
||||
@@ -695,9 +685,6 @@ static RList *strings(RBinFile *bf) {
|
||||
typedef RVecRBinImport R2UnityImportSink;
|
||||
|
||||
static void append_import(R2UnityImportSink *ret, RBinImport *imp) {
|
||||
if (!imp) {
|
||||
return;
|
||||
}
|
||||
RBinImport *dst = RVecRBinImport_emplace_back (ret);
|
||||
if (!dst) {
|
||||
r_bin_import_free (imp);
|
||||
@@ -710,9 +697,7 @@ static void append_import(R2UnityImportSink *ret, RBinImport *imp) {
|
||||
typedef RList R2UnityImportSink;
|
||||
|
||||
static void append_import(R2UnityImportSink *ret, RBinImport *imp) {
|
||||
if (imp) {
|
||||
r_list_append (ret, imp);
|
||||
}
|
||||
r_list_append (ret, imp);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -745,7 +730,7 @@ static bool imports_vec(RBinFile *bf) {
|
||||
#else
|
||||
static RList *imports(RBinFile *bf) {
|
||||
RList *ret = r_list_newf ((RListFree)r_bin_import_free);
|
||||
if (!ret || !imports_fill (bf, ret)) {
|
||||
if (!imports_fill (bf, ret)) {
|
||||
r_list_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ static const char *g_help_msg[] = {
|
||||
"Usage:", "r2unity[-subcmd]", " Unity IL2CPP analyzer",
|
||||
"r2unity", "", "show this help",
|
||||
"r2unity?", "", "show this help",
|
||||
"r2unity-c", "[*j]", "enumerate classes, inheritance, methods, and fields",
|
||||
"r2unity-D", "", "auto-detect companion files from current binary path",
|
||||
"r2unity-i", "[j]", "summary (metadata version, type/method counts)",
|
||||
"r2unity-s", "[*j]", "apply/list managed method symbols as flags + comments",
|
||||
@@ -284,6 +285,415 @@ static bool find_method_pointers(R2UnityMetadata *meta, const char *path, ut64 *
|
||||
return false;
|
||||
}
|
||||
|
||||
static int type_definition_for_type_index(const Il2CppTypeDefinition *types, size_t type_count, int32_t type_index) {
|
||||
if (type_index >= 0) {
|
||||
for (size_t i = 0; i < type_count; i++) {
|
||||
if (types[i].byvalTypeIndex == type_index) {
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *type_name_from_index(R2UnityMetadata *meta, const Il2CppTypeDefinition *types, size_t type_count, int32_t type_index, bool fallback) {
|
||||
int idx = type_definition_for_type_index (types, type_count, type_index);
|
||||
if (idx >= 0) {
|
||||
return r2unity_type_fullname (meta, &types[idx], (size_t)idx, R2U_NAME_FALLBACK_TYPE);
|
||||
}
|
||||
if (fallback && type_index >= 0) {
|
||||
return r_str_newf ("type_index.%d", type_index);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *field_name_or_fallback(R2UnityMetadata *meta, const Il2CppFieldDefinition *field, size_t index) {
|
||||
char *name = r2unity_get_string (meta, field->nameIndex);
|
||||
if (R_STR_ISNOTEMPTY (name)) {
|
||||
return name;
|
||||
}
|
||||
free (name);
|
||||
return r_str_newf ("field.%zu", index);
|
||||
}
|
||||
|
||||
static char *method_name_or_fallback(R2UnityMetadata *meta, const Il2CppMethodDefinition *method, size_t index) {
|
||||
char *name = r2unity_get_string (meta, method->nameIndex);
|
||||
if (R_STR_ISNOTEMPTY (name)) {
|
||||
return name;
|
||||
}
|
||||
free (name);
|
||||
return r_str_newf ("method.%zu", index);
|
||||
}
|
||||
|
||||
static void sanitize_ic_name(char *s) {
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
r_name_filter (s, -1);
|
||||
for (char *p = s; *p; p++) {
|
||||
if (*p == '.' || *p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
|
||||
*p = '_';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *r2_class_name(const char *name, size_t index) {
|
||||
char *out = (name && *name)? strdup (name): r_str_newf ("type_%zu", index);
|
||||
sanitize_ic_name (out);
|
||||
if (!out || !*out) {
|
||||
free (out);
|
||||
out = r_str_newf ("type_%zu", index);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static char *r2_method_name(const char *name, size_t index) {
|
||||
char *out = (name && *name)? r_str_newf ("%s_%zu", name, index): r_str_newf ("method_%zu", index);
|
||||
sanitize_ic_name (out);
|
||||
if (!out || !*out) {
|
||||
free (out);
|
||||
out = r_str_newf ("method_%zu", index);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static char *r2_field_name(const char *name, size_t index) {
|
||||
char *out = (name && *name)? strdup (name): r_str_newf ("field_%zu", index);
|
||||
sanitize_ic_name (out);
|
||||
if (!out || !*out) {
|
||||
free (out);
|
||||
out = r_str_newf ("field_%zu", index);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static void pj_hex(PJ *pj, const char *key, ut64 value, int width) {
|
||||
char hex[64];
|
||||
snprintf (hex, sizeof (hex), "0x%0*" PFMT64x, width, value);
|
||||
pj_ks (pj, key, hex);
|
||||
}
|
||||
|
||||
static void pj_string_or_null(PJ *pj, const char *key, const char *value) {
|
||||
if (value) {
|
||||
pj_ks (pj, key, value);
|
||||
} else {
|
||||
pj_knull (pj, key);
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_class_text(RCore *core,
|
||||
R2UnityMetadata *meta,
|
||||
const Il2CppTypeDefinition *types,
|
||||
size_t type_count,
|
||||
const Il2CppMethodDefinition *methods,
|
||||
size_t method_count,
|
||||
const Il2CppFieldDefinition *fields,
|
||||
size_t field_count,
|
||||
const int32_t *interfaces,
|
||||
size_t interface_count,
|
||||
size_t type_index) {
|
||||
const Il2CppTypeDefinition *td = &types[type_index];
|
||||
char *name = r2unity_type_fullname (meta, td, type_index, R2U_NAME_FALLBACK_TYPE);
|
||||
char *base = type_name_from_index (meta, types, type_count, td->parentIndex, true);
|
||||
r_cons_printf (core->cons, "class %zu %s", type_index, name? name: "-");
|
||||
if (base) {
|
||||
r_cons_printf (core->cons, " : %s", base);
|
||||
}
|
||||
if (interfaces && td->interfaces_count > 0 && td->interfacesStart >= 0) {
|
||||
bool first = true;
|
||||
for (size_t k = 0; k < td->interfaces_count && (size_t)(td->interfacesStart + k) < interface_count; k++) {
|
||||
char *iname = type_name_from_index (meta, types, type_count, interfaces[td->interfacesStart + k], true);
|
||||
if (iname) {
|
||||
r_cons_printf (core->cons, "%s%s", first? " implements ": ", ", iname);
|
||||
first = false;
|
||||
}
|
||||
free (iname);
|
||||
}
|
||||
}
|
||||
r_cons_printf (core->cons, " token=0x%08x fields=%u methods=%u\n", td->token, (unsigned)td->field_count, (unsigned)td->method_count);
|
||||
|
||||
int fstart = td->fieldStart;
|
||||
for (int k = 0; fields && k < td->field_count && fstart >= 0 && (size_t)(fstart + k) < field_count; k++) {
|
||||
size_t fi = (size_t)(fstart + k);
|
||||
char *fname = field_name_or_fallback (meta, &fields[fi], fi);
|
||||
char *ftype = type_name_from_index (meta, types, type_count, fields[fi].typeIndex, true);
|
||||
r_cons_printf (core->cons, " field %zu %s %s token=0x%08x type_index=%d\n",
|
||||
fi,
|
||||
ftype? ftype: "-",
|
||||
fname? fname: "-",
|
||||
fields[fi].token,
|
||||
fields[fi].typeIndex);
|
||||
free (ftype);
|
||||
free (fname);
|
||||
}
|
||||
|
||||
int mstart = td->methodStart;
|
||||
for (int k = 0; methods && k < td->method_count && mstart >= 0 && (size_t)(mstart + k) < method_count; k++) {
|
||||
size_t mi = (size_t)(mstart + k);
|
||||
char *mname = method_name_or_fallback (meta, &methods[mi], mi);
|
||||
char *attrs = method_attrs_str (methods[mi].flags);
|
||||
r_cons_printf (core->cons, " method %zu %s%s%s(%u) token=0x%08x flags=0x%04x\n",
|
||||
mi,
|
||||
attrs && *attrs? attrs: "",
|
||||
attrs && *attrs? " ": "",
|
||||
mname? mname: "-",
|
||||
(unsigned)methods[mi].parameterCount,
|
||||
methods[mi].token,
|
||||
methods[mi].flags);
|
||||
free (attrs);
|
||||
free (mname);
|
||||
}
|
||||
free (base);
|
||||
free (name);
|
||||
}
|
||||
|
||||
static void emit_class_json(PJ *pj,
|
||||
R2UnityMetadata *meta,
|
||||
const Il2CppTypeDefinition *types,
|
||||
size_t type_count,
|
||||
const Il2CppMethodDefinition *methods,
|
||||
size_t method_count,
|
||||
const Il2CppFieldDefinition *fields,
|
||||
size_t field_count,
|
||||
const int32_t *interfaces,
|
||||
size_t interface_count,
|
||||
const ut64 *method_ptrs,
|
||||
bool has_ptrs,
|
||||
size_t type_index) {
|
||||
const Il2CppTypeDefinition *td = &types[type_index];
|
||||
char *name = r2unity_type_fullname (meta, td, type_index, R2U_NAME_FALLBACK_TYPE);
|
||||
char *ns = r2unity_get_string (meta, td->namespaceIndex);
|
||||
char *short_name = r2unity_get_string (meta, td->nameIndex);
|
||||
char *base = type_name_from_index (meta, types, type_count, td->parentIndex, true);
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "index", (ut64)type_index);
|
||||
pj_string_or_null (pj, "name", name);
|
||||
pj_string_or_null (pj, "namespace", ns);
|
||||
pj_string_or_null (pj, "short_name", short_name);
|
||||
pj_string_or_null (pj, "base", base);
|
||||
pj_ki (pj, "base_type_index", td->parentIndex);
|
||||
pj_hex (pj, "flags", td->flags, 8);
|
||||
pj_hex (pj, "token", td->token, 8);
|
||||
|
||||
pj_ka (pj, "interfaces");
|
||||
if (interfaces && td->interfaces_count > 0 && td->interfacesStart >= 0) {
|
||||
for (size_t k = 0; k < td->interfaces_count && (size_t)(td->interfacesStart + k) < interface_count; k++) {
|
||||
int32_t idx = interfaces[td->interfacesStart + k];
|
||||
char *iname = type_name_from_index (meta, types, type_count, idx, true);
|
||||
pj_o (pj);
|
||||
pj_ki (pj, "type_index", idx);
|
||||
pj_string_or_null (pj, "name", iname);
|
||||
pj_end (pj);
|
||||
free (iname);
|
||||
}
|
||||
}
|
||||
pj_end (pj);
|
||||
|
||||
pj_ka (pj, "fields");
|
||||
int fstart = td->fieldStart;
|
||||
for (int k = 0; fields && k < td->field_count && fstart >= 0 && (size_t)(fstart + k) < field_count; k++) {
|
||||
size_t fi = (size_t)(fstart + k);
|
||||
char *fname = field_name_or_fallback (meta, &fields[fi], fi);
|
||||
char *ftype = type_name_from_index (meta, types, type_count, fields[fi].typeIndex, true);
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "index", (ut64)fi);
|
||||
pj_string_or_null (pj, "name", fname);
|
||||
pj_ki (pj, "type_index", fields[fi].typeIndex);
|
||||
pj_string_or_null (pj, "type", ftype);
|
||||
pj_hex (pj, "token", fields[fi].token, 8);
|
||||
pj_end (pj);
|
||||
free (ftype);
|
||||
free (fname);
|
||||
}
|
||||
pj_end (pj);
|
||||
|
||||
pj_ka (pj, "methods");
|
||||
int mstart = td->methodStart;
|
||||
for (int k = 0; methods && k < td->method_count && mstart >= 0 && (size_t)(mstart + k) < method_count; k++) {
|
||||
size_t mi = (size_t)(mstart + k);
|
||||
char *mname = method_name_or_fallback (meta, &methods[mi], mi);
|
||||
char *fullname = r2unity_method_fullname (meta, &methods[mi], td, type_index, R2U_NAME_WITH_PARAMS | R2U_NAME_FALLBACK_TYPE);
|
||||
char *attrs = method_attrs_str (methods[mi].flags);
|
||||
ut64 addr = (has_ptrs && method_ptrs)? method_ptrs[mi]: 0;
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "index", (ut64)mi);
|
||||
pj_string_or_null (pj, "name", mname);
|
||||
pj_string_or_null (pj, "full_name", fullname);
|
||||
pj_kn (pj, "parameter_count", (ut64)methods[mi].parameterCount);
|
||||
pj_kn (pj, "addr", addr);
|
||||
pj_hex (pj, "token", methods[mi].token, 8);
|
||||
pj_hex (pj, "flags", methods[mi].flags, 4);
|
||||
pj_hex (pj, "iflags", methods[mi].iflags, 4);
|
||||
pj_string_or_null (pj, "attrs", (attrs && *attrs)? attrs: NULL);
|
||||
pj_end (pj);
|
||||
free (attrs);
|
||||
free (fullname);
|
||||
free (mname);
|
||||
}
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
free (base);
|
||||
free (short_name);
|
||||
free (ns);
|
||||
free (name);
|
||||
}
|
||||
|
||||
static void emit_class_r2(RCore *core,
|
||||
R2UnityMetadata *meta,
|
||||
const Il2CppTypeDefinition *types,
|
||||
size_t type_count,
|
||||
const Il2CppMethodDefinition *methods,
|
||||
size_t method_count,
|
||||
const Il2CppFieldDefinition *fields,
|
||||
size_t field_count,
|
||||
const int32_t *interfaces,
|
||||
size_t interface_count,
|
||||
const ut64 *method_ptrs,
|
||||
bool has_ptrs,
|
||||
size_t type_index) {
|
||||
const Il2CppTypeDefinition *td = &types[type_index];
|
||||
char *name = r2unity_type_fullname (meta, td, type_index, R2U_NAME_FALLBACK_TYPE);
|
||||
char *r2klass = r2_class_name (name, type_index);
|
||||
char *base = type_name_from_index (meta, types, type_count, td->parentIndex, false);
|
||||
if (base) {
|
||||
r_cons_printf (core->cons, "# class %s : %s\n", name? name: r2klass, base);
|
||||
} else {
|
||||
r_cons_printf (core->cons, "# class %s\n", name? name: r2klass);
|
||||
}
|
||||
r_cons_printf (core->cons, "ic+%s @ 0\n", r2klass);
|
||||
if (base) {
|
||||
char *r2base = r2_class_name (base, 0);
|
||||
r_cons_printf (core->cons, "ic+%s:%s @ 0\n", r2klass, r2base);
|
||||
free (r2base);
|
||||
}
|
||||
free (base);
|
||||
if (interfaces && td->interfaces_count > 0 && td->interfacesStart >= 0) {
|
||||
for (size_t k = 0; k < td->interfaces_count && (size_t)(td->interfacesStart + k) < interface_count; k++) {
|
||||
char *iname = type_name_from_index (meta, types, type_count, interfaces[td->interfacesStart + k], false);
|
||||
if (iname) {
|
||||
char *r2iface = r2_class_name (iname, 0);
|
||||
r_cons_printf (core->cons, "ic+%s:%s @ 0\n", r2klass, r2iface);
|
||||
free (r2iface);
|
||||
}
|
||||
free (iname);
|
||||
}
|
||||
}
|
||||
|
||||
int mstart = td->methodStart;
|
||||
for (int k = 0; methods && k < td->method_count && mstart >= 0 && (size_t)(mstart + k) < method_count; k++) {
|
||||
size_t mi = (size_t)(mstart + k);
|
||||
ut64 addr = (has_ptrs && method_ptrs)? method_ptrs[mi]: 0;
|
||||
addr = addr > 0x1000? addr: 0;
|
||||
char *mname = method_name_or_fallback (meta, &methods[mi], mi);
|
||||
char *r2meth = r2_method_name (mname, mi);
|
||||
r_cons_printf (core->cons, "ic+%s.%s @ 0x%" PFMT64x "\n", r2klass, r2meth, addr);
|
||||
free (r2meth);
|
||||
free (mname);
|
||||
}
|
||||
|
||||
int fstart = td->fieldStart;
|
||||
for (int k = 0; fields && k < td->field_count && fstart >= 0 && (size_t)(fstart + k) < field_count; k++) {
|
||||
size_t fi = (size_t)(fstart + k);
|
||||
char *fname = field_name_or_fallback (meta, &fields[fi], fi);
|
||||
char *r2field = r2_field_name (fname, fi);
|
||||
char *ftype = type_name_from_index (meta, types, type_count, fields[fi].typeIndex, true);
|
||||
r_cons_printf (core->cons, "ic+%s..%s %s @ 0\n",
|
||||
r2klass,
|
||||
r2field,
|
||||
ftype? ftype: "unknown");
|
||||
free (ftype);
|
||||
free (r2field);
|
||||
free (fname);
|
||||
}
|
||||
free (r2klass);
|
||||
free (name);
|
||||
}
|
||||
|
||||
static int cmd_classes(RCore *core, char mode) {
|
||||
const char *metadata_path = resolve_metadata_path (core);
|
||||
RBuffer *buf = NULL;
|
||||
R2UnityMetadata *meta = open_metadata (core, &buf);
|
||||
if (!meta) {
|
||||
return 1;
|
||||
}
|
||||
size_t type_count = 0;
|
||||
Il2CppTypeDefinition *types = r2unity_get_type_definitions (meta, &type_count);
|
||||
if (!types) {
|
||||
R_LOG_ERROR ("unable to decode type definitions");
|
||||
close_metadata (meta, buf);
|
||||
return 1;
|
||||
}
|
||||
size_t method_count = 0;
|
||||
Il2CppMethodDefinition *methods = r2unity_get_method_definitions (meta, &method_count);
|
||||
size_t field_count = 0;
|
||||
Il2CppFieldDefinition *fields = r2unity_get_field_definitions (meta, &field_count);
|
||||
size_t interface_count = 0;
|
||||
int32_t *interfaces = r2unity_get_type_index_table (meta, R2U_SEC_INTERFACES, &interface_count);
|
||||
|
||||
ut64 *method_ptrs = NULL;
|
||||
bool has_ptrs = false;
|
||||
const char *lib = resolve_library_path (core);
|
||||
if (lib && *lib) {
|
||||
has_ptrs = find_method_pointers (meta, lib, &method_ptrs);
|
||||
}
|
||||
if (method_ptrs && !has_ptrs) {
|
||||
for (size_t k = 0; k < method_count; k++) {
|
||||
if (method_ptrs[k]) {
|
||||
has_ptrs = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == 'j') {
|
||||
PJ *pj = pj_new ();
|
||||
pj_o (pj);
|
||||
pj_kb (pj, "ok", true);
|
||||
pj_ki (pj, "version", meta->version);
|
||||
pj_ks (pj, "unity_range", r2unity_unity_range_from_wire (meta->version));
|
||||
pj_kb (pj, "has_ptrs", has_ptrs);
|
||||
pj_kn (pj, "types", (ut64)type_count);
|
||||
pj_kn (pj, "methods", (ut64)method_count);
|
||||
pj_kn (pj, "fields", (ut64)field_count);
|
||||
pj_ka (pj, "classes");
|
||||
for (size_t i = 0; i < type_count; i++) {
|
||||
emit_class_json (pj, meta, types, type_count, methods, method_count, fields, field_count, interfaces, interface_count, method_ptrs, has_ptrs, i);
|
||||
}
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
r_cons_println (core->cons, pj_string (pj));
|
||||
pj_free (pj);
|
||||
} else if (mode == '*') {
|
||||
r_cons_println (core->cons, "# r2 script generated by r2unity-c");
|
||||
r_cons_printf (core->cons, "# Input file: %s\n", metadata_path && *metadata_path? metadata_path: "-");
|
||||
if (!has_ptrs) {
|
||||
r_cons_println (core->cons, "# Method addresses default to 0; run r2unity-D or set r2unity.library to recover native addresses.");
|
||||
}
|
||||
for (size_t i = 0; i < type_count; i++) {
|
||||
emit_class_r2 (core, meta, types, type_count, methods, method_count, fields, field_count, interfaces, interface_count, method_ptrs, has_ptrs, i);
|
||||
}
|
||||
} else {
|
||||
r_cons_printf (core->cons, "# classes from %s\n", metadata_path && *metadata_path? metadata_path: "-");
|
||||
r_cons_printf (core->cons, "# wire_version=%d (%s) types=%zu methods=%zu fields=%zu\n",
|
||||
meta->version,
|
||||
r2unity_unity_range_from_wire (meta->version),
|
||||
type_count,
|
||||
method_count,
|
||||
field_count);
|
||||
for (size_t i = 0; i < type_count; i++) {
|
||||
emit_class_text (core, meta, types, type_count, methods, method_count, fields, field_count, interfaces, interface_count, i);
|
||||
}
|
||||
}
|
||||
|
||||
R_FREE (method_ptrs);
|
||||
R_FREE (interfaces);
|
||||
R_FREE (fields);
|
||||
R_FREE (methods);
|
||||
R_FREE (types);
|
||||
close_metadata (meta, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------- r2unity-s (methods) ---------- */
|
||||
static int cmd_symbols(RCore *core, char mode) {
|
||||
/* mode: 0 = apply to r2 session, '*' = print r2 commands, 'j' = JSON */
|
||||
@@ -678,6 +1088,8 @@ static bool r2unity_call(RCorePluginSession *cps, const char *input) {
|
||||
}
|
||||
|
||||
switch (sub) {
|
||||
case 'c':
|
||||
return cmd_classes (core, mode) == 0;
|
||||
case 'D':
|
||||
return cmd_detect (core, mode == 'j') == 0;
|
||||
case 'i':
|
||||
|
||||
Reference in new issue
Block a user