]>
Commit | Line | Data |
---|---|---|
34d5b5e8 A |
1 | /* |
2 | TEST_RUN_OUTPUT | |
3 | LazyClassName | |
4 | LazyClassName2 | |
5 | END | |
6 | */ | |
7 | ||
8 | #include "test.h" | |
9 | #include "testroot.i" | |
10 | ||
11 | typedef const char * _Nullable (*objc_hook_lazyClassNamer)(_Nonnull Class); | |
12 | ||
13 | void objc_setHook_lazyClassNamer(_Nonnull objc_hook_lazyClassNamer newValue, | |
14 | _Nonnull objc_hook_lazyClassNamer * _Nonnull oldOutValue); | |
15 | ||
16 | #define RW_COPIED_RO (1<<27) | |
17 | ||
18 | struct ObjCClass { | |
19 | struct ObjCClass * __ptrauth_objc_isa_pointer isa; | |
20 | struct ObjCClass * __ptrauth_objc_super_pointer superclass; | |
21 | void *cachePtr; | |
22 | uintptr_t zero; | |
23 | uintptr_t data; | |
24 | }; | |
25 | ||
26 | struct ObjCClass_ro { | |
27 | uint32_t flags; | |
28 | uint32_t instanceStart; | |
29 | uint32_t instanceSize; | |
30 | #ifdef __LP64__ | |
31 | uint32_t reserved; | |
32 | #endif | |
33 | ||
34 | union { | |
35 | const uint8_t * ivarLayout; | |
36 | struct ObjCClass * nonMetaClass; | |
37 | }; | |
38 | ||
39 | const char * name; | |
40 | struct ObjCMethodList * __ptrauth_objc_method_list_pointer baseMethodList; | |
41 | struct protocol_list_t * baseProtocols; | |
42 | const struct ivar_list_t * ivars; | |
43 | ||
44 | const uint8_t * weakIvarLayout; | |
45 | struct property_list_t *baseProperties; | |
46 | }; | |
47 | ||
48 | extern struct ObjCClass OBJC_METACLASS_$_NSObject; | |
49 | extern struct ObjCClass OBJC_CLASS_$_NSObject; | |
50 | ||
51 | extern struct ObjCClass LazyClassName; | |
52 | extern struct ObjCClass LazyClassName2; | |
53 | ||
54 | struct ObjCClass_ro LazyClassNameMetaclass_ro = { | |
55 | .flags = 1, | |
56 | .instanceStart = 40, | |
57 | .instanceSize = 40, | |
58 | .nonMetaClass = &LazyClassName, | |
59 | }; | |
60 | ||
61 | struct ObjCClass LazyClassNameMetaclass = { | |
62 | .isa = &OBJC_METACLASS_$_NSObject, | |
63 | .superclass = &OBJC_METACLASS_$_NSObject, | |
64 | .cachePtr = &_objc_empty_cache, | |
65 | .data = (uintptr_t)&LazyClassNameMetaclass_ro, | |
66 | }; | |
67 | ||
68 | struct ObjCClass_ro LazyClassName_ro = { | |
69 | .instanceStart = 8, | |
70 | .instanceSize = 8, | |
71 | }; | |
72 | ||
73 | struct ObjCClass LazyClassName = { | |
74 | .isa = &LazyClassNameMetaclass, | |
75 | .superclass = &OBJC_CLASS_$_NSObject, | |
76 | .cachePtr = &_objc_empty_cache, | |
77 | .data = (uintptr_t)&LazyClassName_ro + 2, | |
78 | }; | |
79 | ||
80 | struct ObjCClass_ro LazyClassName2Metaclass_ro = { | |
81 | .flags = 1, | |
82 | .instanceStart = 40, | |
83 | .instanceSize = 40, | |
84 | .nonMetaClass = &LazyClassName2, | |
85 | }; | |
86 | ||
87 | struct ObjCClass LazyClassName2Metaclass = { | |
88 | .isa = &OBJC_METACLASS_$_NSObject, | |
89 | .superclass = &OBJC_METACLASS_$_NSObject, | |
90 | .cachePtr = &_objc_empty_cache, | |
91 | .data = (uintptr_t)&LazyClassName2Metaclass_ro, | |
92 | }; | |
93 | ||
94 | struct ObjCClass_ro LazyClassName2_ro = { | |
95 | .instanceStart = 8, | |
96 | .instanceSize = 8, | |
97 | }; | |
98 | ||
99 | struct ObjCClass LazyClassName2 = { | |
100 | .isa = &LazyClassName2Metaclass, | |
101 | .superclass = &OBJC_CLASS_$_NSObject, | |
102 | .cachePtr = &_objc_empty_cache, | |
103 | .data = (uintptr_t)&LazyClassName2_ro + 2, | |
104 | }; | |
105 | ||
106 | static objc_hook_lazyClassNamer OrigNamer; | |
107 | ||
108 | static const char *ClassNamer(Class cls) { | |
109 | if (cls == (__bridge Class)&LazyClassName) | |
110 | return "LazyClassName"; | |
111 | return OrigNamer(cls); | |
112 | } | |
113 | ||
114 | static objc_hook_lazyClassNamer OrigNamer2; | |
115 | ||
116 | static const char *ClassNamer2(Class cls) { | |
117 | if (cls == (__bridge Class)&LazyClassName2) | |
118 | return "LazyClassName2"; | |
119 | return OrigNamer2(cls); | |
120 | } | |
121 | ||
122 | __attribute__((section("__DATA,__objc_classlist,regular,no_dead_strip"))) | |
123 | struct ObjCClass *LazyClassNamePtr = &LazyClassName; | |
124 | __attribute__((section("__DATA,__objc_classlist,regular,no_dead_strip"))) | |
125 | struct ObjCClass *LazyClassNamePtr2 = &LazyClassName2; | |
126 | ||
127 | int main() { | |
128 | #pragma clang diagnostic push | |
129 | #pragma clang diagnostic ignored "-Wunguarded-availability" | |
130 | objc_setHook_lazyClassNamer(ClassNamer, &OrigNamer); | |
131 | objc_setHook_lazyClassNamer(ClassNamer2, &OrigNamer2); | |
132 | #pragma clang diagnostic pop | |
133 | ||
134 | printf("%s\n", class_getName([(__bridge id)&LazyClassName class])); | |
135 | printf("%s\n", class_getName([(__bridge id)&LazyClassName2 class])); | |
136 | } |