]>
Commit | Line | Data |
---|---|---|
bc4fafce A |
1 | #include "test.h" |
2 | ||
3 | struct ObjCClass { | |
34d5b5e8 A |
4 | struct ObjCClass * __ptrauth_objc_isa_pointer isa; |
5 | struct ObjCClass * __ptrauth_objc_super_pointer superclass; | |
bc4fafce A |
6 | void *cachePtr; |
7 | uintptr_t zero; | |
8 | struct ObjCClass_ro *data; | |
9 | }; | |
10 | ||
11 | struct ObjCClass_ro { | |
12 | uint32_t flags; | |
13 | uint32_t instanceStart; | |
14 | uint32_t instanceSize; | |
15 | #ifdef __LP64__ | |
16 | uint32_t reserved; | |
17 | #endif | |
18 | ||
19 | const uint8_t * ivarLayout; | |
20 | ||
21 | const char * name; | |
34d5b5e8 | 22 | struct ObjCMethodList * __ptrauth_objc_method_list_pointer baseMethodList; |
bc4fafce A |
23 | struct protocol_list_t * baseProtocols; |
24 | const struct ivar_list_t * ivars; | |
25 | ||
26 | const uint8_t * weakIvarLayout; | |
27 | struct property_list_t *baseProperties; | |
28 | }; | |
29 | ||
30 | struct ObjCMethod { | |
31 | char *name; | |
32 | char *type; | |
33 | IMP imp; | |
34 | }; | |
35 | ||
36 | struct ObjCMethodList { | |
37 | uint32_t sizeAndFlags; | |
38 | uint32_t count; | |
39 | struct ObjCMethod methods[]; | |
40 | }; | |
41 | ||
42 | struct ObjCMethodSmall { | |
43 | int32_t nameOffset; | |
44 | int32_t typeOffset; | |
45 | int32_t impOffset; | |
46 | }; | |
47 | ||
48 | struct ObjCMethodListSmall { | |
49 | uint32_t sizeAndFlags; | |
50 | uint32_t count; | |
51 | struct ObjCMethodSmall methods[]; | |
52 | }; | |
53 | ||
54 | ||
55 | extern struct ObjCClass OBJC_METACLASS_$_NSObject; | |
56 | extern struct ObjCClass OBJC_CLASS_$_NSObject; | |
57 | ||
58 | ||
59 | struct ObjCClass_ro FooMetaclass_ro = { | |
60 | .flags = 1, | |
61 | .instanceStart = 40, | |
62 | .instanceSize = 40, | |
63 | .name = "Foo", | |
64 | }; | |
65 | ||
66 | struct ObjCClass FooMetaclass = { | |
67 | .isa = &OBJC_METACLASS_$_NSObject, | |
68 | .superclass = &OBJC_METACLASS_$_NSObject, | |
69 | .cachePtr = &_objc_empty_cache, | |
70 | .data = &FooMetaclass_ro, | |
71 | }; | |
72 | ||
73 | ||
74 | int ranMyMethod1; | |
75 | extern "C" void myMethod1(id self __unused, SEL _cmd) { | |
76 | testprintf("myMethod1\n"); | |
77 | testassert(_cmd == @selector(myMethod1)); | |
78 | ranMyMethod1 = 1; | |
79 | } | |
80 | ||
81 | int ranMyMethod2; | |
82 | extern "C" void myMethod2(id self __unused, SEL _cmd) { | |
83 | testprintf("myMethod2\n"); | |
84 | testassert(_cmd == @selector(myMethod2)); | |
85 | ranMyMethod2 = 1; | |
86 | } | |
87 | ||
88 | int ranMyMethod3; | |
89 | extern "C" void myMethod3(id self __unused, SEL _cmd) { | |
90 | testprintf("myMethod3\n"); | |
91 | testassert(_cmd == @selector(myMethod3)); | |
92 | ranMyMethod3 = 1; | |
93 | } | |
94 | ||
95 | int ranMyReplacedMethod1; | |
96 | extern "C" void myReplacedMethod1(id self __unused, SEL _cmd) { | |
97 | testprintf("myReplacedMethod1\n"); | |
98 | testassert(_cmd == @selector(myMethod1)); | |
99 | ranMyReplacedMethod1 = 1; | |
100 | } | |
101 | ||
102 | int ranMyReplacedMethod2; | |
103 | extern "C" void myReplacedMethod2(id self __unused, SEL _cmd) { | |
104 | testprintf("myReplacedMethod2\n"); | |
105 | testassert(_cmd == @selector(myMethod2)); | |
106 | ranMyReplacedMethod2 = 1; | |
107 | } | |
108 | ||
109 | struct BigStruct { | |
110 | uintptr_t a, b, c, d, e, f, g; | |
111 | }; | |
112 | ||
113 | int ranMyMethodStret; | |
114 | extern "C" BigStruct myMethodStret(id self __unused, SEL _cmd) { | |
115 | testprintf("myMethodStret\n"); | |
116 | testassert(_cmd == @selector(myMethodStret)); | |
117 | ranMyMethodStret = 1; | |
118 | BigStruct ret = {}; | |
119 | return ret; | |
120 | } | |
121 | ||
122 | int ranMyReplacedMethodStret; | |
123 | extern "C" BigStruct myReplacedMethodStret(id self __unused, SEL _cmd) { | |
124 | testprintf("myReplacedMethodStret\n"); | |
125 | testassert(_cmd == @selector(myMethodStret)); | |
126 | ranMyReplacedMethodStret = 1; | |
127 | BigStruct ret = {}; | |
128 | return ret; | |
129 | } | |
130 | ||
131 | extern struct ObjCMethodList Foo_methodlistSmall; | |
132 | ||
133 | asm(R"ASM( | |
134 | .section __TEXT,__cstring | |
135 | _MyMethod1Name: | |
136 | .asciz "myMethod1" | |
137 | _MyMethod2Name: | |
138 | .asciz "myMethod2" | |
139 | _MyMethod3Name: | |
140 | .asciz "myMethod3" | |
141 | _BoringMethodType: | |
142 | .asciz "v16@0:8" | |
143 | _MyMethodStretName: | |
144 | .asciz "myMethodStret" | |
34d5b5e8 A |
145 | _MyMethodNullTypesName: |
146 | .asciz "myMethodNullTypes" | |
bc4fafce A |
147 | _StretType: |
148 | .asciz "{BigStruct=QQQQQQQ}16@0:8" | |
149 | )ASM"); | |
150 | ||
151 | #if __LP64__ | |
152 | asm(R"ASM( | |
153 | .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip | |
154 | _MyMethod1NameRef: | |
155 | .quad _MyMethod1Name | |
156 | _MyMethod2NameRef: | |
157 | .quad _MyMethod2Name | |
158 | _MyMethod3NameRef: | |
159 | .quad _MyMethod3Name | |
160 | _MyMethodStretNameRef: | |
161 | .quad _MyMethodStretName | |
34d5b5e8 A |
162 | _MyMethodNullTypesNameRef: |
163 | .quad _MyMethodNullTypesName | |
bc4fafce A |
164 | )ASM"); |
165 | #else | |
166 | asm(R"ASM( | |
167 | .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip | |
168 | _MyMethod1NameRef: | |
169 | .long _MyMethod1Name | |
170 | _MyMethod2NameRef: | |
171 | .long _MyMethod2Name | |
172 | _MyMethod3NameRef: | |
173 | .long _MyMethod3Name | |
174 | _MyMethodStretNameRef: | |
175 | .long _MyMethodStretName | |
34d5b5e8 A |
176 | _MyMethodNullTypesNameRef: |
177 | .long _MyMethodNullTypesName | |
bc4fafce A |
178 | )ASM"); |
179 | #endif | |
180 | ||
181 | #if MUTABLE_METHOD_LIST | |
182 | asm(".section __DATA,__objc_methlist\n"); | |
183 | #else | |
184 | asm(".section __TEXT,__objc_methlist\n"); | |
185 | #endif | |
186 | ||
187 | asm(R"ASM( | |
188 | .p2align 2 | |
189 | _Foo_methodlistSmall: | |
190 | .long 12 | 0x80000000 | |
34d5b5e8 | 191 | .long 5 |
bc4fafce A |
192 | |
193 | .long _MyMethod1NameRef - . | |
194 | .long _BoringMethodType - . | |
195 | .long _myMethod1 - . | |
196 | ||
197 | .long _MyMethod2NameRef - . | |
198 | .long _BoringMethodType - . | |
199 | .long _myMethod2 - . | |
200 | ||
201 | .long _MyMethod3NameRef - . | |
202 | .long _BoringMethodType - . | |
203 | .long _myMethod3 - . | |
204 | ||
205 | .long _MyMethodStretNameRef - . | |
206 | .long _StretType - . | |
207 | .long _myMethodStret - . | |
34d5b5e8 A |
208 | |
209 | .long _MyMethodNullTypesNameRef - . | |
210 | .long 0 | |
211 | .long _myMethod1 - . | |
bc4fafce A |
212 | )ASM"); |
213 | ||
214 | struct ObjCClass_ro Foo_ro = { | |
215 | .instanceStart = 8, | |
216 | .instanceSize = 8, | |
217 | .name = "Foo", | |
218 | .baseMethodList = &Foo_methodlistSmall, | |
219 | }; | |
220 | ||
221 | struct ObjCClass FooClass = { | |
222 | .isa = &FooMetaclass, | |
223 | .superclass = &OBJC_CLASS_$_NSObject, | |
224 | .cachePtr = &_objc_empty_cache, | |
225 | .data = &Foo_ro, | |
226 | }; | |
227 | ||
228 | ||
229 | @interface Foo: NSObject | |
230 | ||
231 | - (void)myMethod1; | |
232 | - (void)myMethod2; | |
233 | - (void)myMethod3; | |
234 | - (BigStruct)myMethodStret; | |
235 | ||
236 | @end |