123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- /*
- TEST_CRASHES
- TEST_RUN_OUTPUT
- arm
- OK: badCache.m
- OR
- crash now
- objc\[\d+\]: Method cache corrupted.*
- objc\[\d+\]: .*
- objc\[\d+\]: .*
- objc\[\d+\]: .*
- objc\[\d+\]: .*
- objc\[\d+\]: Method cache corrupted.*
- objc\[\d+\]: HALTED
- END
- */
- #include "test.h"
- // Test objc_msgSend's detection of infinite loops during cache scan.
- #if __arm__
- int main()
- {
- testwarn("objc_msgSend on arm doesn't detect infinite loops");
- fprintf(stderr, "arm\n");
- succeed(__FILE__);
- }
- #else
- #include "testroot.i"
- #if __LP64__
- typedef uint32_t mask_t;
- #else
- typedef uint16_t mask_t;
- #endif
- struct bucket_t {
- uintptr_t sel;
- uintptr_t imp;
- };
- struct cache_t {
- uintptr_t buckets;
- mask_t mask;
- mask_t occupied;
- };
- struct class_t {
- void *isa;
- void *supercls;
- struct cache_t cache;
- };
- @interface Subclass : TestRoot @end
- @implementation Subclass @end
- int main()
- {
- Class cls = [TestRoot class];
- id obj = [cls new];
- [obj self];
- struct cache_t *cache = &((__bridge struct class_t *)cls)->cache;
-
- // Figure out which cache mask scheme is in use by examining the existing bits.
- int low4 = 0;
- #if __LP64__
- int top16 = 0;
- #endif
- int outlined = 0;
-
- if (cache->buckets & 0xf) {
- low4 = 1;
- #if __LP64__
- } else if ((cache->buckets & (0xffffULL << 48))) {
- top16 = 1;
- #endif
- } else {
- outlined = 1;
- }
-
- # define COUNT 4
- # define COUNTSHIFT 14
- struct bucket_t *buckets = (struct bucket_t *)calloc(sizeof(struct bucket_t), COUNT+1);
- for (int i = 0; i < COUNT; i++) {
- buckets[i].sel = ~0;
- buckets[i].imp = ~0;
- }
- buckets[COUNT].sel = 1;
- buckets[COUNT].imp = (uintptr_t)buckets;
- if (low4) {
- cache->buckets = (uintptr_t)buckets | COUNTSHIFT;
- #if __LP64__
- } else if (top16) {
- cache->buckets = ((uintptr_t)(COUNT - 1) << 48) | (uintptr_t)buckets;
- #endif
- } else if (outlined) {
- cache->mask = COUNT-1;
- cache->buckets = (uintptr_t)buckets;
- }
- cache->occupied = 0;
-
- fprintf(stderr, "crash now\n");
- [obj self];
- fail("should have crashed");
- }
- #endif
|