Skip to content

Commit 5f57e61

Browse files
zhkl0228claude
andcommitted
feat(ios): implement NSConstantDictionary and fix NSConstantArray
Interpret compiler-emitted constant literals in __objc_dictobj/ __objc_arrayobj by their clang ABI layout: - NSConstantDictionary: isa|options|count|keys|objs; implement count, objectForKey: and keyEnumerator so NSDictionary conveniences, fast enumeration and Swift bridging work on constant dictionaries. - NSConstantArray: read real count/objs instead of the count->0 stub, add objectAtIndex:. - Redirect _OBJC_CLASS_$_NSConstantDictionary binding to the fake UIKit image in MachOLoader. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 3107359 commit 5f57e61

4 files changed

Lines changed: 59 additions & 1 deletion

File tree

unidbg-ios/src/main/java/com/github/unidbg/ios/MachOLoader.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,6 +1759,7 @@ final MachOModule fakeTargetImage(MachOModule targetImage, String symbolName) {
17591759
"___NSDictionary0__".equals(symbolName) ||
17601760
"_OBJC_CLASS_$_NSConstantIntegerNumber".equals(symbolName) ||
17611761
"_OBJC_CLASS_$_NSConstantArray".equals(symbolName) ||
1762+
"_OBJC_CLASS_$_NSConstantDictionary".equals(symbolName) ||
17621763
"_NSProcessInfoPowerStateDidChangeNotification".equals(symbolName) ||
17631764
"_NSExtensionHostDidEnterBackgroundNotification".equals(symbolName) ||
17641765
"_NSExtensionHostDidBecomeActiveNotification".equals(symbolName) ||

unidbg-ios/src/main/native/ios/Frameworks/UIKit/UIKit.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,13 @@ BOOL UIAccessibilityDarkerSystemColorsEnabled();
435435

436436
@interface NSConstantArray : NSArray
437437
- (unsigned long)count;
438+
- (id)objectAtIndex:(NSUInteger)index;
439+
@end
440+
441+
@interface NSConstantDictionary : NSDictionary
442+
- (NSUInteger)count;
443+
- (id)objectForKey:(id)aKey;
444+
- (NSEnumerator *)keyEnumerator;
438445
@end
439446

440447
@interface NSConstantIntegerNumber : NSNumber {

unidbg-ios/src/main/native/ios/Frameworks/UIKit/UIKit.m

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,9 +659,59 @@ - (id)init {
659659
@implementation BRQuery
660660
@end
661661

662+
// Compiler-emitted constant array literal layout (__objc_arrayobj):
663+
// isa | count | id *objs
664+
struct __NSConstantArray {
665+
Class isa;
666+
unsigned long count;
667+
const id *objs;
668+
};
669+
670+
// Compiler-emitted constant dictionary literal layout (__objc_dictobj):
671+
// isa | options | count | id *keys | id *objs
672+
// keys[] is immediately followed by objs[], both sized `count`.
673+
struct __NSConstantDictionary {
674+
Class isa;
675+
unsigned long options;
676+
unsigned long count;
677+
const id *keys;
678+
const id *objs;
679+
};
680+
662681
@implementation NSConstantArray
663682
- (unsigned long)count {
664-
return 0;
683+
return ((struct __NSConstantArray *)self)->count;
684+
}
685+
- (id)objectAtIndex:(NSUInteger)index {
686+
struct __NSConstantArray *a = (struct __NSConstantArray *)self;
687+
if (index >= a->count) {
688+
[NSException raise:NSRangeException format:@"index %lu beyond bounds [0 .. %lu]", (unsigned long)index, a->count ? a->count - 1 : 0];
689+
}
690+
return (id)a->objs[index];
691+
}
692+
@end
693+
694+
@implementation NSConstantDictionary
695+
- (NSUInteger)count {
696+
return (NSUInteger)((struct __NSConstantDictionary *)self)->count;
697+
}
698+
- (id)objectForKey:(id)aKey {
699+
struct __NSConstantDictionary *d = (struct __NSConstantDictionary *)self;
700+
for (unsigned long i = 0; i < d->count; i++) {
701+
id key = (id)d->keys[i];
702+
if (key == aKey || [key isEqual:aKey]) {
703+
return (id)d->objs[i];
704+
}
705+
}
706+
return nil;
707+
}
708+
- (NSEnumerator *)keyEnumerator {
709+
struct __NSConstantDictionary *d = (struct __NSConstantDictionary *)self;
710+
NSMutableArray *keys = [NSMutableArray arrayWithCapacity:(NSUInteger)d->count];
711+
for (unsigned long i = 0; i < d->count; i++) {
712+
[keys addObject:(id)d->keys[i]];
713+
}
714+
return [keys objectEnumerator];
665715
}
666716
@end
667717

Binary file not shown.

0 commit comments

Comments
 (0)