Skip to content

Commit fc134a5

Browse files
authored
Fix #25707 - slow iOS kernelcache loading by bulk-reading into memory ##bin
r_cf_value_dict_parse was reading the XML prelink info one byte at a time through the full I/O stack (seek+read syscalls per byte for a 3MB buffer). Bulk-read the entire region into memory first. find_class_registrations was reading 8 bytes per instruction through the I/O stack while decoding .init. functions. Use load_kext_text_blob to read the entire kext text section once, matching the pattern already used by find_class_vtables. Reduces load time for non-MH_FILESET kernelcaches from ~3min to ~6sec.
1 parent 6cb1ed3 commit fc134a5

2 files changed

Lines changed: 29 additions & 11 deletions

File tree

libr/bin/format/xnu/r_cf_dict.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ RCFValueDict *r_cf_value_dict_parse (RBuffer *file_buf, ut64 offset, ut64 size,
7676
int i;
7777
char *content = NULL;
7878

79+
ut8 *buf = malloc (size);
80+
if (!buf) {
81+
return NULL;
82+
}
83+
int buf_len = r_buf_read_at (file_buf, offset, buf, size);
84+
if (buf_len < 1) {
85+
free (buf);
86+
return NULL;
87+
}
88+
7989
RXml *x = r_xml_new (4096);
8090

8191
RList *stack = r_list_newf ((RListFree)&r_cf_parse_state_free);
@@ -92,9 +102,8 @@ RCFValueDict *r_cf_value_dict_parse (RBuffer *file_buf, ut64 offset, ut64 size,
92102

93103
r_list_push (stack, r_cf_parse_state_new (R_CF_STATE_ROOT));
94104

95-
for (i = 0; i < size; i++) {
96-
ut8 doc = 0;
97-
r_buf_read_at (file_buf, offset + i, &doc, 1);
105+
for (i = 0; i < buf_len; i++) {
106+
ut8 doc = buf[i];
98107
if (!doc) {
99108
break;
100109
}
@@ -379,6 +388,7 @@ RCFValueDict *r_cf_value_dict_parse (RBuffer *file_buf, ut64 offset, ut64 size,
379388
r_list_free (stack);
380389
r_list_free (idlist);
381390
free (content);
391+
free (buf);
382392

383393
return result;
384394
}

libr/bin/p/bin_xnu_kernelcache.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ static int ut64_compare(const void *pa, const void *pb);
207207
static ut64 next_vtable_after(const ut64 *arr, size_t n, ut64 self_start);
208208
static bool load_kext_text_blob(RBinFile *bf, RKext *kext, RKextTextBlob *blob);
209209
static const ut8 *text_ptr(const RKextTextBlob *tb, ut64 va);
210+
static const ut8 *text_ptr_n(const RKextTextBlob *tb, ut64 va, size_t n);
210211
static bool try_read_exec_va(RBinFile *bf, RKext *kext, ut64 va, void *dst, size_t len);
211212
static bool try_read_data_va(RBinFile *bf, RKext *kext, ut64 va, void *dst, size_t len);
212213
static bool try_read_printable_cstr(RBinFile *bf, RKext *kext, ut64 va, char **cstr);
@@ -2003,6 +2004,11 @@ static RList *resolve_iokit_classes(RVecRBinSymbol *symbols, ut64 start_offset,
20032004
static RList *find_class_registrations(RVecRBinSymbol *symbols, ut64 start_offset, RBinFile *bf, RKext *kext) {
20042005
RList *classes = r_list_newf (r_iokit_class_free);
20052006

2007+
RKextTextBlob tb;
2008+
if (!load_kext_text_blob (bf, kext, &tb)) {
2009+
return classes;
2010+
}
2011+
20062012
ut64 i;
20072013
ut64 end_offset = RVecRBinSymbol_length (symbols);
20082014
for (i = start_offset; i != end_offset; i++) {
@@ -2019,8 +2025,8 @@ static RList *find_class_registrations(RVecRBinSymbol *symbols, ut64 start_offse
20192025

20202026
ut64 pc;
20212027
for (pc = func_vaddr; true; pc += 4) {
2022-
ut8 bytes[8];
2023-
if (!try_read_exec_va (bf, kext, pc, bytes, sizeof (bytes))) {
2028+
const ut8 *bytes = text_ptr_n (&tb, pc, 8);
2029+
if (!bytes) {
20242030
break;
20252031
}
20262032

@@ -2081,12 +2087,6 @@ static RList *find_class_registrations(RVecRBinSymbol *symbols, ut64 start_offse
20812087
}
20822088
w3_site = 0;
20832089

2084-
/*
2085-
* const int off26 = (int) ((insn & 0x03FFFFFFu) << 6) >> 6;
2086-
* const ut64 bl_target = pc + ((ut64) off26 << 2);
2087-
* TODO: Implement renaming of bl_target.
2088-
*/
2089-
20902090
char *name = NULL;
20912091
if (!try_read_printable_cstr (bf, kext, name_va, &name)) {
20922092
continue;
@@ -2101,6 +2101,7 @@ static RList *find_class_registrations(RVecRBinSymbol *symbols, ut64 start_offse
21012101
}
21022102
}
21032103

2104+
free (tb.buf);
21042105
return classes;
21052106
}
21062107

@@ -2446,6 +2447,13 @@ static const ut8 *text_ptr(const RKextTextBlob *tb, ut64 va) {
24462447
return tb->buf + (va - tb->va);
24472448
}
24482449

2450+
static const ut8 *text_ptr_n(const RKextTextBlob *tb, ut64 va, size_t n) {
2451+
if (va < tb->va || va + n > tb->va + tb->size) {
2452+
return NULL;
2453+
}
2454+
return tb->buf + (va - tb->va);
2455+
}
2456+
24492457
static bool try_read_exec_va(RBinFile *bf, RKext *kext, ut64 va, void *dst, size_t len) {
24502458
return r_buf_read_at (bf->buf, va - kext->pa2va_exec, dst, len) == len;
24512459
}

0 commit comments

Comments
 (0)