mirror of
https://github.com/radareorg/r2unity.git
synced 2026-11-07 06:36:00 -10:00
Cleanup public api and got -250LOC back
This commit is contained in:
1 parent
7c74897721
commit
bc49ade2ee
7 files changed
+401
-651
No files matched your search
+25
-47
@@ -1,7 +1,16 @@
|
||||
// Fast ELF parser for r2unity
|
||||
#define R_LOG_ORIGIN "r2unity.elf"
|
||||
#include "lib.h"
|
||||
#include <string.h>
|
||||
|
||||
static inline void elf_write_word(ut8 *loc, ut64 val, bool is64) {
|
||||
if (is64) {
|
||||
r_write_le64 (loc, val);
|
||||
} else {
|
||||
r_write_le32 (loc, (ut32)val);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ut64 vaddr;
|
||||
ut64 memsz;
|
||||
@@ -242,6 +251,8 @@ R_API bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *e
|
||||
}
|
||||
}
|
||||
}
|
||||
const ut64 base = (base_vaddr != UT64_MAX)? base_vaddr: 0;
|
||||
const ut64 type_mask = e.is64? 0xffffffffULL: 0xffULL;
|
||||
if (rela_off && rela_sz && rela_ent) {
|
||||
for (ut64 i = 0; i + rela_ent <= rela_sz; i += rela_ent) {
|
||||
const ut8 *rp = elf_vm_to_ptr (&e, rela_off + i);
|
||||
@@ -251,26 +262,14 @@ R_API bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *e
|
||||
ut64 r_offset = e.is64? r_read_le64 (rp + 0): (ut64)r_read_le32 (rp + 0);
|
||||
ut64 r_info = e.is64? r_read_le64 (rp + 8): (ut64)r_read_le32 (rp + 4);
|
||||
ut64 r_addend = e.is64? r_read_le64 (rp + 16): (ut64)r_read_le32 (rp + 8);
|
||||
ut64 type = e.is64? (r_info & 0xffffffffULL): (r_info & 0xffULL);
|
||||
ut64 type = r_info & type_mask;
|
||||
bool is_relative = (type == 8) || (type == 23) || (type == 1027);
|
||||
if (!is_relative) {
|
||||
continue;
|
||||
}
|
||||
ut8 *loc = (ut8 *)elf_vm_to_ptr (&e, r_offset);
|
||||
if (!loc) {
|
||||
continue;
|
||||
}
|
||||
// For RELATIVE, new value should be base + addend
|
||||
ut64 newv = base_vaddr != UT64_MAX? (base_vaddr + r_addend): r_addend;
|
||||
if (e.is64) {
|
||||
for (int b = 0; b < 8; b++) {
|
||||
loc[b] = (ut8) ((newv >> (8 * b)) & 0xff);
|
||||
}
|
||||
} else {
|
||||
ut32 v32 = (ut32)newv;
|
||||
for (int b = 0; b < 4; b++) {
|
||||
loc[b] = (ut8) ((v32 >> (8 * b)) & 0xff);
|
||||
}
|
||||
if (loc) {
|
||||
elf_write_word (loc, base + r_addend, e.is64);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +281,7 @@ R_API bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *e
|
||||
}
|
||||
ut64 r_offset = e.is64? r_read_le64 (rp + 0): (ut64)r_read_le32 (rp + 0);
|
||||
ut64 r_info = e.is64? r_read_le64 (rp + 8): (ut64)r_read_le32 (rp + 4);
|
||||
ut64 type = e.is64? (r_info & 0xffffffffULL): (r_info & 0xffULL);
|
||||
ut64 type = r_info & type_mask;
|
||||
bool is_relative = (type == 8) || (type == 23) || (type == 1027);
|
||||
if (!is_relative) {
|
||||
continue;
|
||||
@@ -292,18 +291,7 @@ R_API bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *e
|
||||
continue;
|
||||
}
|
||||
ut64 add = e.is64? r_read_le64 (loc): (ut64)r_read_le32 (loc);
|
||||
// REL: add base to current value
|
||||
ut64 newv = base_vaddr != UT64_MAX? (base_vaddr + add): add;
|
||||
if (e.is64) {
|
||||
for (int b = 0; b < 8; b++) {
|
||||
loc[b] = (ut8) ((newv >> (8 * b)) & 0xff);
|
||||
}
|
||||
} else {
|
||||
ut32 v32 = (ut32)newv;
|
||||
for (int b = 0; b < 4; b++) {
|
||||
loc[b] = (ut8) ((v32 >> (8 * b)) & 0xff);
|
||||
}
|
||||
}
|
||||
elf_write_word (loc, base + add, e.is64);
|
||||
}
|
||||
}
|
||||
if (e.is64 && relr_off && relr_sz && relr_ent) {
|
||||
@@ -318,27 +306,19 @@ R_API bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *e
|
||||
ut64 addr = R;
|
||||
ut8 *loc = (ut8 *)elf_vm_to_ptr (&e, addr);
|
||||
if (loc) {
|
||||
ut64 add = r_read_le64 (loc);
|
||||
ut64 newv = base_vaddr != UT64_MAX? (base_vaddr + add): add;
|
||||
for (int b = 0; b < 8; b++) {
|
||||
loc[b] = (ut8) ((newv >> (8 * b)) & 0xff);
|
||||
}
|
||||
elf_write_word (loc, base + r_read_le64 (loc), true);
|
||||
}
|
||||
curr = addr + 8;
|
||||
} else {
|
||||
ut64 bitmap = R >> 1;
|
||||
for (int bit = 0; bit < 63; bit++) {
|
||||
if (bitmap & (1ULL << bit)) {
|
||||
ut64 addr = curr + (ut64) (bit + 1) * 8ULL;
|
||||
ut8 *loc = (ut8 *)elf_vm_to_ptr (&e, addr);
|
||||
if (!loc) {
|
||||
continue;
|
||||
}
|
||||
ut64 add = r_read_le64 (loc);
|
||||
ut64 newv = base_vaddr != UT64_MAX? (base_vaddr + add): add;
|
||||
for (int b = 0; b < 8; b++) {
|
||||
loc[b] = (ut8) ((newv >> (8 * b)) & 0xff);
|
||||
}
|
||||
if (! (bitmap & (1ULL << bit))) {
|
||||
continue;
|
||||
}
|
||||
ut64 addr = curr + (ut64) (bit + 1) * 8ULL;
|
||||
ut8 *loc = (ut8 *)elf_vm_to_ptr (&e, addr);
|
||||
if (loc) {
|
||||
elf_write_word (loc, base + r_read_le64 (loc), true);
|
||||
}
|
||||
}
|
||||
curr += 8ULL * 63ULL;
|
||||
@@ -389,9 +369,7 @@ R_API bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *e
|
||||
ut32 min_seen = (pass == 0)? 8: sample / 2;
|
||||
ut32 min_good = (pass == 0)? 8: (sample * 3) / 4;
|
||||
if (elf_probe_table (&e, arrptr, cnt, ptrsz, base_vaddr, text_lo, text_hi, min_seen, min_good, method_count, candidates)) {
|
||||
if (r2unity_is_debug ()) {
|
||||
fprintf (stderr, "[r2unity/elf] pass=%d arrptr=0x%" PFMT64x " cnt=%u\n", pass, arrptr, cnt);
|
||||
}
|
||||
R_LOG_DEBUG ("[elf] pass=%d arrptr=0x%" PFMT64x " cnt=%u", pass, arrptr, cnt);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
+347
-320
@@ -3,15 +3,88 @@
|
||||
#include "lib.h"
|
||||
#include <r_util.h>
|
||||
|
||||
static bool g_debug = false;
|
||||
/* On-disk header layouts. Each newer wire version appends fields, so the older
|
||||
* structs are prefixes of the newer ones (except v38 which switched to section
|
||||
* tuples). Only used during parsing; the normalized data lives in
|
||||
* R2UnityMetadata.sections[]. */
|
||||
typedef struct {
|
||||
uint32_t sanity;
|
||||
int32_t version;
|
||||
uint32_t stringLiteralOffset;
|
||||
int32_t stringLiteralSize;
|
||||
uint32_t stringLiteralDataOffset;
|
||||
int32_t stringLiteralDataSize;
|
||||
uint32_t stringOffset;
|
||||
int32_t stringSize;
|
||||
uint32_t eventsOffset;
|
||||
int32_t eventsSize;
|
||||
uint32_t propertiesOffset;
|
||||
int32_t propertiesSize;
|
||||
uint32_t methodsOffset;
|
||||
int32_t methodsSize;
|
||||
uint32_t parameterDefaultValuesOffset;
|
||||
int32_t parameterDefaultValuesSize;
|
||||
uint32_t fieldDefaultValuesOffset;
|
||||
int32_t fieldDefaultValuesSize;
|
||||
uint32_t fieldAndParameterDefaultValueDataOffset;
|
||||
int32_t fieldAndParameterDefaultValueDataSize;
|
||||
uint32_t fieldMarshaledSizesOffset;
|
||||
int32_t fieldMarshaledSizesSize;
|
||||
uint32_t parametersOffset;
|
||||
int32_t parametersSize;
|
||||
uint32_t fieldsOffset;
|
||||
int32_t fieldsSize;
|
||||
uint32_t genericParametersOffset;
|
||||
int32_t genericParametersSize;
|
||||
uint32_t genericParameterConstraintsOffset;
|
||||
int32_t genericParameterConstraintsSize;
|
||||
uint32_t genericContainersOffset;
|
||||
int32_t genericContainersSize;
|
||||
uint32_t nestedTypesOffset;
|
||||
int32_t nestedTypesSize;
|
||||
uint32_t interfacesOffset;
|
||||
int32_t interfacesSize;
|
||||
uint32_t vtableMethodsOffset;
|
||||
int32_t vtableMethodsSize;
|
||||
uint32_t interfaceOffsetsOffset;
|
||||
int32_t interfaceOffsetsSize;
|
||||
uint32_t typeDefinitionsOffset;
|
||||
int32_t typeDefinitionsSize;
|
||||
uint32_t imagesOffset;
|
||||
int32_t imagesSize;
|
||||
uint32_t assembliesOffset;
|
||||
int32_t assembliesSize;
|
||||
uint32_t fieldRefsOffset;
|
||||
int32_t fieldRefsSize;
|
||||
uint32_t referencedAssembliesOffset;
|
||||
int32_t referencedAssembliesSize;
|
||||
uint32_t attributesInfoOffset;
|
||||
int32_t attributesInfoSize;
|
||||
uint32_t attributeTypesOffset;
|
||||
int32_t attributeTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterTypesOffset;
|
||||
int32_t unresolvedVirtualCallParameterTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterRangesOffset;
|
||||
int32_t unresolvedVirtualCallParameterRangesSize;
|
||||
uint32_t windowsRuntimeTypeNamesOffset;
|
||||
int32_t windowsRuntimeTypeNamesSize;
|
||||
uint32_t windowsRuntimeStringsOffset;
|
||||
int32_t windowsRuntimeStringsSize;
|
||||
uint32_t exportedTypeDefinitionsOffset;
|
||||
int32_t exportedTypeDefinitionsSize;
|
||||
/* v27+ */
|
||||
uint32_t rgctxEntriesOffset;
|
||||
int32_t rgctxEntriesSize;
|
||||
/* v29+ */
|
||||
uint32_t rgctxEntriesDataOffset;
|
||||
int32_t rgctxEntriesDataSize;
|
||||
} Il2CppGlobalMetadataHeader_legacy;
|
||||
|
||||
R_API void r2unity_set_debug(bool v) {
|
||||
g_debug = v;
|
||||
}
|
||||
|
||||
R_API bool r2unity_is_debug(void) {
|
||||
return g_debug;
|
||||
}
|
||||
typedef struct {
|
||||
uint32_t sanity;
|
||||
int32_t version;
|
||||
Il2CppMetadataSection sections[R2UNITY_METADATA_BASE_SECTION_COUNT];
|
||||
} Il2CppGlobalMetadataHeader_v38;
|
||||
|
||||
static const char *metadata_section_names[R2UNITY_METADATA_SECTION_COUNT] = {
|
||||
"string_literals",
|
||||
@@ -109,8 +182,7 @@ static void set_section(Il2CppMetadataSection *s, uint32_t off, int32_t size) {
|
||||
s->count = 0;
|
||||
}
|
||||
|
||||
static void init_legacy_sections(R2UnityMetadata *meta) {
|
||||
const Il2CppGlobalMetadataHeader_v24 *h = &meta->header.v24;
|
||||
static void init_legacy_sections(R2UnityMetadata *meta, const Il2CppGlobalMetadataHeader_legacy *h) {
|
||||
Il2CppMetadataSection *s = meta->sections;
|
||||
set_section (&s[R2U_SEC_STRING_LITERALS], h->stringLiteralOffset, h->stringLiteralSize);
|
||||
set_section (&s[R2U_SEC_STRING_LITERAL_DATA], h->stringLiteralDataOffset, h->stringLiteralDataSize);
|
||||
@@ -143,13 +215,11 @@ static void init_legacy_sections(R2UnityMetadata *meta) {
|
||||
set_section (&s[R2U_SEC_WINDOWS_RUNTIME_TYPE_NAMES], h->windowsRuntimeTypeNamesOffset, h->windowsRuntimeTypeNamesSize);
|
||||
set_section (&s[R2U_SEC_WINDOWS_RUNTIME_STRINGS], h->windowsRuntimeStringsOffset, h->windowsRuntimeStringsSize);
|
||||
set_section (&s[R2U_SEC_EXPORTED_TYPE_DEFINITIONS], h->exportedTypeDefinitionsOffset, h->exportedTypeDefinitionsSize);
|
||||
if (meta->version >= 27 && meta->version < 29) {
|
||||
const Il2CppGlobalMetadataHeader_v27 *h27 = &meta->header.v27;
|
||||
set_section (&s[R2U_SEC_RGCTX_ENTRIES], h27->rgctxEntriesOffset, h27->rgctxEntriesSize);
|
||||
} else if (meta->version >= 29) {
|
||||
const Il2CppGlobalMetadataHeader_v29 *h29 = &meta->header.v29;
|
||||
set_section (&s[R2U_SEC_RGCTX_ENTRIES], h29->rgctxEntriesOffset, h29->rgctxEntriesSize);
|
||||
set_section (&s[R2U_SEC_RGCTX_ENTRIES_DATA], h29->rgctxEntriesDataOffset, h29->rgctxEntriesDataSize);
|
||||
if (meta->version >= 27) {
|
||||
set_section (&s[R2U_SEC_RGCTX_ENTRIES], h->rgctxEntriesOffset, h->rgctxEntriesSize);
|
||||
}
|
||||
if (meta->version >= 29) {
|
||||
set_section (&s[R2U_SEC_RGCTX_ENTRIES_DATA], h->rgctxEntriesDataOffset, h->rgctxEntriesDataSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +331,25 @@ static bool is_v24_0(R2UnityMetadata *meta) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Wire-version header sizes on disk; v27/v29 are v24 + extra rgctx fields. */
|
||||
#define R2U_HDR_V24 248
|
||||
#define R2U_HDR_V27 256
|
||||
#define R2U_HDR_V29 264
|
||||
|
||||
static size_t header_size_for(int32_t version) {
|
||||
if (version >= 38) {
|
||||
return sizeof (Il2CppGlobalMetadataHeader_v38);
|
||||
}
|
||||
if (version < 27) {
|
||||
return R2U_HDR_V24;
|
||||
}
|
||||
if (version < 29) {
|
||||
return R2U_HDR_V27;
|
||||
}
|
||||
/* v29..v35 share layout (v30, v31 reuse these fields). */
|
||||
return R2U_HDR_V29;
|
||||
}
|
||||
|
||||
R_API R2UnityMetadata *r2unity_parse_metadata(RBuffer *buf) {
|
||||
R_RETURN_VAL_IF_FAIL (buf, NULL);
|
||||
ut8 preamble[8];
|
||||
@@ -274,17 +363,7 @@ R_API R2UnityMetadata *r2unity_parse_metadata(RBuffer *buf) {
|
||||
if (version < 24 || version > 39 || (version > 35 && version < 38)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t header_size;
|
||||
if (version >= 38) {
|
||||
header_size = sizeof (Il2CppGlobalMetadataHeader_v38);
|
||||
} else if (version < 27) {
|
||||
header_size = sizeof (Il2CppGlobalMetadataHeader_v24);
|
||||
} else if (version < 29) {
|
||||
header_size = sizeof (Il2CppGlobalMetadataHeader_v27);
|
||||
} else {
|
||||
/* v29..v35 share layout (v30, v31 reuse these fields). */
|
||||
header_size = sizeof (Il2CppGlobalMetadataHeader_v29);
|
||||
}
|
||||
const size_t header_size = header_size_for (version);
|
||||
R2UnityMetadata *meta = R_NEW0 (R2UnityMetadata);
|
||||
meta->version = version;
|
||||
meta->buf = buf;
|
||||
@@ -292,19 +371,20 @@ R_API R2UnityMetadata *r2unity_parse_metadata(RBuffer *buf) {
|
||||
meta->typeDefinitionIndexSize = 4;
|
||||
meta->genericContainerIndexSize = 4;
|
||||
meta->parameterIndexSize = 4;
|
||||
if (r_buf_read_at (buf, 0, (ut8 *)&meta->header.v24, header_size) != (st64)header_size) {
|
||||
R_FREE (meta);
|
||||
return NULL;
|
||||
}
|
||||
/* All Il2Cpp header fields are 32-bit words; sweep in-place for BE hosts
|
||||
*(no-op on LE). This also normalises the fields accessed below. */
|
||||
uint32_t *hdr_words = (uint32_t *)&meta->header;
|
||||
size_t nfields = header_size / sizeof (uint32_t);
|
||||
for (size_t i = 0; i < nfields; i++) {
|
||||
hdr_words[i] = r_read_le32 (&hdr_words[i]);
|
||||
}
|
||||
if (version >= 38) {
|
||||
memcpy (meta->sections, &meta->header.v38.stringLiterals,
|
||||
Il2CppGlobalMetadataHeader_v38 hdr = {0};
|
||||
if (r_buf_read_at (buf, 0, (ut8 *)&hdr, header_size) != (st64)header_size) {
|
||||
R_FREE (meta);
|
||||
return NULL;
|
||||
}
|
||||
/* All Il2Cpp header fields are 32-bit words; sweep in-place for BE
|
||||
* hosts (no-op on LE). */
|
||||
uint32_t *w = (uint32_t *)&hdr;
|
||||
const size_t n = header_size / sizeof (uint32_t);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
w[i] = r_read_le32 (&w[i]);
|
||||
}
|
||||
memcpy (meta->sections, hdr.sections,
|
||||
sizeof (Il2CppMetadataSection) * R2UNITY_METADATA_BASE_SECTION_COUNT);
|
||||
Il2CppMetadataSection *s = meta->sections;
|
||||
if (s[R2U_SEC_PARAMETERS].count) {
|
||||
@@ -320,7 +400,17 @@ R_API R2UnityMetadata *r2unity_parse_metadata(RBuffer *buf) {
|
||||
meta->genericContainerIndexSize = index_size_from_count (s[R2U_SEC_GENERIC_CONTAINERS].count);
|
||||
meta->parameterIndexSize = version >= 39? index_size_from_count (s[R2U_SEC_PARAMETERS].count): 4;
|
||||
} else {
|
||||
init_legacy_sections (meta);
|
||||
Il2CppGlobalMetadataHeader_legacy hdr = {0};
|
||||
if (r_buf_read_at (buf, 0, (ut8 *)&hdr, header_size) != (st64)header_size) {
|
||||
R_FREE (meta);
|
||||
return NULL;
|
||||
}
|
||||
uint32_t *w = (uint32_t *)&hdr;
|
||||
const size_t n = header_size / sizeof (uint32_t);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
w[i] = r_read_le32 (&w[i]);
|
||||
}
|
||||
init_legacy_sections (meta, &hdr);
|
||||
}
|
||||
Il2CppMetadataSection *s = meta->sections;
|
||||
meta->stringOffset = s[R2U_SEC_STRINGS].offset;
|
||||
@@ -342,19 +432,20 @@ R_API R2UnityMetadata *r2unity_parse_metadata(RBuffer *buf) {
|
||||
}
|
||||
meta->strings = r_buf_new_slice (buf, meta->stringOffset, meta->stringSize);
|
||||
meta->string_literals = r_buf_new_slice (buf, meta->stringLiteralOffset, meta->stringLiteralSize);
|
||||
if (g_debug) {
|
||||
fprintf (stderr, "[r2unity] meta version=%d strings=%u@0x%x methods=%d@0x%x types=%d@0x%x\n", meta->version, (unsigned)meta->stringSize, (unsigned)meta->stringOffset, (int)meta->methodsSize, (unsigned)meta->methodsOffset, (int)meta->typeDefinitionsSize, (unsigned)meta->typeDefinitionsOffset);
|
||||
if (version >= 38) {
|
||||
fprintf (stderr, "[r2unity] v38+ counts literals=%u methods=%u types=%u images=%u index_sizes=%d/%d/%d/%d\n",
|
||||
(unsigned)s[R2U_SEC_STRING_LITERALS].count,
|
||||
(unsigned)s[R2U_SEC_METHODS].count,
|
||||
(unsigned)s[R2U_SEC_TYPE_DEFINITIONS].count,
|
||||
(unsigned)s[R2U_SEC_IMAGES].count,
|
||||
meta->typeIndexSize,
|
||||
meta->typeDefinitionIndexSize,
|
||||
meta->genericContainerIndexSize,
|
||||
meta->parameterIndexSize);
|
||||
}
|
||||
R_LOG_DEBUG ("meta version=%d strings=%u@0x%x methods=%d@0x%x types=%d@0x%x",
|
||||
meta->version, (unsigned)meta->stringSize, (unsigned)meta->stringOffset,
|
||||
(int)meta->methodsSize, (unsigned)meta->methodsOffset,
|
||||
(int)meta->typeDefinitionsSize, (unsigned)meta->typeDefinitionsOffset);
|
||||
if (version >= 38) {
|
||||
R_LOG_DEBUG ("v38+ counts literals=%u methods=%u types=%u images=%u index_sizes=%d/%d/%d/%d",
|
||||
(unsigned)s[R2U_SEC_STRING_LITERALS].count,
|
||||
(unsigned)s[R2U_SEC_METHODS].count,
|
||||
(unsigned)s[R2U_SEC_TYPE_DEFINITIONS].count,
|
||||
(unsigned)s[R2U_SEC_IMAGES].count,
|
||||
meta->typeIndexSize,
|
||||
meta->typeDefinitionIndexSize,
|
||||
meta->genericContainerIndexSize,
|
||||
meta->parameterIndexSize);
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
@@ -405,9 +496,7 @@ R_API ut64 r2unity_metadata_section_entry_size(R2UnityMetadata *meta, R2UMetadat
|
||||
case R2U_SEC_IMAGES:
|
||||
return image_definition_entry_size (meta);
|
||||
case R2U_SEC_ASSEMBLIES: {
|
||||
size_t image_count = 0;
|
||||
Il2CppImageDefinition *images = r2unity_get_images (meta, &image_count);
|
||||
R_FREE (images);
|
||||
ut64 image_count = r2unity_metadata_section_count (meta, R2U_SEC_IMAGES);
|
||||
return image_count? sec.size / image_count: 0;
|
||||
}
|
||||
case R2U_SEC_REFERENCED_ASSEMBLIES:
|
||||
@@ -437,48 +526,36 @@ R_API ut64 r2unity_metadata_section_count(R2UnityMetadata *meta, R2UMetadataSect
|
||||
|
||||
R_API ut64 r2unity_metadata_header_size(R2UnityMetadata *meta) {
|
||||
R_RETURN_VAL_IF_FAIL (meta, 0);
|
||||
if (meta->version >= 38) {
|
||||
return sizeof (Il2CppGlobalMetadataHeader_v38);
|
||||
}
|
||||
if (meta->version < 27) {
|
||||
return sizeof (Il2CppGlobalMetadataHeader_v24);
|
||||
}
|
||||
if (meta->version < 29) {
|
||||
return sizeof (Il2CppGlobalMetadataHeader_v27);
|
||||
}
|
||||
return sizeof (Il2CppGlobalMetadataHeader_v29);
|
||||
return header_size_for (meta->version);
|
||||
}
|
||||
|
||||
R_API const char *r2unity_get_string(R2UnityMetadata *meta, uint32_t index) {
|
||||
R_API char *r2unity_get_string(R2UnityMetadata *meta, uint32_t index) {
|
||||
R_RETURN_VAL_IF_FAIL (meta, NULL);
|
||||
if (!meta->strings || index >= r_buf_size (meta->strings)) {
|
||||
return NULL;
|
||||
}
|
||||
// Align index to the beginning of the string in case it points mid-string
|
||||
ut8 bprev = 0;
|
||||
ut64 idx = index;
|
||||
while (idx > 0) {
|
||||
if (r_buf_read_at (meta->strings, idx - 1, &bprev, 1) != 1) {
|
||||
break;
|
||||
}
|
||||
if (bprev == 0) {
|
||||
ut8 bprev = 0;
|
||||
if (r_buf_read_at (meta->strings, idx - 1, &bprev, 1) != 1 || !bprev) {
|
||||
break;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
// Read until null terminator
|
||||
char *str = NULL;
|
||||
ut64 len = 0;
|
||||
ut8 byte;
|
||||
while (r_buf_read_at (meta->strings, idx + len, &byte, 1) == 1 && byte != 0) {
|
||||
while (r_buf_read_at (meta->strings, idx + len, &byte, 1) == 1 && byte) {
|
||||
len++;
|
||||
}
|
||||
if (len > 0) {
|
||||
str = R_NEWS (char, len + 1);
|
||||
if (str) {
|
||||
r_buf_read_at (meta->strings, idx, (ut8 *)str, len);
|
||||
str[len] = 0;
|
||||
}
|
||||
if (!len) {
|
||||
return NULL;
|
||||
}
|
||||
char *str = R_NEWS (char, len + 1);
|
||||
if (str) {
|
||||
r_buf_read_at (meta->strings, idx, (ut8 *)str, len);
|
||||
str[len] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@@ -546,11 +623,7 @@ R_API Il2CppTypeDefinition *r2unity_get_type_definitions(R2UnityMetadata *meta,
|
||||
const bool has_element_type = (meta->version <= 31);
|
||||
const int type_index_size = compact_indices? meta->typeIndexSize: 4;
|
||||
const int generic_container_size = compact_indices? meta->genericContainerIndexSize: 4;
|
||||
const ut64 entry = 4 + 4
|
||||
+ type_index_size + type_index_size + type_index_size
|
||||
+ (has_element_type? 4: 0)
|
||||
+ generic_container_size
|
||||
+ 4 + 32 + 16 + 4 + 4;
|
||||
const ut64 entry = type_definition_entry_size (meta);
|
||||
ut8 *buf = read_metadata_table (meta, R2U_SEC_TYPE_DEFINITIONS, entry, count);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
@@ -608,14 +681,7 @@ R_API Il2CppMethodDefinition *r2unity_get_method_definitions(R2UnityMetadata *me
|
||||
const int type_index_size = compact_indices? meta->typeIndexSize: 4;
|
||||
const int parameter_index_size = meta->version >= 39? meta->parameterIndexSize: 4;
|
||||
const int generic_container_size = compact_indices? meta->genericContainerIndexSize: 4;
|
||||
const ut64 entry = 4
|
||||
+ type_definition_size
|
||||
+ type_index_size
|
||||
+ (has_return_parameter? 4: 0)
|
||||
+ parameter_index_size
|
||||
+ generic_container_size
|
||||
+ 4 + 2 + 2 + 2 + 2;
|
||||
|
||||
const ut64 entry = method_definition_entry_size (meta);
|
||||
ut8 *buf = read_metadata_table (meta, R2U_SEC_METHODS, entry, count);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
@@ -650,8 +716,7 @@ R_API Il2CppImageDefinition *r2unity_get_images(R2UnityMetadata *meta, size_t *c
|
||||
*count = 0;
|
||||
const bool compact_indices = (meta->version >= 35);
|
||||
const int type_definition_size = compact_indices? meta->typeDefinitionIndexSize: 4;
|
||||
const ut64 entry = 4 + 4 + type_definition_size + 4
|
||||
+ type_definition_size + 4 + 4 + 4 + 4 + 4;
|
||||
const ut64 entry = image_definition_entry_size (meta);
|
||||
ut8 *buf = read_metadata_table (meta, R2U_SEC_IMAGES, entry, count);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
@@ -786,43 +851,26 @@ R_API Il2CppAssemblyDefinition *r2unity_get_assemblies(R2UnityMetadata *meta, si
|
||||
R_API int32_t *r2unity_get_referenced_assemblies(R2UnityMetadata *meta, size_t *count) {
|
||||
R_RETURN_VAL_IF_FAIL (meta && count, NULL);
|
||||
*count = 0;
|
||||
Il2CppMetadataSection sec = meta->sections[R2U_SEC_REFERENCED_ASSEMBLIES];
|
||||
ut64 rsize = sec.size;
|
||||
if (rsize < 4 || (rsize % 4) != 0) {
|
||||
const Il2CppMetadataSection sec = meta->sections[R2U_SEC_REFERENCED_ASSEMBLIES];
|
||||
if (sec.size < 4 || (sec.size % 4) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
*count = (size_t) (rsize / 4);
|
||||
int32_t *out = R_NEWS (int32_t, *count);
|
||||
const size_t n = sec.size / 4;
|
||||
int32_t *out = R_NEWS (int32_t, n);
|
||||
if (!out) {
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
ut8 *buf = R_NEWS (ut8, rsize);
|
||||
if (!buf) {
|
||||
if (r_buf_read_at (meta->buf, sec.offset, (ut8 *)out, sec.size) != (st64)sec.size) {
|
||||
R_FREE (out);
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (r_buf_read_at (meta->buf, sec.offset, buf, rsize) != (st64)rsize) {
|
||||
R_FREE (buf);
|
||||
R_FREE (out);
|
||||
*count = 0;
|
||||
return NULL;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
out[i] = (int32_t)r_read_le32 (out + i);
|
||||
}
|
||||
for (size_t i = 0; i < *count; i++) {
|
||||
out[i] = (int32_t)r_read_le32 (buf + i * 4);
|
||||
}
|
||||
R_FREE (buf);
|
||||
*count = n;
|
||||
return out;
|
||||
}
|
||||
|
||||
R_API bool r2unity_read_method_pointers_at(R2UnityMetadata *meta, const char *exe_path, ut64 addr, size_t count, ut64 **out_ptrs) {
|
||||
R_RETURN_VAL_IF_FAIL (meta && exe_path && out_ptrs, false);
|
||||
(void)addr;
|
||||
(void)count;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Per-image sorted (token, method_idx) index used for scoped token lookups.
|
||||
* Method tokens are only unique within their owning image. */
|
||||
typedef struct {
|
||||
@@ -873,105 +921,112 @@ static int image_index_for_method(const int *type2img, size_t type_count, const
|
||||
static char *build_qualified_name(R2UnityMetadata *meta,
|
||||
const Il2CppTypeDefinition *td,
|
||||
uint32_t method_name_idx) {
|
||||
char *ns = td? (char *)r2unity_get_string (meta, td->namespaceIndex): NULL;
|
||||
char *tn = td? (char *)r2unity_get_string (meta, td->nameIndex): NULL;
|
||||
char *mn = (char *)r2unity_get_string (meta, method_name_idx);
|
||||
char *ns = td? r2unity_get_string (meta, td->namespaceIndex): NULL;
|
||||
char *tn = td? r2unity_get_string (meta, td->nameIndex): NULL;
|
||||
char *mn = r2unity_get_string (meta, method_name_idx);
|
||||
if (!mn) {
|
||||
free (ns);
|
||||
free (tn);
|
||||
return NULL;
|
||||
}
|
||||
char buf[1024];
|
||||
char *out;
|
||||
if (ns && *ns && tn && *tn) {
|
||||
snprintf (buf, sizeof (buf), "%s.%s.%s", ns, tn, mn);
|
||||
out = r_str_newf ("%s.%s.%s", ns, tn, mn);
|
||||
} else if (tn && *tn) {
|
||||
snprintf (buf, sizeof (buf), "%s.%s", tn, mn);
|
||||
out = r_str_newf ("%s.%s", tn, mn);
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "%s", mn);
|
||||
out = strdup (mn);
|
||||
}
|
||||
char *out = strdup (buf);
|
||||
free (ns);
|
||||
free (tn);
|
||||
free (mn);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Shared context for P/Invoke and reverse P/Invoke enumeration. */
|
||||
typedef struct {
|
||||
R2UnityMetadata *meta;
|
||||
Il2CppMethodDefinition *methods;
|
||||
size_t method_count;
|
||||
Il2CppTypeDefinition *types;
|
||||
size_t type_count;
|
||||
Il2CppImageDefinition *images;
|
||||
size_t image_count;
|
||||
int *type2img;
|
||||
} InteropCtx;
|
||||
|
||||
static bool interop_ctx_init(InteropCtx *c, R2UnityMetadata *meta) {
|
||||
memset (c, 0, sizeof (*c));
|
||||
c->meta = meta;
|
||||
c->methods = r2unity_get_method_definitions (meta, &c->method_count);
|
||||
if (!c->methods || !c->method_count) {
|
||||
return false;
|
||||
}
|
||||
c->types = r2unity_get_type_definitions (meta, &c->type_count);
|
||||
c->images = r2unity_get_images (meta, &c->image_count);
|
||||
c->type2img = build_type2img (c->images, c->image_count, c->type_count);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void interop_ctx_fini(InteropCtx *c) {
|
||||
R_FREE (c->methods);
|
||||
R_FREE (c->types);
|
||||
R_FREE (c->images);
|
||||
R_FREE (c->type2img);
|
||||
}
|
||||
|
||||
static void interop_fill(R2UnityInterop *it, const InteropCtx *c, int32_t method_index, uint8_t kind) {
|
||||
const Il2CppMethodDefinition *m = &c->methods[method_index];
|
||||
it->kind = kind;
|
||||
it->method_index = method_index;
|
||||
it->token = m->token;
|
||||
it->flags = m->flags;
|
||||
it->iflags = m->iflags;
|
||||
it->wrapper_va = 0;
|
||||
it->wrapper_index = UINT32_MAX;
|
||||
it->confidence = 100;
|
||||
|
||||
const Il2CppTypeDefinition *td = NULL;
|
||||
if (c->types && m->declaringType >= 0 && (size_t)m->declaringType < c->type_count) {
|
||||
td = &c->types[m->declaringType];
|
||||
}
|
||||
it->name = build_qualified_name (c->meta, td, m->nameIndex);
|
||||
|
||||
int img_idx = image_index_for_method (c->type2img, c->type_count, m);
|
||||
it->image_index = img_idx;
|
||||
if (img_idx >= 0 && c->images && (size_t)img_idx < c->image_count) {
|
||||
it->image_name = r2unity_get_string (c->meta, c->images[img_idx].nameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
R_API R2UnityInterop *r2unity_enumerate_pinvokes(R2UnityMetadata *meta, size_t *count) {
|
||||
R_RETURN_VAL_IF_FAIL (meta && count, NULL);
|
||||
*count = 0;
|
||||
|
||||
size_t method_count = 0;
|
||||
Il2CppMethodDefinition *methods = r2unity_get_method_definitions (meta, &method_count);
|
||||
if (!methods || !method_count) {
|
||||
R_FREE (methods);
|
||||
InteropCtx c;
|
||||
if (!interop_ctx_init (&c, meta)) {
|
||||
interop_ctx_fini (&c);
|
||||
return NULL;
|
||||
}
|
||||
size_t type_count = 0;
|
||||
Il2CppTypeDefinition *types = r2unity_get_type_definitions (meta, &type_count);
|
||||
size_t image_count = 0;
|
||||
Il2CppImageDefinition *images = r2unity_get_images (meta, &image_count);
|
||||
int *type2img = build_type2img (images, image_count, type_count);
|
||||
|
||||
/* First pass: count P/Invoke methods. */
|
||||
size_t n = 0;
|
||||
for (size_t j = 0; j < method_count; j++) {
|
||||
if (methods[j].flags & IL2CPP_METHOD_ATTRIBUTE_PINVOKE_IMPL) {
|
||||
for (size_t j = 0; j < c.method_count; j++) {
|
||||
if (c.methods[j].flags & IL2CPP_METHOD_ATTRIBUTE_PINVOKE_IMPL) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (!n) {
|
||||
R_FREE (methods);
|
||||
R_FREE (types);
|
||||
R_FREE (images);
|
||||
R_FREE (type2img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R2UnityInterop *out = R_NEWS0 (R2UnityInterop, n);
|
||||
if (!out) {
|
||||
R_FREE (methods);
|
||||
R_FREE (types);
|
||||
R_FREE (images);
|
||||
R_FREE (type2img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t k = 0;
|
||||
for (size_t j = 0; j < method_count && k < n; j++) {
|
||||
Il2CppMethodDefinition *m = &methods[j];
|
||||
if (! (m->flags & IL2CPP_METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
|
||||
continue;
|
||||
R2UnityInterop *out = n? R_NEWS0 (R2UnityInterop, n): NULL;
|
||||
if (out) {
|
||||
size_t k = 0;
|
||||
for (size_t j = 0; j < c.method_count && k < n; j++) {
|
||||
if (c.methods[j].flags & IL2CPP_METHOD_ATTRIBUTE_PINVOKE_IMPL) {
|
||||
/* DLL name / entry-point recovery requires attribute-BLOB
|
||||
* decoding (v29+) or generator disassembly (v<=27.2);
|
||||
* not implemented yet. */
|
||||
interop_fill (&out[k++], &c, (int32_t)j, R2U_INTEROP_PINVOKE);
|
||||
}
|
||||
}
|
||||
R2UnityInterop *it = &out[k++];
|
||||
it->kind = R2U_INTEROP_PINVOKE;
|
||||
it->method_index = (int32_t)j;
|
||||
it->token = m->token;
|
||||
it->flags = m->flags;
|
||||
it->iflags = m->iflags;
|
||||
it->wrapper_va = 0;
|
||||
it->wrapper_index = UINT32_MAX;
|
||||
it->confidence = 100;
|
||||
|
||||
const Il2CppTypeDefinition *td = NULL;
|
||||
if (types && m->declaringType >= 0 && (size_t)m->declaringType < type_count) {
|
||||
td = &types[m->declaringType];
|
||||
}
|
||||
it->name = build_qualified_name (meta, td, m->nameIndex);
|
||||
int img_idx = image_index_for_method (type2img, type_count, m);
|
||||
it->image_index = img_idx;
|
||||
if (img_idx >= 0 && images && (size_t)img_idx < image_count) {
|
||||
it->image_name = (char *)r2unity_get_string (meta, images[img_idx].nameIndex);
|
||||
}
|
||||
/* DLL name / entry-point recovery requires attribute-BLOB decoding
|
||||
*(v29+) or generator disassembly (v<=27.2). Not implemented yet. */
|
||||
*count = n;
|
||||
}
|
||||
|
||||
R_FREE (methods);
|
||||
R_FREE (types);
|
||||
R_FREE (images);
|
||||
R_FREE (type2img);
|
||||
|
||||
*count = n;
|
||||
interop_ctx_fini (&c);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -1123,6 +1178,78 @@ static uint8_t attribute_range_interop_kind(
|
||||
return kind;
|
||||
}
|
||||
|
||||
/* Per-image sorted (token, method_idx) index for scoped binary search. */
|
||||
typedef struct {
|
||||
int32_t *start;
|
||||
int32_t *count;
|
||||
R2UTokIdx *map;
|
||||
} TokIndex;
|
||||
|
||||
static void tokindex_free(TokIndex *t) {
|
||||
R_FREE (t->start);
|
||||
R_FREE (t->count);
|
||||
R_FREE (t->map);
|
||||
}
|
||||
|
||||
static bool tokindex_build(TokIndex *t, const InteropCtx *c) {
|
||||
memset (t, 0, sizeof (*t));
|
||||
if (!c->type2img || !c->image_count) {
|
||||
return false;
|
||||
}
|
||||
t->start = R_NEWS0 (int32_t, c->image_count);
|
||||
t->count = R_NEWS0 (int32_t, c->image_count);
|
||||
t->map = R_NEWS (R2UTokIdx, c->method_count);
|
||||
if (!t->start || !t->count || !t->map) {
|
||||
tokindex_free (t);
|
||||
return false;
|
||||
}
|
||||
for (size_t j = 0; j < c->method_count; j++) {
|
||||
int ii = image_index_for_method (c->type2img, c->type_count, &c->methods[j]);
|
||||
if (ii < 0 || (size_t)ii >= c->image_count || !c->methods[j].token) {
|
||||
continue;
|
||||
}
|
||||
t->count[ii]++;
|
||||
}
|
||||
int32_t acc = 0;
|
||||
for (size_t ii = 0; ii < c->image_count; ii++) {
|
||||
t->start[ii] = acc;
|
||||
acc += t->count[ii];
|
||||
t->count[ii] = 0;
|
||||
}
|
||||
for (size_t j = 0; j < c->method_count; j++) {
|
||||
int ii = image_index_for_method (c->type2img, c->type_count, &c->methods[j]);
|
||||
if (ii < 0 || (size_t)ii >= c->image_count || !c->methods[j].token) {
|
||||
continue;
|
||||
}
|
||||
int32_t pos = t->start[ii] + t->count[ii]++;
|
||||
t->map[pos].token = c->methods[j].token;
|
||||
t->map[pos].idx = (int32_t)j;
|
||||
}
|
||||
for (size_t ii = 0; ii < c->image_count; ii++) {
|
||||
qsort (t->map + t->start[ii], (size_t)t->count[ii], sizeof (R2UTokIdx), cmp_tokidx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int32_t tokindex_lookup(const TokIndex *t, size_t image_idx, uint32_t token) {
|
||||
if (!t->map) {
|
||||
return -1;
|
||||
}
|
||||
size_t lo = (size_t)t->start[image_idx];
|
||||
size_t hi = lo + (size_t)t->count[image_idx];
|
||||
while (lo < hi) {
|
||||
size_t mid = (lo + hi) >> 1;
|
||||
if (t->map[mid].token < token) {
|
||||
lo = mid + 1;
|
||||
} else if (t->map[mid].token > token) {
|
||||
hi = mid;
|
||||
} else {
|
||||
return t->map[mid].idx;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
R_API R2UnityInterop *r2unity_enumerate_reverse_pinvokes(R2UnityMetadata *meta, size_t *count) {
|
||||
R_RETURN_VAL_IF_FAIL (meta && count, NULL);
|
||||
*count = 0;
|
||||
@@ -1130,117 +1257,47 @@ R_API R2UnityInterop *r2unity_enumerate_reverse_pinvokes(R2UnityMetadata *meta,
|
||||
/* Pre-v29: attribute args live in native generator stubs; see doc/pinvoke.md §4.2. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t method_count = 0;
|
||||
Il2CppMethodDefinition *methods = r2unity_get_method_definitions (meta, &method_count);
|
||||
if (!methods || !method_count) {
|
||||
R_FREE (methods);
|
||||
InteropCtx c;
|
||||
if (!interop_ctx_init (&c, meta)) {
|
||||
interop_ctx_fini (&c);
|
||||
return NULL;
|
||||
}
|
||||
size_t type_count = 0;
|
||||
Il2CppTypeDefinition *types = r2unity_get_type_definitions (meta, &type_count);
|
||||
size_t image_count = 0;
|
||||
Il2CppImageDefinition *images = r2unity_get_images (meta, &image_count);
|
||||
|
||||
ut64 attr_data_off = 0, attr_data_size = 0;
|
||||
size_t nranges = 0;
|
||||
R2UAttrRange *ranges = load_attribute_ranges (meta, &nranges, &attr_data_off, &attr_data_size);
|
||||
if (!ranges || !nranges) {
|
||||
R_FREE (methods);
|
||||
R_FREE (types);
|
||||
R_FREE (images);
|
||||
R_FREE (ranges);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int *type2img = build_type2img (images, image_count, type_count);
|
||||
|
||||
/* Build per-image sorted (token, method_idx) index. */
|
||||
int32_t *img_tok_start = NULL;
|
||||
int32_t *img_tok_count = NULL;
|
||||
R2UTokIdx *tmap = NULL;
|
||||
if (type2img && image_count) {
|
||||
img_tok_start = R_NEWS0 (int32_t, image_count);
|
||||
img_tok_count = R_NEWS0 (int32_t, image_count);
|
||||
tmap = R_NEWS (R2UTokIdx, method_count);
|
||||
if (!img_tok_start || !img_tok_count || !tmap) {
|
||||
/* Partial allocation: drop all three so the lookup loop's
|
||||
* `if (tmap)` guard correctly skips the index. */
|
||||
R_FREE (img_tok_start);
|
||||
R_FREE (img_tok_count);
|
||||
R_FREE (tmap);
|
||||
} else {
|
||||
for (size_t j = 0; j < method_count; j++) {
|
||||
int img_idx = image_index_for_method (type2img, type_count, &methods[j]);
|
||||
if (img_idx < 0 || (size_t)img_idx >= image_count || !methods[j].token) {
|
||||
continue;
|
||||
}
|
||||
img_tok_count[img_idx]++;
|
||||
}
|
||||
int32_t acc = 0;
|
||||
for (size_t ii = 0; ii < image_count; ii++) {
|
||||
img_tok_start[ii] = acc;
|
||||
acc += img_tok_count[ii];
|
||||
img_tok_count[ii] = 0; /* reused as append cursor */
|
||||
}
|
||||
for (size_t j = 0; j < method_count; j++) {
|
||||
int img_idx = image_index_for_method (type2img, type_count, &methods[j]);
|
||||
if (img_idx < 0 || (size_t)img_idx >= image_count || !methods[j].token) {
|
||||
continue;
|
||||
}
|
||||
int32_t pos = img_tok_start[img_idx] + img_tok_count[img_idx]++;
|
||||
tmap[pos].token = methods[j].token;
|
||||
tmap[pos].idx = (int32_t)j;
|
||||
}
|
||||
for (size_t ii = 0; ii < image_count; ii++) {
|
||||
qsort (tmap + img_tok_start[ii], (size_t)img_tok_count[ii], sizeof (R2UTokIdx), cmp_tokidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate attribute ranges per-image, so method-token lookups stay scoped. */
|
||||
size_t cap = 32;
|
||||
R2UnityInterop *out = R_NEWS0 (R2UnityInterop, cap);
|
||||
TokIndex tok = {0};
|
||||
R2UnityInterop *out = NULL;
|
||||
size_t n = 0;
|
||||
if (!ranges || !nranges) {
|
||||
goto done;
|
||||
}
|
||||
tokindex_build (&tok, &c);
|
||||
|
||||
size_t cap = 32;
|
||||
out = R_NEWS0 (R2UnityInterop, cap);
|
||||
if (!out) {
|
||||
goto done;
|
||||
}
|
||||
for (size_t ii = 0; ii < image_count; ii++) {
|
||||
int32_t r_start = images[ii].customAttributeStart;
|
||||
int32_t r_end = r_start + (int32_t)images[ii].customAttributeCount;
|
||||
for (size_t ii = 0; ii < c.image_count; ii++) {
|
||||
int32_t r_start = c.images[ii].customAttributeStart;
|
||||
int32_t r_end = r_start + (int32_t)c.images[ii].customAttributeCount;
|
||||
if (r_start < 0 || r_end < 0 || (size_t)r_end > nranges) {
|
||||
continue;
|
||||
}
|
||||
for (int32_t ri = r_start; ri < r_end; ri++) {
|
||||
uint32_t tok = ranges[ri].token;
|
||||
if ((tok >> 24) != 0x06) {
|
||||
uint32_t token = ranges[ri].token;
|
||||
if ((token >> 24) != 0x06) {
|
||||
continue;
|
||||
}
|
||||
uint8_t kind = attribute_range_interop_kind (meta, ranges, nranges, (size_t)ri, attr_data_off, attr_data_size, methods, method_count, types, type_count);
|
||||
uint8_t kind = attribute_range_interop_kind (meta, ranges, nranges, (size_t)ri, attr_data_off, attr_data_size, c.methods, c.method_count, c.types, c.type_count);
|
||||
if (!kind) {
|
||||
continue;
|
||||
}
|
||||
/* Binary-search this image's token slice. */
|
||||
int32_t mi = -1;
|
||||
if (tmap) {
|
||||
size_t lo = (size_t)img_tok_start[ii];
|
||||
size_t hi = lo + (size_t)img_tok_count[ii];
|
||||
while (lo < hi) {
|
||||
size_t mid = (lo + hi) >> 1;
|
||||
if (tmap[mid].token < tok) {
|
||||
lo = mid + 1;
|
||||
} else if (tmap[mid].token > tok) {
|
||||
hi = mid;
|
||||
} else {
|
||||
mi = tmap[mid].idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int32_t mi = tokindex_lookup (&tok, ii, token);
|
||||
if (mi < 0) {
|
||||
continue;
|
||||
}
|
||||
if (n + 1 > cap) {
|
||||
if (n == cap) {
|
||||
size_t ncap = cap * 2;
|
||||
R2UnityInterop *noo = realloc (out, ncap * sizeof (R2UnityInterop));
|
||||
if (!noo) {
|
||||
@@ -1250,46 +1307,16 @@ R_API R2UnityInterop *r2unity_enumerate_reverse_pinvokes(R2UnityMetadata *meta,
|
||||
out = noo;
|
||||
cap = ncap;
|
||||
}
|
||||
R2UnityInterop *it = &out[n++];
|
||||
const Il2CppMethodDefinition *m = &methods[mi];
|
||||
it->kind = kind;
|
||||
it->method_index = mi;
|
||||
it->token = m->token;
|
||||
it->flags = m->flags;
|
||||
it->iflags = m->iflags;
|
||||
it->wrapper_va = 0;
|
||||
it->wrapper_index = UINT32_MAX;
|
||||
it->confidence = 100;
|
||||
|
||||
const Il2CppTypeDefinition *td = NULL;
|
||||
if (types && m->declaringType >= 0 && (size_t)m->declaringType < type_count) {
|
||||
td = &types[m->declaringType];
|
||||
}
|
||||
it->name = build_qualified_name (meta, td, m->nameIndex);
|
||||
|
||||
int img_idx = -1;
|
||||
if (type2img && m->declaringType >= 0 && (size_t)m->declaringType < type_count) {
|
||||
img_idx = type2img[m->declaringType];
|
||||
}
|
||||
it->image_index = img_idx;
|
||||
if (img_idx >= 0 && images && (size_t)img_idx < image_count) {
|
||||
it->image_name = (char *)r2unity_get_string (meta, images[img_idx].nameIndex);
|
||||
}
|
||||
} /* close for ri */
|
||||
} /* close for ii */
|
||||
if (n == 0) {
|
||||
interop_fill (&out[n++], &c, mi, kind);
|
||||
}
|
||||
}
|
||||
if (!n) {
|
||||
R_FREE (out);
|
||||
out = NULL;
|
||||
}
|
||||
done:
|
||||
R_FREE (ranges);
|
||||
R_FREE (methods);
|
||||
R_FREE (types);
|
||||
R_FREE (images);
|
||||
R_FREE (type2img);
|
||||
R_FREE (img_tok_start);
|
||||
R_FREE (img_tok_count);
|
||||
R_FREE (tmap);
|
||||
tokindex_free (&tok);
|
||||
interop_ctx_fini (&c);
|
||||
*count = n;
|
||||
return out;
|
||||
}
|
||||
|
||||
+2
-257
@@ -50,258 +50,7 @@ typedef struct {
|
||||
} Il2CppMetadataSection;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sanity;
|
||||
int32_t version;
|
||||
uint32_t stringLiteralOffset;
|
||||
int32_t stringLiteralSize;
|
||||
uint32_t stringLiteralDataOffset;
|
||||
int32_t stringLiteralDataSize;
|
||||
uint32_t stringOffset;
|
||||
int32_t stringSize;
|
||||
uint32_t eventsOffset;
|
||||
int32_t eventsSize;
|
||||
uint32_t propertiesOffset;
|
||||
int32_t propertiesSize;
|
||||
uint32_t methodsOffset;
|
||||
int32_t methodsSize;
|
||||
uint32_t parameterDefaultValuesOffset;
|
||||
int32_t parameterDefaultValuesSize;
|
||||
uint32_t fieldDefaultValuesOffset;
|
||||
int32_t fieldDefaultValuesSize;
|
||||
uint32_t fieldAndParameterDefaultValueDataOffset;
|
||||
int32_t fieldAndParameterDefaultValueDataSize;
|
||||
uint32_t fieldMarshaledSizesOffset;
|
||||
int32_t fieldMarshaledSizesSize;
|
||||
uint32_t parametersOffset;
|
||||
int32_t parametersSize;
|
||||
uint32_t fieldsOffset;
|
||||
int32_t fieldsSize;
|
||||
uint32_t genericParametersOffset;
|
||||
int32_t genericParametersSize;
|
||||
uint32_t genericParameterConstraintsOffset;
|
||||
int32_t genericParameterConstraintsSize;
|
||||
uint32_t genericContainersOffset;
|
||||
int32_t genericContainersSize;
|
||||
uint32_t nestedTypesOffset;
|
||||
int32_t nestedTypesSize;
|
||||
uint32_t interfacesOffset;
|
||||
int32_t interfacesSize;
|
||||
uint32_t vtableMethodsOffset;
|
||||
int32_t vtableMethodsSize;
|
||||
uint32_t interfaceOffsetsOffset;
|
||||
int32_t interfaceOffsetsSize;
|
||||
uint32_t typeDefinitionsOffset;
|
||||
int32_t typeDefinitionsSize;
|
||||
uint32_t imagesOffset;
|
||||
int32_t imagesSize;
|
||||
uint32_t assembliesOffset;
|
||||
int32_t assembliesSize;
|
||||
uint32_t fieldRefsOffset;
|
||||
int32_t fieldRefsSize;
|
||||
uint32_t referencedAssembliesOffset;
|
||||
int32_t referencedAssembliesSize;
|
||||
uint32_t attributesInfoOffset;
|
||||
int32_t attributesInfoSize;
|
||||
uint32_t attributeTypesOffset;
|
||||
int32_t attributeTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterTypesOffset;
|
||||
int32_t unresolvedVirtualCallParameterTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterRangesOffset;
|
||||
int32_t unresolvedVirtualCallParameterRangesSize;
|
||||
uint32_t windowsRuntimeTypeNamesOffset;
|
||||
int32_t windowsRuntimeTypeNamesSize;
|
||||
uint32_t windowsRuntimeStringsOffset;
|
||||
int32_t windowsRuntimeStringsSize;
|
||||
uint32_t exportedTypeDefinitionsOffset;
|
||||
int32_t exportedTypeDefinitionsSize;
|
||||
} Il2CppGlobalMetadataHeader_v24;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sanity;
|
||||
int32_t version;
|
||||
uint32_t stringLiteralOffset;
|
||||
int32_t stringLiteralSize;
|
||||
uint32_t stringLiteralDataOffset;
|
||||
int32_t stringLiteralDataSize;
|
||||
uint32_t stringOffset;
|
||||
int32_t stringSize;
|
||||
uint32_t eventsOffset;
|
||||
int32_t eventsSize;
|
||||
uint32_t propertiesOffset;
|
||||
int32_t propertiesSize;
|
||||
uint32_t methodsOffset;
|
||||
int32_t methodsSize;
|
||||
uint32_t parameterDefaultValuesOffset;
|
||||
int32_t parameterDefaultValuesSize;
|
||||
uint32_t fieldDefaultValuesOffset;
|
||||
int32_t fieldDefaultValuesSize;
|
||||
uint32_t fieldAndParameterDefaultValueDataOffset;
|
||||
int32_t fieldAndParameterDefaultValueDataSize;
|
||||
uint32_t fieldMarshaledSizesOffset;
|
||||
int32_t fieldMarshaledSizesSize;
|
||||
uint32_t parametersOffset;
|
||||
int32_t parametersSize;
|
||||
uint32_t fieldsOffset;
|
||||
int32_t fieldsSize;
|
||||
uint32_t genericParametersOffset;
|
||||
int32_t genericParametersSize;
|
||||
uint32_t genericParameterConstraintsOffset;
|
||||
int32_t genericParameterConstraintsSize;
|
||||
uint32_t genericContainersOffset;
|
||||
int32_t genericContainersSize;
|
||||
uint32_t nestedTypesOffset;
|
||||
int32_t nestedTypesSize;
|
||||
uint32_t interfacesOffset;
|
||||
int32_t interfacesSize;
|
||||
uint32_t vtableMethodsOffset;
|
||||
int32_t vtableMethodsSize;
|
||||
uint32_t interfaceOffsetsOffset;
|
||||
int32_t interfaceOffsetsSize;
|
||||
uint32_t typeDefinitionsOffset;
|
||||
int32_t typeDefinitionsSize;
|
||||
uint32_t imagesOffset;
|
||||
int32_t imagesSize;
|
||||
uint32_t assembliesOffset;
|
||||
int32_t assembliesSize;
|
||||
uint32_t fieldRefsOffset;
|
||||
int32_t fieldRefsSize;
|
||||
uint32_t referencedAssembliesOffset;
|
||||
int32_t referencedAssembliesSize;
|
||||
uint32_t attributesInfoOffset;
|
||||
int32_t attributesInfoSize;
|
||||
uint32_t attributeTypesOffset;
|
||||
int32_t attributeTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterTypesOffset;
|
||||
int32_t unresolvedVirtualCallParameterTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterRangesOffset;
|
||||
int32_t unresolvedVirtualCallParameterRangesSize;
|
||||
uint32_t windowsRuntimeTypeNamesOffset;
|
||||
int32_t windowsRuntimeTypeNamesSize;
|
||||
uint32_t windowsRuntimeStringsOffset;
|
||||
int32_t windowsRuntimeStringsSize;
|
||||
uint32_t exportedTypeDefinitionsOffset;
|
||||
int32_t exportedTypeDefinitionsSize;
|
||||
uint32_t rgctxEntriesOffset;
|
||||
int32_t rgctxEntriesSize;
|
||||
} Il2CppGlobalMetadataHeader_v27;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sanity;
|
||||
int32_t version;
|
||||
uint32_t stringLiteralOffset;
|
||||
int32_t stringLiteralSize;
|
||||
uint32_t stringLiteralDataOffset;
|
||||
int32_t stringLiteralDataSize;
|
||||
uint32_t stringOffset;
|
||||
int32_t stringSize;
|
||||
uint32_t eventsOffset;
|
||||
int32_t eventsSize;
|
||||
uint32_t propertiesOffset;
|
||||
int32_t propertiesSize;
|
||||
uint32_t methodsOffset;
|
||||
int32_t methodsSize;
|
||||
uint32_t parameterDefaultValuesOffset;
|
||||
int32_t parameterDefaultValuesSize;
|
||||
uint32_t fieldDefaultValuesOffset;
|
||||
int32_t fieldDefaultValuesSize;
|
||||
uint32_t fieldAndParameterDefaultValueDataOffset;
|
||||
int32_t fieldAndParameterDefaultValueDataSize;
|
||||
uint32_t fieldMarshaledSizesOffset;
|
||||
int32_t fieldMarshaledSizesSize;
|
||||
uint32_t parametersOffset;
|
||||
int32_t parametersSize;
|
||||
uint32_t fieldsOffset;
|
||||
int32_t fieldsSize;
|
||||
uint32_t genericParametersOffset;
|
||||
int32_t genericParametersSize;
|
||||
uint32_t genericParameterConstraintsOffset;
|
||||
int32_t genericParameterConstraintsSize;
|
||||
uint32_t genericContainersOffset;
|
||||
int32_t genericContainersSize;
|
||||
uint32_t nestedTypesOffset;
|
||||
int32_t nestedTypesSize;
|
||||
uint32_t interfacesOffset;
|
||||
int32_t interfacesSize;
|
||||
uint32_t vtableMethodsOffset;
|
||||
int32_t vtableMethodsSize;
|
||||
uint32_t interfaceOffsetsOffset;
|
||||
int32_t interfaceOffsetsSize;
|
||||
uint32_t typeDefinitionsOffset;
|
||||
int32_t typeDefinitionsSize;
|
||||
uint32_t imagesOffset;
|
||||
int32_t imagesSize;
|
||||
uint32_t assembliesOffset;
|
||||
int32_t assembliesSize;
|
||||
uint32_t fieldRefsOffset;
|
||||
int32_t fieldRefsSize;
|
||||
uint32_t referencedAssembliesOffset;
|
||||
int32_t referencedAssembliesSize;
|
||||
uint32_t attributesInfoOffset;
|
||||
int32_t attributesInfoSize;
|
||||
uint32_t attributeTypesOffset;
|
||||
int32_t attributeTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterTypesOffset;
|
||||
int32_t unresolvedVirtualCallParameterTypesSize;
|
||||
uint32_t unresolvedVirtualCallParameterRangesOffset;
|
||||
int32_t unresolvedVirtualCallParameterRangesSize;
|
||||
uint32_t windowsRuntimeTypeNamesOffset;
|
||||
int32_t windowsRuntimeTypeNamesSize;
|
||||
uint32_t windowsRuntimeStringsOffset;
|
||||
int32_t windowsRuntimeStringsSize;
|
||||
uint32_t exportedTypeDefinitionsOffset;
|
||||
int32_t exportedTypeDefinitionsSize;
|
||||
uint32_t rgctxEntriesOffset;
|
||||
int32_t rgctxEntriesSize;
|
||||
uint32_t rgctxEntriesDataOffset;
|
||||
int32_t rgctxEntriesDataSize;
|
||||
} Il2CppGlobalMetadataHeader_v29;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sanity;
|
||||
int32_t version;
|
||||
Il2CppMetadataSection stringLiterals;
|
||||
Il2CppMetadataSection stringLiteralData;
|
||||
Il2CppMetadataSection strings;
|
||||
Il2CppMetadataSection events;
|
||||
Il2CppMetadataSection properties;
|
||||
Il2CppMetadataSection methods;
|
||||
Il2CppMetadataSection parameterDefaultValues;
|
||||
Il2CppMetadataSection fieldDefaultValues;
|
||||
Il2CppMetadataSection fieldAndParameterDefaultValueData;
|
||||
Il2CppMetadataSection fieldMarshaledSizes;
|
||||
Il2CppMetadataSection parameters;
|
||||
Il2CppMetadataSection fields;
|
||||
Il2CppMetadataSection genericParameters;
|
||||
Il2CppMetadataSection genericParameterConstraints;
|
||||
Il2CppMetadataSection genericContainers;
|
||||
Il2CppMetadataSection nestedTypes;
|
||||
Il2CppMetadataSection interfaces;
|
||||
Il2CppMetadataSection vtableMethods;
|
||||
Il2CppMetadataSection interfaceOffsets;
|
||||
Il2CppMetadataSection typeDefinitions;
|
||||
Il2CppMetadataSection images;
|
||||
Il2CppMetadataSection assemblies;
|
||||
Il2CppMetadataSection fieldRefs;
|
||||
Il2CppMetadataSection referencedAssemblies;
|
||||
Il2CppMetadataSection attributeData;
|
||||
Il2CppMetadataSection attributeDataRanges;
|
||||
Il2CppMetadataSection unresolvedIndirectCallParameterTypes;
|
||||
Il2CppMetadataSection unresolvedIndirectCallParameterRanges;
|
||||
Il2CppMetadataSection windowsRuntimeTypeNames;
|
||||
Il2CppMetadataSection windowsRuntimeStrings;
|
||||
Il2CppMetadataSection exportedTypeDefinitions;
|
||||
} Il2CppGlobalMetadataHeader_v38;
|
||||
|
||||
typedef union {
|
||||
Il2CppGlobalMetadataHeader_v24 v24;
|
||||
Il2CppGlobalMetadataHeader_v27 v27;
|
||||
Il2CppGlobalMetadataHeader_v29 v29;
|
||||
Il2CppGlobalMetadataHeader_v38 v38;
|
||||
} Il2CppGlobalMetadataHeader;
|
||||
|
||||
typedef struct {
|
||||
int32_t version;
|
||||
Il2CppGlobalMetadataHeader header;
|
||||
RBuffer *buf;
|
||||
RBuffer *strings;
|
||||
RBuffer *string_literals;
|
||||
@@ -436,7 +185,8 @@ typedef struct {
|
||||
|
||||
R_API R2UnityMetadata *r2unity_parse_metadata(RBuffer *buf);
|
||||
R_API void r2unity_free_metadata(R2UnityMetadata *meta);
|
||||
R_API const char *r2unity_get_string(R2UnityMetadata *meta, uint32_t index);
|
||||
/* Caller owns the returned string and must free() it. NULL on missing/empty. */
|
||||
R_API char *r2unity_get_string(R2UnityMetadata *meta, uint32_t index);
|
||||
R_API Il2CppStringLiteral *r2unity_get_string_literals(R2UnityMetadata *meta, size_t *count);
|
||||
R_API bool r2unity_read_string_literal(R2UnityMetadata *meta, const Il2CppStringLiteral *lit, ut8 **out_bytes, size_t *out_len);
|
||||
R_API Il2CppTypeDefinition *r2unity_get_type_definitions(R2UnityMetadata *meta, size_t *count);
|
||||
@@ -455,15 +205,10 @@ R_API bool r2unity_metadata_section(R2UnityMetadata *meta, R2UMetadataSectionId
|
||||
R_API ut64 r2unity_metadata_section_entry_size(R2UnityMetadata *meta, R2UMetadataSectionId id);
|
||||
R_API ut64 r2unity_metadata_section_count(R2UnityMetadata *meta, R2UMetadataSectionId id);
|
||||
R_API ut64 r2unity_metadata_header_size(R2UnityMetadata *meta);
|
||||
/* Simplified API: use format-specific finders, or manual read stub. */
|
||||
R_API bool r2unity_read_method_pointers_at(R2UnityMetadata *meta, const char *exe_path, ut64 addr, size_t count, ut64 **out_ptrs);
|
||||
R_API bool r2unity_find_method_pointers_macho(R2UnityMetadata *meta, const char *macho_path, ut64 **out_ptrs);
|
||||
R_API bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *elf_path, ut64 **out_ptrs);
|
||||
R_API bool r2unity_find_method_pointers_pe(R2UnityMetadata *meta, const char *pe_path, ut64 **out_ptrs);
|
||||
|
||||
R_API void r2unity_set_debug(bool v);
|
||||
R_API bool r2unity_is_debug(void);
|
||||
|
||||
/* Companion-file discovery.
|
||||
*
|
||||
* Given any file or root directory inside a Unity IL2CPP deployment (the main
|
||||
|
||||
+2
-3
@@ -1,4 +1,5 @@
|
||||
// Fast Mach-O parser for r2unity
|
||||
#define R_LOG_ORIGIN "r2unity.macho"
|
||||
#include "lib.h"
|
||||
#include <string.h>
|
||||
|
||||
@@ -232,9 +233,7 @@ R_API bool r2unity_find_method_pointers_macho(R2UnityMetadata *meta, const char
|
||||
ut32 min_seen = (pass == 0)? 8: sample / 2;
|
||||
ut32 min_good = (pass == 0)? 8: (sample * 3) / 4;
|
||||
if (macho_probe_table (&mo, arrptr, cnt, text_lo, text_hi, min_seen, min_good, method_count, candidates)) {
|
||||
if (r2unity_is_debug ()) {
|
||||
fprintf (stderr, "[r2unity/macho] pass=%d arrptr=0x%" PFMT64x " cnt=%u\n", pass, arrptr, cnt);
|
||||
}
|
||||
R_LOG_DEBUG ("[macho] pass=%d arrptr=0x%" PFMT64x " cnt=%u", pass, arrptr, cnt);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-3
@@ -2,6 +2,7 @@
|
||||
// PE .dll images are already relocated at link time (preferred image base is
|
||||
// concrete), so no relocation fixup is required — pointers in .data / .rdata
|
||||
// are absolute VAs relative to the ImageBase.
|
||||
#define R_LOG_ORIGIN "r2unity.pe"
|
||||
#include "lib.h"
|
||||
#include <string.h>
|
||||
|
||||
@@ -244,9 +245,7 @@ R_API bool r2unity_find_method_pointers_pe(R2UnityMetadata *meta, const char *pe
|
||||
ut32 min_seen = (pass == 0)? 8: sample / 2;
|
||||
ut32 min_good = (pass == 0)? 8: (sample * 3) / 4;
|
||||
if (pe_probe_table (&pe, arrptr, cnt, ptrsz, text_lo, text_hi, min_seen, min_good, method_count, candidates)) {
|
||||
if (r2unity_is_debug ()) {
|
||||
fprintf (stderr, "[r2unity/pe] pass=%d arrptr=0x%" PFMT64x " cnt=%u\n", pass, arrptr, cnt);
|
||||
}
|
||||
R_LOG_DEBUG ("[pe] pass=%d arrptr=0x%" PFMT64x " cnt=%u", pass, arrptr, cnt);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
+14
-12
@@ -238,8 +238,8 @@ static int emit_sbom(R2UnityMetadata *meta, const char *exe_path, const char *me
|
||||
fprintf (f, " \"components\": [\n");
|
||||
for (size_t i = 0; i < asm_count; i++) {
|
||||
Il2CppAssemblyDefinition *a = &asms[i];
|
||||
char *name = (char *)r2unity_get_string (meta, a->aname.name_idx);
|
||||
char *culture = (char *)r2unity_get_string (meta, a->aname.culture_idx);
|
||||
char *name = r2unity_get_string (meta, a->aname.name_idx);
|
||||
char *culture = r2unity_get_string (meta, a->aname.culture_idx);
|
||||
const char *nm = name? name: "";
|
||||
const char *cl = (culture && *culture)? culture: "neutral";
|
||||
|
||||
@@ -247,7 +247,7 @@ static int emit_sbom(R2UnityMetadata *meta, const char *exe_path, const char *me
|
||||
const char *img = "";
|
||||
char *img_name_owned = NULL;
|
||||
if (imgs && a->image_index >= 0 && (size_t)a->image_index < img_count) {
|
||||
img_name_owned = (char *)r2unity_get_string (meta, imgs[a->image_index].nameIndex);
|
||||
img_name_owned = r2unity_get_string (meta, imgs[a->image_index].nameIndex);
|
||||
if (img_name_owned) {
|
||||
img = img_name_owned;
|
||||
}
|
||||
@@ -317,7 +317,7 @@ static int emit_sbom(R2UnityMetadata *meta, const char *exe_path, const char *me
|
||||
if ((size_t) (a->referenced_start + a->referenced_count) > ref_count) {
|
||||
continue;
|
||||
}
|
||||
char *name = (char *)r2unity_get_string (meta, a->aname.name_idx);
|
||||
char *name = r2unity_get_string (meta, a->aname.name_idx);
|
||||
const char *nm = name? name: "";
|
||||
if (!first_dep) {
|
||||
fprintf (f, ",\n");
|
||||
@@ -333,7 +333,7 @@ static int emit_sbom(R2UnityMetadata *meta, const char *exe_path, const char *me
|
||||
continue;
|
||||
}
|
||||
Il2CppAssemblyDefinition *r = &asms[ridx];
|
||||
char *rname = (char *)r2unity_get_string (meta, r->aname.name_idx);
|
||||
char *rname = r2unity_get_string (meta, r->aname.name_idx);
|
||||
if (!first_ref) {
|
||||
fprintf (f, ",");
|
||||
}
|
||||
@@ -615,12 +615,12 @@ static bool emit_r2_method(R2UnityMetadata *meta,
|
||||
if (addr <= 0x1000) {
|
||||
return false;
|
||||
}
|
||||
char *mn = (char *)r2unity_get_string (meta, m->nameIndex);
|
||||
char *mn = r2unity_get_string (meta, m->nameIndex);
|
||||
if (!mn) {
|
||||
return false;
|
||||
}
|
||||
char *ns = td? (char *)r2unity_get_string (meta, td->namespaceIndex): NULL;
|
||||
char *tn = td? (char *)r2unity_get_string (meta, td->nameIndex): NULL;
|
||||
char *ns = td? r2unity_get_string (meta, td->namespaceIndex): NULL;
|
||||
char *tn = td? r2unity_get_string (meta, td->nameIndex): NULL;
|
||||
char fullname[1024];
|
||||
unsigned pc = (unsigned)m->parameterCount;
|
||||
if (ns && *ns) {
|
||||
@@ -640,7 +640,7 @@ static bool emit_r2_method(R2UnityMetadata *meta,
|
||||
}
|
||||
r_name_filter (fullname, -1);
|
||||
char *attrs = method_attrs (m->flags);
|
||||
char *im = img? (char *)r2unity_get_string (meta, img->nameIndex): NULL;
|
||||
char *im = img? r2unity_get_string (meta, img->nameIndex): NULL;
|
||||
if (im && *im) {
|
||||
printf ("'@0x%" PFMT64x "'f sym.unity.%s.%s\n", addr, im, fullname);
|
||||
printf ("'@0x%" PFMT64x "'CCu Method: [%s]%s%s %s\n",
|
||||
@@ -746,8 +746,9 @@ int main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* configure debug */
|
||||
r2unity_set_debug (debug);
|
||||
if (debug) {
|
||||
r_log_set_level (R_LOG_LEVEL_DEBUG);
|
||||
}
|
||||
R2UnityMetadata *meta = r2unity_parse_metadata (buf);
|
||||
if (!meta) {
|
||||
R_LOG_ERROR ("Failed to parse metadata");
|
||||
@@ -793,7 +794,8 @@ int main(int argc, char *argv[]) {
|
||||
ut64 *method_ptrs = NULL;
|
||||
bool has_ptrs = false;
|
||||
if (gmp_addr) {
|
||||
has_ptrs = r2unity_read_method_pointers_at (meta, exe_path, gmp_addr, gmp_count, &method_ptrs);
|
||||
R_LOG_WARN ("Manual method-pointer table reading (-a/-c) is not implemented");
|
||||
(void)gmp_count;
|
||||
} else if (fast) {
|
||||
has_ptrs = find_method_pointers_fast (meta, exe_path, &method_ptrs);
|
||||
}
|
||||
|
||||
@@ -285,12 +285,12 @@ static bool find_method_pointers(R2UnityMetadata *meta, const char *path, ut64 *
|
||||
static char *build_method_fullname(R2UnityMetadata *meta,
|
||||
const Il2CppMethodDefinition *m,
|
||||
const Il2CppTypeDefinition *td) {
|
||||
char *mn = (char *)r2unity_get_string (meta, m->nameIndex);
|
||||
char *mn = r2unity_get_string (meta, m->nameIndex);
|
||||
if (!mn) {
|
||||
return NULL;
|
||||
}
|
||||
char *ns = td? (char *)r2unity_get_string (meta, td->namespaceIndex): NULL;
|
||||
char *tn = td? (char *)r2unity_get_string (meta, td->nameIndex): NULL;
|
||||
char *ns = td? r2unity_get_string (meta, td->namespaceIndex): NULL;
|
||||
char *tn = td? r2unity_get_string (meta, td->nameIndex): NULL;
|
||||
unsigned pc = (unsigned)m->parameterCount;
|
||||
char *out = NULL;
|
||||
if (ns && *ns) {
|
||||
@@ -381,7 +381,7 @@ static int cmd_symbols(RCore *core, char mode) {
|
||||
if (!fullname) {
|
||||
continue;
|
||||
}
|
||||
char *imgname = img? (char *)r2unity_get_string (meta, img->nameIndex): NULL;
|
||||
char *imgname = img? r2unity_get_string (meta, img->nameIndex): NULL;
|
||||
char flag_buf[1024];
|
||||
if (imgname && *imgname) {
|
||||
snprintf (flag_buf, sizeof (flag_buf), "sym.unity.%s.%s", imgname, fullname);
|
||||
@@ -716,14 +716,14 @@ static int cmd_sbom(RCore *core) {
|
||||
pj_ka (pj, "components");
|
||||
for (size_t i = 0; i < asm_count; i++) {
|
||||
Il2CppAssemblyDefinition *a = &asms[i];
|
||||
char *name = (char *)r2unity_get_string (meta, a->aname.name_idx);
|
||||
char *culture = (char *)r2unity_get_string (meta, a->aname.culture_idx);
|
||||
char *name = r2unity_get_string (meta, a->aname.name_idx);
|
||||
char *culture = r2unity_get_string (meta, a->aname.culture_idx);
|
||||
const char *nm = name? name: "";
|
||||
const char *cl = (culture && *culture)? culture: "neutral";
|
||||
char *img_name_owned = NULL;
|
||||
const char *img = "";
|
||||
if (imgs && a->image_index >= 0 && (size_t)a->image_index < img_count) {
|
||||
img_name_owned = (char *)r2unity_get_string (meta, imgs[a->image_index].nameIndex);
|
||||
img_name_owned = r2unity_get_string (meta, imgs[a->image_index].nameIndex);
|
||||
if (img_name_owned) {
|
||||
img = img_name_owned;
|
||||
}
|
||||
@@ -767,7 +767,7 @@ static int cmd_sbom(RCore *core) {
|
||||
if ((size_t) (a->referenced_start + a->referenced_count) > ref_count) {
|
||||
continue;
|
||||
}
|
||||
char *name = (char *)r2unity_get_string (meta, a->aname.name_idx);
|
||||
char *name = r2unity_get_string (meta, a->aname.name_idx);
|
||||
const char *nm = name? name: "";
|
||||
char ver[64];
|
||||
snprintf (ver, sizeof (ver), "%d.%d.%d.%d", a->aname.major, a->aname.minor, a->aname.build, a->aname.revision);
|
||||
@@ -782,7 +782,7 @@ static int cmd_sbom(RCore *core) {
|
||||
continue;
|
||||
}
|
||||
Il2CppAssemblyDefinition *r = &asms[ridx];
|
||||
char *rname = (char *)r2unity_get_string (meta, r->aname.name_idx);
|
||||
char *rname = r2unity_get_string (meta, r->aname.name_idx);
|
||||
char rver[64];
|
||||
snprintf (rver, sizeof (rver), "%d.%d.%d.%d", r->aname.major, r->aname.minor, r->aname.build, r->aname.revision);
|
||||
char rref[512];
|
||||
|
||||
Reference in new issue
Block a user