]> git.saurik.com Git - apple/dyld.git/blob - testing/test-cases/_dyld_for_each_objc_class.dtest/main.m
dyld-851.27.tar.gz
[apple/dyld.git] / testing / test-cases / _dyld_for_each_objc_class.dtest / main.m
1
2 // BUILD: $CC linked1.m -dynamiclib -o $BUILD_DIR/liblinked1.dylib -install_name $RUN_DIR/liblinked1.dylib -lobjc
3 // BUILD: $CC linked2.m -dynamiclib -o $BUILD_DIR/liblinked2.dylib -install_name $RUN_DIR/liblinked2.dylib -lobjc
4 // BUILD: $CC main.m -o $BUILD_DIR/_dyld_for_each_objc_class.exe $BUILD_DIR/liblinked1.dylib $BUILD_DIR/liblinked2.dylib -lobjc
5
6 // RUN: ./_dyld_for_each_objc_class.exe
7
8 // The preoptimized objc class information is available via _dyld_for_each_objc_class().
9 // This test ensures that we match the objc behaviour when there are duplicates.
10 // For objc today, it walks the images in reverse load order, so the deepest library will be
11 // the canonical definition of a class.
12
13 #include <mach-o/dyld_priv.h>
14
15 #import <Foundation/Foundation.h>
16
17 #include "test_support.h"
18
19 // All the libraries have a copy of DyldClass
20 @interface DyldClass : NSObject
21 @end
22
23 @implementation DyldClass
24 @end
25
26 // Only the main executable has DyldMainClass
27 @interface DyldMainClass : NSObject
28 @end
29
30 @implementation DyldMainClass
31 @end
32
33 extern Class OBJC_CLASS_$_DyldClass;
34 extern Class OBJC_CLASS_$_DyldMainClass;
35
36 Class getMainDyldClass() {
37 return (Class)&OBJC_CLASS_$_DyldClass;
38 }
39
40 Class getMainDyldMainClass() {
41 return (Class)&OBJC_CLASS_$_DyldMainClass;
42 }
43
44 extern id objc_getClass(const char *name);
45
46 // Get the DyldClass from liblinked1.dylib
47 extern Class getLinked1DyldClass();
48
49 // Get the DyldClass from liblinked2.dylib
50 extern Class getLinked2DyldClass();
51
52 // Get the DyldLinkedClass from liblinked2.dylib
53 extern Class getLinked2DyldLinkedClass();
54
55 static bool gotDyldClassMain = false;
56 static bool gotDyldClassLinked = false;
57 static bool gotDyldClassLinked2 = false;
58
59
60 static bool objcOptimizedByDyld() {
61 extern const uint32_t objcInfo[] __asm("section$start$__DATA_CONST$__objc_imageinfo");
62 return (objcInfo[1] & 0x80);
63 }
64
65 static bool haveDyldCache() {
66 size_t unusedCacheLen;
67 return (_dyld_get_shared_cache_range(&unusedCacheLen) != NULL);
68 }
69
70 int main(int argc, const char* argv[], const char* envp[], const char* apple[]) {
71 if (!objcOptimizedByDyld() || !haveDyldCache()) {
72 __block bool sawClass = false;
73 _dyld_for_each_objc_class("DyldClass", ^(void* classPtr, bool isLoaded, bool* stop) {
74 sawClass = true;
75 });
76 if (sawClass) {
77 FAIL("dyld2 shouldn't see any classes");
78 }
79 PASS("no shared cache or no dyld optimized objc");
80 }
81
82 // Check that DyldClass comes from liblinked2 as it is last in load order
83 id runtimeDyldClass = objc_getClass("DyldClass");
84 if (runtimeDyldClass != getLinked2DyldClass()) {
85 FAIL("DyldClass should have come from liblinked2");
86 }
87
88 // Check that DyldLinkedClass comes from liblinked2 as it is last in load order
89 id runtimeDyldLinkedClass = objc_getClass("DyldLinkedClass");
90 if (runtimeDyldLinkedClass != getLinked2DyldLinkedClass()) {
91 FAIL("DyldLinkedClass should have come from liblinked2");
92 }
93
94 // Walk all the implementations of "DyldClass"
95 _dyld_for_each_objc_class("DyldClass", ^(void* classPtr, bool isLoaded, bool* stop) {
96 // We should walk these in the order liblinked2, liblinked, main exe
97 if (!gotDyldClassLinked2) {
98 if (classPtr != getLinked2DyldClass()) {
99 FAIL("Optimized DyldClass should have come from liblinked2");
100 }
101 if (!isLoaded) {
102 FAIL("Optimized DyldClass isLoaded should have been set on liblinked2");
103 }
104 gotDyldClassLinked2 = true;
105 return;
106 }
107 if (!gotDyldClassLinked) {
108 if (classPtr != getLinked1DyldClass()) {
109 FAIL("Optimized DyldClass should have come from liblinked");
110 }
111 if (!isLoaded) {
112 FAIL("Optimized DyldClass isLoaded should have been set on liblinked");
113 }
114 gotDyldClassLinked = true;
115 return;
116 }
117 if (!gotDyldClassMain) {
118 if (classPtr != getMainDyldClass()) {
119 FAIL("Optimized DyldClass should have come from main exe");
120 }
121 if (!isLoaded) {
122 FAIL("Optimized DyldClass isLoaded should have been set on main exe");
123 }
124 gotDyldClassMain = true;
125 return;
126 }
127 FAIL("Unexpected Optimized DyldClass");
128 });
129
130 if ( !gotDyldClassLinked2 || !gotDyldClassLinked || !gotDyldClassMain) {
131 FAIL("Failed to find all duplicates of 'DyldClass'");
132 }
133
134 // Visit again, and return liblinked2's DyldClass
135 __block void* dyldClassImpl = nil;
136 _dyld_for_each_objc_class("DyldClass", ^(void* classPtr, bool isLoaded, bool* stop) {
137 dyldClassImpl = classPtr;
138 *stop = true;
139 });
140 if (dyldClassImpl != getLinked2DyldClass()) {
141 FAIL("_dyld_for_each_objc_class should have returned DyldClass from liblinked2");
142 }
143
144 // Visit DyldMainClass and make sure it makes the callback for just the result from main.exe
145 __block void* dyldMainClassImpl = nil;
146 _dyld_for_each_objc_class("DyldMainClass", ^(void* classPtr, bool isLoaded, bool* stop) {
147 dyldMainClassImpl = classPtr;
148 *stop = true;
149 });
150 if (dyldMainClassImpl != getMainDyldMainClass()) {
151 FAIL("_dyld_for_each_objc_class should have returned DyldMainClass from main.exe");
152 }
153
154 PASS("Success");
155 }