mirror of
https://github.com/darlinghq/darling-objc4.git
synced 2024-11-26 21:50:26 +00:00
117 lines
2.1 KiB
Mathematica
117 lines
2.1 KiB
Mathematica
|
/*
|
||
|
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
|