diff --git a/src/lib/elf.c b/src/lib/elf.c index 10641e1..3bb618c 100644 --- a/src/lib/elf.c +++ b/src/lib/elf.c @@ -1,20 +1,6 @@ // Fast ELF parser for r2unity #include "lib.h" #include -#include -#include -#include - -static inline ut32 RD_LE32 (const ut8 *p) { - return ((ut32)p[0]) | ((ut32)p[1] << 8) | ((ut32)p[2] << 16) | ((ut32)p[3] << 24); -} -static inline ut64 RD_LE64 (const ut8 *p) { - return ((ut64)p[0]) | ((ut64)p[1] << 8) | ((ut64)p[2] << 16) | ((ut64)p[3] << 24) | - ((ut64)p[4] << 32) | ((ut64)p[5] << 40) | ((ut64)p[6] << 48) | ((ut64)p[7] << 56); -} -static inline ut16 RD_LE16 (const ut8 *p) { - return (ut16)((ut16)p[0] | ((ut16)p[1] << 8)); -} typedef struct { ut64 vaddr; @@ -36,54 +22,48 @@ typedef struct { static bool elf_load (const char *path, ElfImg *e) { memset (e, 0, sizeof (*e)); - int fd = open (path, O_RDONLY); - if (fd < 0) return false; - struct stat st; - if (fstat (fd, &st) != 0 || st.st_size <= 0) { close (fd); return false; } - e->filesize = (ut64) st.st_size; - e->file = R_NEWS (ut8, e->filesize); - if (!e->file) { close (fd); return false; } - ssize_t rd = read (fd, e->file, (size_t) e->filesize); - close (fd); - if (rd < 0 || (ut64) rd != e->filesize) { R_FREE (e->file); return false; } + size_t sz = 0; + e->file = (ut8 *) r_file_slurp (path, &sz); + if (!e->file || sz == 0) { R_FREE (e->file); return false; } + e->filesize = (ut64) sz; const ut8 *p = e->file; if (!(p[0] == 0x7f && p[1] == 'E' && p[2] == 'L' && p[3] == 'F')) { R_FREE (e->file); return false; } e->is64 = (p[4] == 2); e->le = (p[5] == 1); if (!e->le) { R_FREE (e->file); return false; } if (e->is64) { - ut64 phoff = RD_LE64 (p + 0x20); - ut16 phentsize = RD_LE16 (p + 0x36); - ut16 phnum = RD_LE16 (p + 0x38); + ut64 phoff = r_read_le64 (p + 0x20); + ut16 phentsize = r_read_le16 (p + 0x36); + ut16 phnum = r_read_le16 (p + 0x38); for (ut16 i = 0; i < phnum && e->nsegs < (int)(sizeof (e->segs)/sizeof (e->segs[0])); i++) { ut64 off = phoff + (ut64) i * phentsize; if (off + 56 > e->filesize) break; const ut8 *ph = p + off; - ut32 p_type = RD_LE32 (ph + 0); - ut32 p_flags = RD_LE32 (ph + 4); - ut64 p_offset = RD_LE64 (ph + 8); - ut64 p_vaddr = RD_LE64 (ph + 16); - ut64 p_filesz = RD_LE64 (ph + 32); - ut64 p_memsz = RD_LE64 (ph + 40); + ut32 p_type = r_read_le32 (ph + 0); + ut32 p_flags = r_read_le32 (ph + 4); + ut64 p_offset = r_read_le64 (ph + 8); + ut64 p_vaddr = r_read_le64 (ph + 16); + ut64 p_filesz = r_read_le64 (ph + 32); + ut64 p_memsz = r_read_le64 (ph + 40); if (p_type == 1 || p_type == 2) { ElfSeg *s = &e->segs[e->nsegs++]; s->vaddr = p_vaddr; s->memsz = p_memsz; s->offset = p_offset; s->filesz = p_filesz; s->flags = p_flags; s->p_type = p_type; } } } else { - ut32 phoff = RD_LE32 (p + 0x1C); - ut16 phentsize = RD_LE16 (p + 0x2A); - ut16 phnum = RD_LE16 (p + 0x2C); + ut32 phoff = r_read_le32 (p + 0x1C); + ut16 phentsize = r_read_le16 (p + 0x2A); + ut16 phnum = r_read_le16 (p + 0x2C); for (ut16 i = 0; i < phnum && e->nsegs < (int)(sizeof (e->segs)/sizeof (e->segs[0])); i++) { ut64 off = (ut64) phoff + (ut64) i * phentsize; if (off + 32 > e->filesize) break; const ut8 *ph = p + off; - ut32 p_type = RD_LE32 (ph + 0); - ut32 p_offset = RD_LE32 (ph + 4); - ut32 p_vaddr = RD_LE32 (ph + 8); - ut32 p_filesz = RD_LE32 (ph + 16); - ut32 p_memsz = RD_LE32 (ph + 20); - ut32 p_flags = RD_LE32 (ph + 24); + ut32 p_type = r_read_le32 (ph + 0); + ut32 p_offset = r_read_le32 (ph + 4); + ut32 p_vaddr = r_read_le32 (ph + 8); + ut32 p_filesz = r_read_le32 (ph + 16); + ut32 p_memsz = r_read_le32 (ph + 20); + ut32 p_flags = r_read_le32 (ph + 24); if (p_type == 1 || p_type == 2) { ElfSeg *s = &e->segs[e->nsegs++]; s->vaddr = p_vaddr; s->memsz = p_memsz; s->offset = p_offset; s->filesz = p_filesz; s->flags = p_flags; s->p_type = p_type; @@ -139,8 +119,8 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * if (dyn_off && dyn_sz) { const ut8 *d = e.file + dyn_off; for (ut64 off = 0; off + (e.is64? 16: 8) <= dyn_sz; off += (e.is64? 16: 8)) { - ut64 tag = e.is64 ? RD_LE64 (d + off) : (ut64) RD_LE32 (d + off); - ut64 val = e.is64 ? RD_LE64 (d + off + 8) : (ut64) RD_LE32 (d + off + 4); + ut64 tag = e.is64 ? r_read_le64 (d + off) : (ut64) r_read_le32 (d + off); + ut64 val = e.is64 ? r_read_le64 (d + off + 8) : (ut64) r_read_le32 (d + off + 4); if (tag == 0) break; if (tag == 7) rela_off = val; else if (tag == 8) rela_sz = val; else if (tag == 9) rela_ent = val; else if (tag == 17) rel_off = val; else if (tag == 18) rel_sz = val; else if (tag == 19) rel_ent = val; @@ -150,9 +130,9 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * 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); if (!rp) break; - ut64 r_offset = e.is64 ? RD_LE64 (rp + 0) : (ut64) RD_LE32 (rp + 0); - ut64 r_info = e.is64 ? RD_LE64 (rp + 8) : (ut64) RD_LE32 (rp + 4); - ut64 r_addend = e.is64 ? RD_LE64 (rp + 16) : (ut64) RD_LE32 (rp + 8); + 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); bool is_relative = (type == 8) || (type == 23) || (type == 1027); if (!is_relative) continue; @@ -166,13 +146,13 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * if (rel_off && rel_sz && rel_ent) { for (ut64 i = 0; i + rel_ent <= rel_sz; i += rel_ent) { const ut8 *rp = elf_vm_to_ptr (&e, rel_off + i); if (!rp) break; - ut64 r_offset = e.is64 ? RD_LE64 (rp + 0) : (ut64) RD_LE32 (rp + 0); - ut64 r_info = e.is64 ? RD_LE64 (rp + 8) : (ut64) RD_LE32 (rp + 4); + 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); 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; - ut64 add = e.is64 ? RD_LE64 (loc) : (ut64) RD_LE32 (loc); + 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); } @@ -183,17 +163,17 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * ut64 curr = 0; for (ut64 i = 0; i + relr_ent <= relr_sz; i += relr_ent) { const ut8 *rp = elf_vm_to_ptr (&e, relr_off + i); if (!rp) break; - ut64 R = RD_LE64 (rp); + ut64 R = r_read_le64 (rp); if ((R & 1ULL) == 0) { ut64 addr = R; ut8 *loc = (ut8 *) elf_vm_to_ptr (&e, addr); - if (loc) { ut64 add = RD_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 (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); } 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 = RD_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); + 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); } curr += 8ULL * 63ULL; } @@ -212,9 +192,9 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * const ut8 *buf = e.file + s->offset; ut64 sz = s->filesz; for (ut64 off = 0; off + (ut64)(8 + ptrsz) * 3 <= sz; off += 4) { - ut32 cnt1 = RD_LE32 (buf + off + 0); - ut64 p1 = (ptrsz == 8)? RD_LE64 (buf + off + 8): (ut64) RD_LE32 (buf + off + 4); - ut32 cnt2 = RD_LE32 (buf + off + (ut64)(8 + ptrsz)); + ut32 cnt1 = r_read_le32 (buf + off + 0); + ut64 p1 = (ptrsz == 8)? r_read_le64 (buf + off + 8): (ut64) r_read_le32 (buf + off + 4); + ut32 cnt2 = r_read_le32 (buf + off + (ut64)(8 + ptrsz)); if (cnt1 < 32 || cnt2 < 16) continue; // Sample method array ut32 good = 0, seen = 0; @@ -223,7 +203,7 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * const ut8 *pp = elf_vm_to_ptr (&e, p1 + (ut64)k * (ut64)ptrsz); if (!pp && base_vaddr != UT64_MAX) { pp = elf_vm_to_ptr (&e, base_vaddr + p1 + (ut64)k * (ut64)ptrsz); } if (!pp) break; - ut64 val = (ptrsz == 8) ? RD_LE64 (pp) : (ut64) RD_LE32 (pp); + ut64 val = (ptrsz == 8) ? r_read_le64 (pp) : (ut64) r_read_le32 (pp); if (val) seen++; if ((val >= text_lo && val < text_hi) || (val && base_vaddr != UT64_MAX && (val + base_vaddr) >= text_lo && (val + base_vaddr) < text_hi)) good++; } @@ -236,7 +216,7 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * const ut8 *pp = elf_vm_to_ptr (&e, p1 + (ut64)m * (ut64)ptrsz); if (!pp && base_vaddr != UT64_MAX) { pp = elf_vm_to_ptr (&e, base_vaddr + p1 + (ut64)m * (ut64)ptrsz); } if (!pp) break; - ut64 val = (ptrsz == 8) ? RD_LE64 (pp) : (ut64) RD_LE32 (pp); + ut64 val = (ptrsz == 8) ? r_read_le64 (pp) : (ut64) r_read_le32 (pp); ut64 abs = (val >= text_lo && val < text_hi)? val: ((val && base_vaddr != UT64_MAX)? val + base_vaddr: val); if (abs >= text_lo && abs < text_hi) { candidates[m] = abs; in_text++; } } @@ -252,19 +232,19 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * const ut8 *buf = e.file + s->offset; ut64 sz = s->filesz; for (ut64 off = 0; off + (ut64)(8 + ptrsz) <= sz; off += 4) { - ut32 cnt32 = RD_LE32 (buf + off); + ut32 cnt32 = r_read_le32 (buf + off); if (cnt32 == 0) continue; /* stricter thresholds to avoid wrong tables */ if (cnt32 < 64) continue; if (expected && (cnt32 > expected * 2 || cnt32 < expected / 2)) continue; - ut64 arrptr = (ptrsz == 8) ? RD_LE64 (buf + off + 8) : (ut64) RD_LE32 (buf + off + 4); + ut64 arrptr = (ptrsz == 8) ? r_read_le64 (buf + off + 8) : (ut64) r_read_le32 (buf + off + 4); ut32 good = 0, seen = 0; ut32 sample = R_MIN ((ut32)128, cnt32); for (ut32 k = 0; k < sample; k++) { const ut8 *pp = elf_vm_to_ptr (&e, arrptr + (ut64)k * (ut64)ptrsz); if (!pp && base_vaddr != UT64_MAX) { pp = elf_vm_to_ptr (&e, base_vaddr + arrptr + (ut64)k * (ut64)ptrsz); } if (!pp) break; - ut64 val = (ptrsz == 8) ? RD_LE64 (pp) : (ut64) RD_LE32 (pp); + ut64 val = (ptrsz == 8) ? r_read_le64 (pp) : (ut64) r_read_le32 (pp); if (val) seen++; if ((val >= text_lo && val < text_hi) || (val && base_vaddr != UT64_MAX && (val + base_vaddr) >= text_lo && (val + base_vaddr) < text_hi)) good++; } @@ -277,7 +257,7 @@ R_API bool r2unity_find_method_pointers_elf (R2UnityMetadata *meta, const char * const ut8 *pp = elf_vm_to_ptr (&e, arrptr + (ut64)m * (ut64)ptrsz); if (!pp && base_vaddr != UT64_MAX) { pp = elf_vm_to_ptr (&e, base_vaddr + arrptr + (ut64)m * (ut64)ptrsz); } if (!pp) break; - ut64 val = (ptrsz == 8) ? RD_LE64 (pp) : (ut64) RD_LE32 (pp); + ut64 val = (ptrsz == 8) ? r_read_le64 (pp) : (ut64) r_read_le32 (pp); ut64 abs = (val >= text_lo && val < text_hi)? val: ((val && base_vaddr != UT64_MAX)? val + base_vaddr: val); if (abs >= text_lo && abs < text_hi) { candidates[m] = abs; in_text++; } } diff --git a/src/lib/lib.c b/src/lib/lib.c index 65f6e1e..89ac229 100644 --- a/src/lib/lib.c +++ b/src/lib/lib.c @@ -1,18 +1,5 @@ #include "lib.h" #include -#include -#undef RD_LE32 -static inline ut32 RD_LE32 (const ut8 *p) { - return ((ut32)p[0]) | ((ut32)p[1] << 8) | ((ut32)p[2] << 16) | ((ut32)p[3] << 24); -} -static inline ut16 RD_LE16 (const ut8 *p) { - return (ut16)((ut16)p[0] | ((ut16)p[1] << 8)); -} -#include -#include -#include -#include -#include static bool g_debug = false; @@ -39,12 +26,12 @@ R_API R2UnityMetadata *r2unity_parse_metadata (RBuffer *buf) { R_FREE (meta); return NULL; } - uint32_t sanity = RD_LE32 (preamble); + uint32_t sanity = r_read_le32 (preamble); if (sanity != IL2CPP_MAGIC) { R_FREE (meta); return NULL; } - int32_t version = (int32_t) RD_LE32 (preamble + 4); + int32_t version = (int32_t) r_read_le32 (preamble + 4); meta->version = version; size_t header_size = 0; if (version < 24 || version > 31) { @@ -66,11 +53,11 @@ R_API R2UnityMetadata *r2unity_parse_metadata (RBuffer *buf) { } // Normalize header from on-disk little-endian to native byte order. // Every field in the Il2Cpp header structs is a 32-bit word, so a single - // in-place RD_LE32 sweep handles all versions and is a no-op on LE hosts. + // in-place r_read_le32 sweep handles all versions and is a no-op on LE hosts. 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] = RD_LE32 ((const ut8 *) &hdr_words[i]); + hdr_words[i] = r_read_le32 (&hdr_words[i]); } meta->buf = buf; /* Normalize header fields depending on version to simplify later access */ @@ -181,32 +168,32 @@ R_API Il2CppTypeDefinition *r2unity_get_type_definitions (R2UnityMetadata *meta, } for (size_t i = 0; i < *count; i++) { const ut8 *p = buf + i * entry; - types[i].nameIndex = RD_LE32 (p + 0); - types[i].namespaceIndex = RD_LE32 (p + 4); - types[i].byvalTypeIndex = (int32_t) RD_LE32 (p + 8); - types[i].declaringTypeIndex = (int32_t) RD_LE32 (p + 12); - types[i].parentIndex = (int32_t) RD_LE32 (p + 16); - types[i].elementTypeIndex = (int32_t) RD_LE32 (p + 20); - types[i].genericContainerIndex = (int32_t) RD_LE32 (p + 24); - types[i].flags = RD_LE32 (p + 28); - types[i].fieldStart = (int32_t) RD_LE32 (p + 32); - types[i].methodStart = (int32_t) RD_LE32 (p + 36); - types[i].eventStart = (int32_t) RD_LE32 (p + 40); - types[i].propertyStart = (int32_t) RD_LE32 (p + 44); - types[i].nestedTypesStart = (int32_t) RD_LE32 (p + 48); - types[i].interfacesStart = (int32_t) RD_LE32 (p + 52); - types[i].vtableStart = (int32_t) RD_LE32 (p + 56); - types[i].interfaceOffsetsStart = (int32_t) RD_LE32 (p + 60); - types[i].method_count = RD_LE16 (p + 64); - types[i].property_count = RD_LE16 (p + 66); - types[i].field_count = RD_LE16 (p + 68); - types[i].event_count = RD_LE16 (p + 70); - types[i].nested_type_count = RD_LE16 (p + 72); - types[i].vtable_count = RD_LE16 (p + 74); - types[i].interfaces_count = RD_LE16 (p + 76); - types[i].interface_offsets_count = RD_LE16 (p + 78); - types[i].bitfield = RD_LE32 (p + 80); - types[i].token = RD_LE32 (p + 84); + types[i].nameIndex = r_read_le32 (p + 0); + types[i].namespaceIndex = r_read_le32 (p + 4); + types[i].byvalTypeIndex = (int32_t) r_read_le32 (p + 8); + types[i].declaringTypeIndex = (int32_t) r_read_le32 (p + 12); + types[i].parentIndex = (int32_t) r_read_le32 (p + 16); + types[i].elementTypeIndex = (int32_t) r_read_le32 (p + 20); + types[i].genericContainerIndex = (int32_t) r_read_le32 (p + 24); + types[i].flags = r_read_le32 (p + 28); + types[i].fieldStart = (int32_t) r_read_le32 (p + 32); + types[i].methodStart = (int32_t) r_read_le32 (p + 36); + types[i].eventStart = (int32_t) r_read_le32 (p + 40); + types[i].propertyStart = (int32_t) r_read_le32 (p + 44); + types[i].nestedTypesStart = (int32_t) r_read_le32 (p + 48); + types[i].interfacesStart = (int32_t) r_read_le32 (p + 52); + types[i].vtableStart = (int32_t) r_read_le32 (p + 56); + types[i].interfaceOffsetsStart = (int32_t) r_read_le32 (p + 60); + types[i].method_count = r_read_le16 (p + 64); + types[i].property_count = r_read_le16 (p + 66); + types[i].field_count = r_read_le16 (p + 68); + types[i].event_count = r_read_le16 (p + 70); + types[i].nested_type_count = r_read_le16 (p + 72); + types[i].vtable_count = r_read_le16 (p + 74); + types[i].interfaces_count = r_read_le16 (p + 76); + types[i].interface_offsets_count = r_read_le16 (p + 78); + types[i].bitfield = r_read_le32 (p + 80); + types[i].token = r_read_le32 (p + 84); } R_FREE (buf); return types; @@ -239,16 +226,16 @@ R_API Il2CppMethodDefinition *r2unity_get_method_definitions (R2UnityMetadata *m } for (size_t i = 0; i < *count; i++) { const ut8 *p = buf + i * entry; - methods[i].nameIndex = RD_LE32 (p + 0); - methods[i].declaringType = (int32_t) RD_LE32 (p + 4); - methods[i].returnType = (int32_t) RD_LE32 (p + 8); - methods[i].parameterStart = (int32_t) RD_LE32 (p + 12); - methods[i].genericContainerIndex = (int32_t) RD_LE32 (p + 16); - methods[i].token = RD_LE32 (p + 20); - methods[i].flags = RD_LE16 (p + 24); - methods[i].iflags = RD_LE16 (p + 26); - methods[i].slot = RD_LE16 (p + 28); - methods[i].parameterCount = RD_LE16 (p + 30); + methods[i].nameIndex = r_read_le32 (p + 0); + methods[i].declaringType = (int32_t) r_read_le32 (p + 4); + methods[i].returnType = (int32_t) r_read_le32 (p + 8); + methods[i].parameterStart = (int32_t) r_read_le32 (p + 12); + methods[i].genericContainerIndex = (int32_t) r_read_le32 (p + 16); + methods[i].token = r_read_le32 (p + 20); + methods[i].flags = r_read_le16 (p + 24); + methods[i].iflags = r_read_le16 (p + 26); + methods[i].slot = r_read_le16 (p + 28); + methods[i].parameterCount = r_read_le16 (p + 30); } R_FREE (buf); return methods; @@ -295,16 +282,16 @@ R_API Il2CppImageDefinition *r2unity_get_images (R2UnityMetadata *meta, size_t * } for (size_t i = 0; i < *count; i++) { const ut8 *p = buf2 + i * entry; - imgs[i].nameIndex = RD_LE32 (p + 0); - imgs[i].assemblyIndex = (int32_t) RD_LE32 (p + 4); - imgs[i].typeStart = (int32_t) RD_LE32 (p + 8); - imgs[i].typeCount = RD_LE32 (p + 12); - imgs[i].exportedTypeStart = (int32_t) RD_LE32 (p + 16); - imgs[i].exportedTypeCount = RD_LE32 (p + 20); - imgs[i].entryPointIndex = (int32_t) RD_LE32 (p + 24); - imgs[i].token = RD_LE32 (p + 28); - imgs[i].customAttributeStart = (int32_t) RD_LE32 (p + 32); - imgs[i].customAttributeCount = RD_LE32 (p + 36); + imgs[i].nameIndex = r_read_le32 (p + 0); + imgs[i].assemblyIndex = (int32_t) r_read_le32 (p + 4); + imgs[i].typeStart = (int32_t) r_read_le32 (p + 8); + imgs[i].typeCount = r_read_le32 (p + 12); + imgs[i].exportedTypeStart = (int32_t) r_read_le32 (p + 16); + imgs[i].exportedTypeCount = r_read_le32 (p + 20); + imgs[i].entryPointIndex = (int32_t) r_read_le32 (p + 24); + imgs[i].token = r_read_le32 (p + 28); + imgs[i].customAttributeStart = (int32_t) r_read_le32 (p + 32); + imgs[i].customAttributeCount = r_read_le32 (p + 36); } R_FREE (buf2); return imgs; diff --git a/src/lib/macho.c b/src/lib/macho.c index 10566a0..f5dcec5 100644 --- a/src/lib/macho.c +++ b/src/lib/macho.c @@ -1,20 +1,6 @@ // Fast Mach-O parser for r2unity #include "lib.h" #include -#include -#include -#include - -static inline ut32 RD_LE32 (const ut8 *p) { - return ((ut32)p[0]) | ((ut32)p[1] << 8) | ((ut32)p[2] << 16) | ((ut32)p[3] << 24); -} -static inline ut32 RD_BE32 (const ut8 *p) { - return ((ut32)p[3]) | ((ut32)p[2] << 8) | ((ut32)p[1] << 16) | ((ut32)p[0] << 24); -} -static inline ut64 RD_LE64 (const ut8 *p) { - return ((ut64)p[0]) | ((ut64)p[1] << 8) | ((ut64)p[2] << 16) | ((ut64)p[3] << 24) | - ((ut64)p[4] << 32) | ((ut64)p[5] << 40) | ((ut64)p[6] << 48) | ((ut64)p[7] << 56); -} typedef struct { char segname[16]; @@ -38,62 +24,50 @@ typedef struct { static bool macho_load (const char *path, MachO *mo) { memset (mo, 0, sizeof (*mo)); - int fd = open (path, O_RDONLY); - if (fd < 0) return false; - struct stat st; - if (fstat (fd, &st) != 0 || st.st_size <= 0) { - close (fd); - return false; - } - mo->filesize = (ut64) st.st_size; - mo->file = R_NEWS (ut8, mo->filesize); - if (!mo->file) { - close (fd); - return false; - } - ssize_t rd = read (fd, mo->file, (size_t) mo->filesize); - close (fd); - if (rd < 0 || (ut64) rd != mo->filesize) { + size_t sz = 0; + mo->file = (ut8 *) r_file_slurp (path, &sz); + if (!mo->file || sz == 0) { R_FREE (mo->file); return false; } - ut32 magic = RD_BE32 (mo->file); + mo->filesize = (ut64) sz; + ut32 magic = r_read_be32 (mo->file); ut64 off = 0; if (magic == 0xcafebabe) { - ut32 nfat = RD_BE32 (mo->file + 4); + ut32 nfat = r_read_be32 (mo->file + 4); ut32 best = 0; for (ut32 i = 0; i < nfat; i++) { const ut8 *fa = mo->file + 8 + i * 20; - ut32 cputype = RD_BE32 (fa + 0); + ut32 cputype = r_read_be32 (fa + 0); if (cputype == 0x0100000c) { best = i; break; } } const ut8 *fa = mo->file + 8 + best * 20; - off = RD_BE32 (fa + 8); + off = r_read_be32 (fa + 8); } mo->base = off; const ut8 *p = mo->file + off; - ut32 mh_magic = RD_LE32 (p); + ut32 mh_magic = r_read_le32 (p); if (mh_magic != 0xFEEDFACF) { R_FREE (mo->file); return false; } - ut32 ncmds = RD_LE32 (p + 0x10); + ut32 ncmds = r_read_le32 (p + 0x10); mo->ncmds = ncmds; mo->cmd_off = off + 0x20; ut64 co = mo->cmd_off; for (ut32 i = 0; i < ncmds && (co + 8 <= mo->filesize); i++) { - ut32 cmd = RD_LE32 (mo->file + co); - ut32 cmdsize = RD_LE32 (mo->file + co + 4); + ut32 cmd = r_read_le32 (mo->file + co); + ut32 cmdsize = r_read_le32 (mo->file + co + 4); if (cmd == 0x19 && cmdsize >= 72) { if (mo->nsegs < (int)(sizeof (mo->segs)/sizeof (mo->segs[0]))) { MachSeg *s = &mo->segs[mo->nsegs++]; const ut8 *sp = mo->file + co + 8; memcpy (s->segname, sp, 16); - s->vmaddr = RD_LE64 (sp + 16); - s->vmsize = RD_LE64 (sp + 24); - s->fileoff = RD_LE64 (sp + 32); - s->filesize = RD_LE64 (sp + 40); - s->maxprot = RD_LE32 (sp + 48); + s->vmaddr = r_read_le64 (sp + 16); + s->vmsize = r_read_le64 (sp + 24); + s->fileoff = r_read_le64 (sp + 32); + s->filesize = r_read_le64 (sp + 40); + s->maxprot = r_read_le32 (sp + 48); if (!mo->vm_base || s->vmaddr < mo->vm_base) { mo->vm_base = s->vmaddr; } @@ -176,8 +150,8 @@ R_API bool r2unity_find_method_pointers_macho (R2UnityMetadata *meta, const char const ut8 *buf = mo.file + mo.base + s->fileoff; ut64 sz = s->filesize; for (ut64 off = 0; off + 16 <= sz; off += 4) { - ut32 cnt1 = RD_LE32 (buf + off); - ut64 p1 = RD_LE64 (buf + off + 8); + ut32 cnt1 = r_read_le32 (buf + off); + ut64 p1 = r_read_le64 (buf + off + 8); if (cnt1 < 32) continue; ut32 good = 0, seen = 0; ut32 sample = R_MIN ((ut32)128, cnt1); @@ -185,7 +159,7 @@ R_API bool r2unity_find_method_pointers_macho (R2UnityMetadata *meta, const char const ut8 *p = macho_vm_to_ptr (&mo, p1 + (ut64)k * 8); if (!p && mo.vm_base) { p = macho_vm_to_ptr (&mo, mo.vm_base + p1 + (ut64)k * 8); } if (!p) break; - ut64 val = RD_LE64 (p); + ut64 val = r_read_le64 (p); if (val) seen++; if (val < text_lo && mo.vm_base) val += mo.vm_base; if (val >= text_lo && val < text_hi) good++; @@ -197,7 +171,7 @@ R_API bool r2unity_find_method_pointers_macho (R2UnityMetadata *meta, const char const ut8 *p = macho_vm_to_ptr (&mo, p1 + (ut64)m * 8); if (!p && mo.vm_base) { p = macho_vm_to_ptr (&mo, mo.vm_base + p1 + (ut64)m * 8); } if (!p) break; - ut64 val = RD_LE64 (p); + ut64 val = r_read_le64 (p); if (val < text_lo && mo.vm_base) val += mo.vm_base; if (val >= text_lo && val < text_hi) candidates[m] = val; } @@ -213,18 +187,18 @@ R_API bool r2unity_find_method_pointers_macho (R2UnityMetadata *meta, const char const ut8 *buf = mo.file + mo.base + s->fileoff; ut64 sz = s->filesize; for (ut64 off = 0; off + 16 <= sz; off += 4) { - ut32 cnt32 = RD_LE32 (buf + off); + ut32 cnt32 = r_read_le32 (buf + off); /* stricter thresholds to avoid wrong tables */ if (cnt32 < 64) continue; if (expected && (cnt32 > expected * 2 || cnt32 < expected / 2)) continue; - ut64 arrptr = RD_LE64 (buf + off + 8); + ut64 arrptr = r_read_le64 (buf + off + 8); ut32 good = 0, seen = 0; ut32 sample = R_MIN ((ut32)128, cnt32); for (ut32 k = 0; k < sample; k++) { const ut8 *p = macho_vm_to_ptr (&mo, arrptr + (ut64)k * (ut64)ptrsz); if (!p && mo.vm_base) { p = macho_vm_to_ptr (&mo, mo.vm_base + arrptr + (ut64)k * (ut64)ptrsz); } if (!p) break; - ut64 val = RD_LE64 (p); + ut64 val = r_read_le64 (p); // Do not treat 0 as RVA; only add base when non-zero if (val && val < text_lo && mo.vm_base && (val + mo.vm_base) >= text_lo && (val + mo.vm_base) < text_hi) { val += mo.vm_base; @@ -239,7 +213,7 @@ R_API bool r2unity_find_method_pointers_macho (R2UnityMetadata *meta, const char const ut8 *p = macho_vm_to_ptr (&mo, arrptr + (ut64)m * (ut64)ptrsz); if (!p && mo.vm_base) { p = macho_vm_to_ptr (&mo, mo.vm_base + arrptr + (ut64)m * (ut64)ptrsz); } if (!p) break; - ut64 val = RD_LE64 (p); + ut64 val = r_read_le64 (p); if (val && val < text_lo && mo.vm_base && (val + mo.vm_base) >= text_lo && (val + mo.vm_base) < text_hi) { val += mo.vm_base; }