123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- // xpc leaks memory in dlopen(). Disable it.
- // TEST_ENV XPC_SERVICES_UNAVAILABLE=1
- /*
- TEST_BUILD
- $C{COMPILE} $DIR/unload4.m -o unload4.dylib -dynamiclib
- $C{COMPILE_C} $DIR/unload3.c -o unload3.dylib -dynamiclib
- $C{COMPILE} $DIR/unload2.m -o unload2.bundle -bundle $C{FORCE_LOAD_ARCLITE} -Xlinker -undefined -Xlinker dynamic_lookup
- $C{COMPILE} $DIR/unload.m -o unload.exe -framework Foundation
- END
- */
- /*
- TEST_BUILD_OUTPUT
- ld: warning: -undefined dynamic_lookup is deprecated on .*
- OR
- END
- */
- #include "test.h"
- #include <objc/runtime.h>
- #include <dlfcn.h>
- #include <unistd.h>
- #include "unload.h"
- #if __has_feature(objc_arc)
- int main()
- {
- testwarn("rdar://11368528 confused by Foundation");
- succeed(__FILE__);
- }
- #else
- static id forward_handler(void)
- {
- return 0;
- }
- static BOOL hasName(const char * const *names, const char *query)
- {
- const char *name;
- while ((name = *names++)) {
- if (strstr(name, query)) return YES;
- }
- return NO;
- }
- void cycle(void)
- {
- int i;
- char buf[100];
- unsigned int imageCount, imageCount0;
- const char **names;
- const char *name;
- names = objc_copyImageNames(&imageCount0);
- testassert(names);
- free(names);
- void *bundle = dlopen("unload2.bundle", RTLD_LAZY);
- testassert(bundle);
- names = objc_copyImageNames(&imageCount);
- testassert(names);
- testassert(imageCount == imageCount0 + 1);
- testassert(hasName(names, "unload2.bundle"));
- free(names);
- Class small = objc_getClass("SmallClass");
- Class big = objc_getClass("BigClass");
- Class missing = objc_getClass("SubclassOfMissingWeakImport");
- testassert(small);
- testassert(big);
- testassert(!missing);
- name = class_getImageName(small);
- testassert(name);
- testassert(strstr(name, "unload2.bundle"));
- name = class_getImageName(big);
- testassert(name);
- testassert(strstr(name, "unload2.bundle"));
- id o1 = [small new];
- id o2 = [big new];
- testassert(o1);
- testassert(o2);
-
- // give BigClass and BigClass->isa large method caches (4692641)
- // Flush caches part way through to test large empty caches.
- for (i = 0; i < 3000; i++) {
- sprintf(buf, "method_%d", i);
- SEL sel = sel_registerName(buf);
- ((void(*)(id, SEL))objc_msgSend)(o2, sel);
- ((void(*)(id, SEL))objc_msgSend)(object_getClass(o2), sel);
- }
- _objc_flush_caches(object_getClass(o2));
- for (i = 0; i < 17000; i++) {
- sprintf(buf, "method_%d", i);
- SEL sel = sel_registerName(buf);
- ((void(*)(id, SEL))objc_msgSend)(o2, sel);
- ((void(*)(id, SEL))objc_msgSend)(object_getClass(o2), sel);
- }
- RELEASE_VAR(o1);
- RELEASE_VAR(o2);
- testcollect();
- int err = dlclose(bundle);
- testassert(err == 0);
- err = dlclose(bundle);
- testassert(err == -1); // already closed
- _objc_flush_caches(nil);
- testassert(objc_getClass("SmallClass") == NULL);
- testassert(objc_getClass("BigClass") == NULL);
- names = objc_copyImageNames(&imageCount);
- testassert(names);
- testassert(imageCount == imageCount0);
- testassert(! hasName(names, "unload2.bundle"));
- free(names);
- // these selectors came from the bundle
- testassert(0 == strcmp("unload2_instance_method", sel_getName(sel_registerName("unload2_instance_method"))));
- testassert(0 == strcmp("unload2_category_method", sel_getName(sel_registerName("unload2_category_method"))));
- // This protocol came from the bundle.
- // It isn't unloaded cleanly (rdar://20664713), but neither
- // may it cause the protocol table to crash after unloading.
- testassert(objc_getProtocol("SmallProtocol"));
- }
- int main()
- {
- objc_setForwardHandler((void*)&forward_handler, (void*)&forward_handler);
- #if defined(__arm__) || defined(__arm64__)
- int count = 10;
- #else
- int count = is_guardmalloc() ? 10 : 100;
- #endif
-
- cycle();
- #if __LP64__
- // fixme heap use goes up 512 bytes after the 2nd cycle only - bad or not?
- cycle();
- #endif
- leak_mark();
- while (count--) {
- cycle();
- }
- leak_check(0);
- // 5359412 Make sure dylibs with nothing other than image_info can close
- void *dylib = dlopen("unload3.dylib", RTLD_LAZY);
- testassert(dylib);
- int err = dlclose(dylib);
- testassert(err == 0);
- err = dlclose(dylib);
- testassert(err == -1); // already closed
- // Make sure dylibs with real objc content cannot close
- dylib = dlopen("unload4.dylib", RTLD_LAZY);
- testassert(dylib);
- err = dlclose(dylib);
- testassert(err == 0);
- err = dlclose(dylib);
- testassert(err == -1); // already closed
- succeed(__FILE__);
- }
- #endif
|