]>
Commit | Line | Data |
---|---|---|
13ba007e A |
1 | /* |
2 | TEST_CRASHES | |
3 | TEST_RUN_OUTPUT | |
4 | arm | |
5 | OK: badCache.m | |
6 | OR | |
7 | crash now | |
8 | objc\[\d+\]: Method cache corrupted.* | |
9 | objc\[\d+\]: .* | |
10 | objc\[\d+\]: .* | |
11 | objc\[\d+\]: .* | |
12 | objc\[\d+\]: .* | |
13 | objc\[\d+\]: Method cache corrupted.* | |
14 | objc\[\d+\]: HALTED | |
15 | END | |
16 | */ | |
17 | ||
18 | ||
19 | #include "test.h" | |
20 | ||
21 | // Test objc_msgSend's detection of infinite loops during cache scan. | |
22 | ||
23 | #if __arm__ | |
24 | ||
25 | int main() | |
26 | { | |
27 | testwarn("objc_msgSend on arm doesn't detect infinite loops"); | |
28 | fprintf(stderr, "arm\n"); | |
29 | succeed(__FILE__); | |
30 | } | |
31 | ||
32 | #else | |
33 | ||
34 | #include "testroot.i" | |
35 | ||
36 | #if __LP64__ | |
37 | typedef uint32_t mask_t; | |
38 | #else | |
39 | typedef uint16_t mask_t; | |
40 | #endif | |
41 | ||
42 | struct bucket_t { | |
43 | uintptr_t sel; | |
44 | uintptr_t imp; | |
45 | }; | |
46 | ||
47 | struct cache_t { | |
1807f628 | 48 | uintptr_t buckets; |
13ba007e A |
49 | mask_t mask; |
50 | mask_t occupied; | |
51 | }; | |
52 | ||
53 | struct class_t { | |
54 | void *isa; | |
55 | void *supercls; | |
56 | struct cache_t cache; | |
57 | }; | |
58 | ||
59 | @interface Subclass : TestRoot @end | |
60 | @implementation Subclass @end | |
61 | ||
62 | int main() | |
63 | { | |
64 | Class cls = [TestRoot class]; | |
65 | id obj = [cls new]; | |
66 | [obj self]; | |
67 | ||
68 | struct cache_t *cache = &((__bridge struct class_t *)cls)->cache; | |
1807f628 A |
69 | |
70 | // Figure out which cache mask scheme is in use by examining the existing bits. | |
71 | int low4 = 0; | |
72 | #if __LP64__ | |
73 | int top16 = 0; | |
74 | #endif | |
75 | int outlined = 0; | |
76 | ||
77 | if (cache->buckets & 0xf) { | |
78 | low4 = 1; | |
79 | #if __LP64__ | |
80 | } else if ((cache->buckets & (0xffffULL << 48))) { | |
81 | top16 = 1; | |
82 | #endif | |
83 | } else { | |
84 | outlined = 1; | |
85 | } | |
86 | ||
13ba007e | 87 | # define COUNT 4 |
1807f628 | 88 | # define COUNTSHIFT 14 |
13ba007e A |
89 | struct bucket_t *buckets = (struct bucket_t *)calloc(sizeof(struct bucket_t), COUNT+1); |
90 | for (int i = 0; i < COUNT; i++) { | |
91 | buckets[i].sel = ~0; | |
92 | buckets[i].imp = ~0; | |
93 | } | |
94 | buckets[COUNT].sel = 1; | |
95 | buckets[COUNT].imp = (uintptr_t)buckets; | |
96 | ||
1807f628 A |
97 | if (low4) { |
98 | cache->buckets = (uintptr_t)buckets | COUNTSHIFT; | |
99 | #if __LP64__ | |
100 | } else if (top16) { | |
101 | cache->buckets = ((uintptr_t)(COUNT - 1) << 48) | (uintptr_t)buckets; | |
102 | #endif | |
103 | } else if (outlined) { | |
104 | cache->mask = COUNT-1; | |
105 | cache->buckets = (uintptr_t)buckets; | |
106 | } | |
13ba007e | 107 | |
1807f628 A |
108 | cache->occupied = 0; |
109 | ||
13ba007e A |
110 | fprintf(stderr, "crash now\n"); |
111 | [obj self]; | |
112 | ||
113 | fail("should have crashed"); | |
114 | } | |
115 | ||
116 | #endif |