├── .gitignore
├── APPLE_LICENSE
├── LICENSE
├── README.md
├── ReleaseNotes.rtf
├── include
├── Block_private.h
├── CrashReporterClient.h
├── System
│ ├── machine
│ │ └── cpu_capabilities.h
│ └── pthread_machdep.h
├── _simple.h
├── kern
│ └── restartable.h
├── mach-o
│ └── dyld_priv.h
├── objc-shared-cache.h
├── os
│ ├── base_private.h
│ ├── linker_set.h
│ ├── lock_private.h
│ ├── reason_private.h
│ ├── tsd.h
│ └── variant_private.h
├── pthread
│ ├── spinlock_private.h
│ └── tsd_private.h
└── sys
│ └── reason.h
├── interposable.txt
├── lastGitDiff
├── lastGitStatus
├── markgc.cpp
├── objc.sln
├── objc.vcproj
├── objc.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── objc4.plist
├── objc_debug
└── main.m
├── objcdt
├── json.h
├── json.mm
├── objcdt-entitlements.plist
├── objcdt.1
└── objcdt.mm
├── objcrt
└── objcrt.vcproj
├── prebuild.bat
├── runtime
├── DenseMapExtras.h
├── Messengers.subproj
│ ├── objc-msg-arm.s
│ ├── objc-msg-arm64.s
│ ├── objc-msg-i386.s
│ ├── objc-msg-simulator-i386.s
│ ├── objc-msg-simulator-x86_64.s
│ ├── objc-msg-win32.m
│ └── objc-msg-x86_64.s
├── Module
│ ├── ObjectiveC.apinotes
│ └── module.modulemap
├── ModulePrivate
│ └── module.modulemap
├── NSObjCRuntime.h
├── NSObject-internal.h
├── NSObject-private.h
├── NSObject.h
├── NSObject.mm
├── Object.h
├── Object.mm
├── OldClasses.subproj
│ ├── List.h
│ └── List.m
├── PointerUnion.h
├── Protocol.h
├── Protocol.mm
├── arm64-asm.h
├── dummy-library-mac-i386.c
├── hashtable.h
├── hashtable2.h
├── hashtable2.mm
├── isa.h
├── llvm-AlignOf.h
├── llvm-DenseMap.h
├── llvm-DenseMapInfo.h
├── llvm-DenseSet.h
├── llvm-MathExtras.h
├── llvm-type_traits.h
├── maptable.h
├── maptable.mm
├── message.h
├── objc-abi.h
├── objc-accessors.mm
├── objc-api.h
├── objc-auto.h
├── objc-auto.mm
├── objc-block-trampolines.h
├── objc-block-trampolines.mm
├── objc-blocktramps-arm.s
├── objc-blocktramps-arm64.s
├── objc-blocktramps-i386.s
├── objc-blocktramps-x86_64.s
├── objc-cache-old.h
├── objc-cache-old.mm
├── objc-cache.mm
├── objc-class-old.mm
├── objc-class.h
├── objc-class.mm
├── objc-config.h
├── objc-env.h
├── objc-errors.mm
├── objc-exception.h
├── objc-exception.mm
├── objc-file-old.h
├── objc-file-old.mm
├── objc-file.h
├── objc-file.mm
├── objc-gdb.h
├── objc-initialize.h
├── objc-initialize.mm
├── objc-internal.h
├── objc-layout.mm
├── objc-load.h
├── objc-load.mm
├── objc-loadmethod.h
├── objc-loadmethod.mm
├── objc-lockdebug.h
├── objc-lockdebug.mm
├── objc-locks-new.h
├── objc-locks-old.h
├── objc-locks.h
├── objc-object.h
├── objc-opt.mm
├── objc-os.h
├── objc-os.mm
├── objc-private.h
├── objc-probes.d
├── objc-ptrauth.h
├── objc-references.h
├── objc-references.mm
├── objc-runtime-new.h
├── objc-runtime-new.mm
├── objc-runtime-old.h
├── objc-runtime-old.mm
├── objc-runtime.h
├── objc-runtime.mm
├── objc-sel-old.mm
├── objc-sel-set.h
├── objc-sel-set.mm
├── objc-sel-table.s
├── objc-sel.mm
├── objc-sync.h
├── objc-sync.mm
├── objc-typeencoding.mm
├── objc-weak.h
├── objc-weak.mm
├── objc-zalloc.h
├── objc-zalloc.mm
├── objc.h
├── objcrt.c
├── objcrt.h
└── runtime.h
├── test
├── ARCBase.h
├── ARCBase.m
├── ARCLayouts.m
├── ARCLayoutsWithoutWeak.m
├── ARCMRC.h
├── ARCMRC.m
├── MRCARC.h
├── MRCARC.m
├── MRCBase.h
├── MRCBase.m
├── accessors.m
├── accessors2.m
├── addMethod.m
├── addMethods.m
├── addProtocol.m
├── applescriptobjc.m
├── arr-cast.m
├── arr-weak.m
├── asm-placeholder.s
├── association-cf.m
├── association.m
├── associationForbidden.h
├── associationForbidden.m
├── associationForbidden2.m
├── associationForbidden3.m
├── associationForbidden4.m
├── atomicProperty.mm
├── badAltHandler.m
├── badCache.m
├── badPool.m
├── badPoolCompat-ios.m
├── badPoolCompat-macos.m
├── badPoolCompat-tvos.m
├── badPoolCompat-watchos.m
├── badSuperclass.m
├── badSuperclass2.m
├── badTagClass.m
├── badTagIndex.m
├── bigrc.m
├── blocksAsImps.m
├── bool.c
├── cacheflush-constant.m
├── cacheflush.h
├── cacheflush.m
├── cacheflush0.m
├── cacheflush2.m
├── cacheflush3.m
├── category.m
├── cdtors.mm
├── classgetclass.m
├── classname.m
├── classpair.mm
├── classversion.m
├── concurrentcat.m
├── concurrentcat_category.m
├── consolidatePoolPointers.m
├── copyFixupHandler.mm
├── copyIvarList.m
├── copyMethodList.m
├── copyPropertyList.m
├── copyProtocolList.m
├── createInstance.m
├── customrr-cat1.m
├── customrr-cat2.m
├── customrr-nsobject-awz.m
├── customrr-nsobject-core.m
├── customrr-nsobject-none.m
├── customrr-nsobject-rr.m
├── customrr-nsobject-rrawz.m
├── customrr-nsobject.m
├── customrr.m
├── customrr2.m
├── debugScanWeakTables.m
├── defines.c
├── defines.expected
├── defines.sh
├── definitions.c
├── designatedinit.m
├── duplicateClass.m
├── duplicateProtocols.m
├── duplicatedClasses.m
├── evil-class-def.m
├── exc.m
├── exchangeImp.m
├── fakeRealizedClass.m
├── fakeRealizedClass2.m
├── foreach.m
├── fork.m
├── forkInitialize.m
├── forkInitializeDisabled.m
├── forkInitializeSingleThreaded.m
├── forward.m
├── forwardDefault.m
├── forwardDefaultStret.m
├── future.h
├── future.m
├── future0.m
├── future2.m
├── gdb.m
├── getClassHook.m
├── getImageNameHook.m
├── getMethod.m
├── get_task_allow_entitlement.plist
├── headers.c
├── headers.sh
├── imageAPIs.m
├── imageorder.h
├── imageorder.m
├── imageorder1.m
├── imageorder2.m
├── imageorder3.m
├── imports.c
├── include-warnings.c
├── includes-objc2.c
├── includes.c
├── initialize.m
├── initializeVersusWeak.m
├── instanceSize.m
├── isaValidation.m
├── ismeta.m
├── ivar.m
├── ivarSlide.h
├── ivarSlide.m
├── ivarSlide1.m
├── lazyClassName.m
├── libraryPath.c
├── literals.m
├── load-image-notification-dylib.m
├── load-image-notification.m
├── load-order.m
├── load-order1.m
├── load-order2.m
├── load-order3.m
├── load-parallel.m
├── load-parallel0.m
├── load-parallel00.m
├── load-reentrant.m
├── load-reentrant2.m
├── load.m
├── methodArgs.m
├── methodCacheLeaks.m
├── methodListSize.m
├── methodListSmall.h
├── methodListSmall.mm
├── msgSend-performance.m
├── msgSend.m
├── nilAPIArgs.m
├── nonpointerisa.m
├── nopool.m
├── nscdtors.mm
├── nsexc.m
├── nsobject.m
├── nsprotocol.m
├── objectCopy.m
├── preopt-caches.entitlements
├── preopt-caches.mm
├── property.m
├── propertyDesc.m
├── protocol.m
├── protocolSmall.m
├── protocol_copyMethodList.m
├── protocol_copyPropertyList.m
├── rawisa.m
├── readClassPair.m
├── realizedClassGenerationCount.m
├── release-workaround.m
├── resolve.m
├── restartableRangesSynchronizeStress.m
├── restartableRangesSynchronizeStress2.m
├── rr-autorelease-fast.m
├── rr-autorelease-fastarc.m
├── rr-autorelease-stacklogging.m
├── rr-autorelease.m
├── rr-autorelease2.m
├── rr-nsautorelease.m
├── rr-sidetable.m
├── runtime.m
├── sel.m
├── setAssociatedObjectHook.m
├── setSuper.m
├── subscripting.m
├── super.m
├── supported-inline-refcnt.m
├── swift-class-def.m
├── swiftMetadataInitializer.m
├── swiftMetadataInitializerRealloc-dylib1.m
├── swiftMetadataInitializerRealloc-dylib2.m
├── swiftMetadataInitializerRealloc.m
├── swiftStubClassList.m
├── synchronized-counter.m
├── synchronized-grid.m
├── synchronized.m
├── taggedNSPointers.m
├── taggedPointers.m
├── taggedPointersAllClasses.m
├── taggedPointersDisabled.m
├── taggedPointersTagObfuscationDisabled.m
├── tbi.c
├── test-defines.h
├── test.h
├── test.pl
├── testroot.i
├── timeout.pl
├── unload.h
├── unload.m
├── unload2.m
├── unload3.c
├── unload4.m
├── unwind.m
├── weak.h
├── weak.m
├── weak2.m
├── weakReferenceHook.m
├── weakcopy.m
├── weakframework-missing.m
├── weakframework-not-missing.m
├── weakimport-missing.m
├── weakimport-not-missing.m
├── weakrace.m
├── willInitializeClassFunc.m
└── zone.m
├── unexported_symbols
├── version.bat
└── version.rc
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 | .DS_Store
9 |
10 | ## Various settings
11 | *.pbxuser
12 | !default.pbxuser
13 | *.mode1v3
14 | !default.mode1v3
15 | *.mode2v3
16 | !default.mode2v3
17 | *.perspectivev3
18 | !default.perspectivev3
19 | xcuserdata/
20 |
21 | ## Other
22 | *.moved-aside
23 | *.xccheckout
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 | *.dSYM.zip
30 | *.dSYM
31 |
32 | # CocoaPods
33 | #
34 | # We recommend against adding the Pods directory to your .gitignore. However
35 | # you should judge for yourself, the pros and cons are mentioned at:
36 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
37 | #
38 | # Pods/
39 |
40 | # Carthage
41 | #
42 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
43 | # Carthage/Checkouts
44 |
45 | Carthage/Build
46 |
47 | # fastlane
48 | #
49 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
50 | # screenshots whenever they are needed.
51 | # For more information about the recommended setup visit:
52 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
53 |
54 | fastlane/report.xml
55 | fastlane/Preview.html
56 | fastlane/screenshots
57 | fastlane/test_output
58 |
59 | # Code Injection
60 | #
61 | # After new code Injection tools there's a generated folder /iOSInjectionProject
62 | # https://github.com/johnno1962/injectionforxcode
63 |
64 | iOSInjectionProject/
65 |
66 | #Visual Studio Code
67 |
68 | .vscode
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2022
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 可调试的、基于M1芯片、macOS 12系统的objc4.
2 |
3 |
4 | 
5 | [](https://gitter.im/0xxd0/objc4?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6 | 
7 |
8 | - [Version](#Version)
9 | - [Installation](#Installation)
10 | - [Usage](#Usage)
11 | - [License](#license)
12 |
13 |
14 | ## **Version**
15 |
16 | | macOS | macOS Version | Xcode Version | objc4 tarball version |
17 | | - | - | - | - |
18 | | macOS Monterey | 12.0.1 | 13.2 (13C90) | objc4-838 |
19 |
20 | ## **Installation**
21 |
22 | Download zip or clone this repo, select **objc_debug** 、 **My Mac** and build.
23 |
24 |
25 | ## **Usage**
26 |
27 | 手动把编译产物`libobjc.A.dylib`加入到你的工程,或者直接在`objc_debug`的main文件打断点调试。
28 | 如果没有办法在main函数打断点,可以尝试写个类,提供一个方法,方法里面设置断点,在main函数里调用这个方法。
29 |
30 |
31 | ## License
32 | This project is released under the **MIT License**. The objc4 project is released under the **APPLE PUBLIC SOURCE LICENSE Version 2.0**.
33 |
--------------------------------------------------------------------------------
/include/CrashReporterClient.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Apple Inc. All rights reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /***********************************************************************
25 | * Not to be installed in /usr/local/include
26 | ***********************************************************************/
27 | //Libc-825.40.1/include/CrashReporterClient.h
28 | #ifndef _LIBC_CRASHREPORTERCLIENT_H
29 | #define _LIBC_CRASHREPORTERCLIENT_H
30 |
31 | #ifdef LIBC_NO_LIBCRASHREPORTERCLIENT
32 |
33 | /* Fake the CrashReporterClient API */
34 | #define CRGetCrashLogMessage() 0
35 | #define CRSetCrashLogMessage(x) /* nothing */
36 |
37 | #else /* !LIBC_NO_LIBCRASHREPORTERCLIENT */
38 |
39 | /* Include the real CrashReporterClient.h */
40 | #include_next
41 |
42 | #endif /* !LIBC_NO_LIBCRASHREPORTERCLIENT */
43 |
44 | #endif /* _LIBC_CRASHREPORTERCLIENT_H */
45 |
--------------------------------------------------------------------------------
/include/System/machine/cpu_capabilities.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 | *
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. The rights granted to you under the License
10 | * may not be used to create, or enable the creation or redistribution of,
11 | * unlawful or unlicensed copies of an Apple operating system, or to
12 | * circumvent, violate, or enable the circumvention or violation of, any
13 | * terms of an Apple operating system software license agreement.
14 | *
15 | * Please obtain a copy of the License at
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 | *
18 | * The Original Code and all software distributed under the License are
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 | * Please see the License for the specific language governing rights and
24 | * limitations under the License.
25 | *
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 | */
28 | ///11.5-xnu-xnu-7195.141.2/osfmk/machine/cpu_capabilities.h
29 | #ifdef PRIVATE
30 |
31 | #ifndef _MACHINE_CPU_CAPABILITIES_H
32 | #define _MACHINE_CPU_CAPABILITIES_H
33 |
34 | #ifdef KERNEL_PRIVATE
35 | #if defined (__i386__) || defined (__x86_64__)
36 | #include "i386/cpu_capabilities.h"
37 | #elif defined (__arm__) || defined (__arm64__)
38 | #include "arm/cpu_capabilities.h"
39 | #else
40 | #error architecture not supported
41 | #endif
42 |
43 | #else /* !KERNEL_PRIVATE -- System Framework header */
44 | #if defined (__i386__) || defined(__x86_64__)
45 | #include
46 | #elif defined (__arm__) || defined(__arm64__)
47 | #include
48 | #else
49 | #error architecture not supported
50 | #endif
51 | #endif /* KERNEL_PRIVATE */
52 |
53 | #endif /* _MACHINE_CPU_CAPABILITIES_H */
54 | #endif /* PRIVATE */
55 |
--------------------------------------------------------------------------------
/include/os/base_private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
3 | *
4 | * @APPLE_APACHE_LICENSE_HEADER_START@
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | *
18 | * @APPLE_APACHE_LICENSE_HEADER_END@
19 | */
20 |
21 | /// 11.5-xnu-xnu-7195.141.2/libkern/os/base_private.h
22 | #ifndef __OS_BASE_PRIVATE__
23 | #define __OS_BASE_PRIVATE__
24 |
25 | #ifndef KERNEL
26 | #include
27 | #endif
28 | #include
29 |
30 | #ifndef os_fastpath
31 | #define os_fastpath(x) ((__typeof__(x))OS_EXPECT((long)(x), ~0l))
32 | #endif
33 | #ifndef os_slowpath
34 | #define os_slowpath(x) ((__typeof__(x))OS_EXPECT((long)(x), 0l))
35 | #endif
36 | #ifndef os_likely
37 | #define os_likely(x) OS_EXPECT(!!(x), 1)
38 | #endif
39 | #ifndef os_unlikely
40 | #define os_unlikely(x) OS_EXPECT(!!(x), 0)
41 | #endif
42 |
43 |
44 | #endif // __OS_BASE_PRIVATE__
45 |
--------------------------------------------------------------------------------
/include/os/reason_private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017 Apple Inc. All rights reserved.
3 | *
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. The rights granted to you under the License
10 | * may not be used to create, or enable the creation or redistribution of,
11 | * unlawful or unlicensed copies of an Apple operating system, or to
12 | * circumvent, violate, or enable the circumvention or violation of, any
13 | * terms of an Apple operating system software license agreement.
14 | *
15 | * Please obtain a copy of the License at
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 | *
18 | * The Original Code and all software distributed under the License are
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 | * Please see the License for the specific language governing rights and
24 | * limitations under the License.
25 | *
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 | */
28 | //11.5-xnu-xnu-7195.141.2/libkern/os/reason_private.h
29 | #ifndef OS_REASON_PRIVATE_H
30 | #define OS_REASON_PRIVATE_H
31 |
32 | #include
33 | #include
34 |
35 | /* Codes in the OS_REASON_LIBSYSTEM namespace */
36 |
37 | OS_ENUM(os_reason_libsystem_code, uint64_t,
38 | OS_REASON_LIBSYSTEM_CODE_WORKLOOP_OWNERSHIP_LEAK = 1,
39 | OS_REASON_LIBSYSTEM_CODE_FAULT = 2, /* generated by os_log_fault */
40 | OS_REASON_LIBSYSTEM_CODE_SECINIT_INITIALIZER = 3,
41 | OS_REASON_LIBSYSTEM_CODE_PTHREAD_CORRUPTION = 4,
42 | );
43 |
44 | #ifndef KERNEL
45 |
46 | /*
47 | * similar to abort_with_payload, but for faults.
48 | *
49 | * [EBUSY] too many corpses are being generated at the moment
50 | * [EQFULL] the process used all its user fault quota
51 | * [ENOTSUP] generating simulated abort with reason is disabled
52 | * [EPERM] generating simulated abort with reason for this namespace is not turned on
53 | */
54 | int
55 | os_fault_with_payload(uint32_t reason_namespace, uint64_t reason_code,
56 | void *payload, uint32_t payload_size, const char *reason_string,
57 | uint64_t reason_flags) __attribute__((cold));
58 |
59 | #endif // !KERNEL
60 |
61 | #endif // OS_REASON_PRIVATE_H
62 |
--------------------------------------------------------------------------------
/interposable.txt:
--------------------------------------------------------------------------------
1 | _objc_release
2 |
--------------------------------------------------------------------------------
/lastGitStatus:
--------------------------------------------------------------------------------
1 | On branch main
2 | Your branch is up to date with 'origin/main'.
3 |
4 | Changes to be committed:
5 | (use "git restore --staged ..." to unstage)
6 | new file: LICENSE
7 | new file: README.md
8 | new file: include/Block_private.h
9 | new file: include/CrashReporterClient.h
10 | new file: include/System/machine/cpu_capabilities.h
11 | new file: include/System/pthread_machdep.h
12 | new file: include/_simple.h
13 | new file: include/kern/restartable.h
14 | new file: include/mach-o/dyld_priv.h
15 | new file: include/objc-shared-cache.h
16 | new file: include/os/base_private.h
17 | new file: include/os/linker_set.h
18 | new file: include/os/lock_private.h
19 | new file: include/os/reason_private.h
20 | new file: include/os/tsd.h
21 | new file: include/os/variant_private.h
22 | new file: include/pthread/spinlock_private.h
23 | new file: include/pthread/tsd_private.h
24 | new file: include/sys/reason.h
25 | new file: objc_debug/main.m
26 |
27 | Changes not staged for commit:
28 | (use "git add/rm ..." to update what will be committed)
29 | (use "git restore ..." to discard changes in working directory)
30 | deleted: LICENSE
31 | deleted: README.md
32 | modified: include/Block_private.h
33 | modified: include/CrashReporterClient.h
34 | modified: include/System/machine/cpu_capabilities.h
35 | modified: include/System/pthread_machdep.h
36 | modified: include/_simple.h
37 | modified: include/kern/restartable.h
38 | modified: include/mach-o/dyld_priv.h
39 | modified: include/objc-shared-cache.h
40 | modified: include/os/linker_set.h
41 | modified: include/os/lock_private.h
42 | modified: include/os/reason_private.h
43 | modified: include/os/tsd.h
44 | modified: include/os/variant_private.h
45 | modified: include/pthread/spinlock_private.h
46 | modified: include/pthread/tsd_private.h
47 | modified: include/sys/reason.h
48 | modified: objc.xcodeproj/project.pbxproj
49 | modified: objc_debug/main.m
50 | modified: runtime/NSObject.mm
51 | modified: runtime/objc-cache.mm
52 | modified: runtime/objc-opt.mm
53 | modified: runtime/objc-os.mm
54 | modified: runtime/objc-runtime-new.mm
55 | modified: runtime/objc-runtime.mm
56 |
57 | Untracked files:
58 | (use "git add ..." to include in what will be committed)
59 | .DS_Store
60 | include/.DS_Store
61 | lastGitDiff
62 | lastGitStatus
63 | objc.xcodeproj/project.xcworkspace/
64 | objc.xcodeproj/xcuserdata/
65 |
66 |
--------------------------------------------------------------------------------
/objc.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 9.00
3 | # Visual C++ Express 2005
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "objc", "objc.vcproj", "{B3408263-0CF1-47BE-83CC-56070EFC9BC1}"
5 | EndProject
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "objcrt", "objcrt\objcrt.vcproj", "{E38C1996-8B3D-4050-A4B2-DC85957B047D}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1} = {B3408263-0CF1-47BE-83CC-56070EFC9BC1}
9 | EndProjectSection
10 | EndProject
11 | Global
12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
13 | Debug|Win32 = Debug|Win32
14 | DebugDLL|Win32 = DebugDLL|Win32
15 | Release|Win32 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Debug|Win32.ActiveCfg = Debug|Win32
19 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Debug|Win32.Build.0 = Debug|Win32
20 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
21 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
22 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Release|Win32.ActiveCfg = Release|Win32
23 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Release|Win32.Build.0 = Release|Win32
24 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Debug|Win32.ActiveCfg = Debug|Win32
25 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Debug|Win32.Build.0 = Debug|Win32
26 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.DebugDLL|Win32.ActiveCfg = Debug|Win32
27 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.DebugDLL|Win32.Build.0 = Debug|Win32
28 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Release|Win32.ActiveCfg = Release|Win32
29 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Release|Win32.Build.0 = Release|Win32
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/objc.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/objc.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/objc4.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | preoptimizedCaches
6 |
7 | Enabled
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/objc_debug/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // objc_debug
4 | //
5 | // Created by 单晓辉 on 2022/2/14.
6 | //
7 |
8 | #import
9 |
10 | int main(int argc, const char * argv[]) {
11 | @autoreleasepool {
12 | // insert code here...
13 | NSLog(@"You can start debugging objc here\n");
14 | NSLog(@"你可以开始debug objc了\n");
15 | }
16 | return 0;
17 | }
18 |
--------------------------------------------------------------------------------
/objcdt/json.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_OBJCDT_JSON_H_
25 | #define _OBJC_OBJCDT_JSON_H_
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | namespace json {
33 |
34 | enum context: uint8_t {
35 | root,
36 | array_value,
37 | object_value,
38 | object_key,
39 | done,
40 | };
41 |
42 | class writer {
43 | private:
44 | FILE *_file;
45 | context _context;
46 | int _depth;
47 | bool _needs_comma;
48 |
49 | void begin_value(int sep = '\0');
50 | void advance(context old);
51 | void key(const char *key);
52 |
53 | public:
54 |
55 | writer(FILE *f);
56 | ~writer();
57 |
58 | void object(std::function);
59 | void object(const char *key, std::function);
60 |
61 | void array(std::function);
62 | void array(const char *key, std::function);
63 |
64 | void boolean(bool value);
65 | void boolean(const char *key, bool value);
66 |
67 | void number(uint64_t value);
68 | void number(const char *key, uint64_t value);
69 |
70 | void string(const char *s);
71 | void string(const char *key, const char *s);
72 |
73 | __printflike(2, 3)
74 | void stringf(const char *fmt, ...);
75 |
76 | __printflike(3, 4)
77 | void stringf(const char *key, const char *fmt, ...);
78 | };
79 |
80 | }
81 |
82 | #endif /* _OBJC_OBJCDT_JSON_H_ */
83 |
--------------------------------------------------------------------------------
/objcdt/objcdt-entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | task_for_pid-allow
6 |
7 | com.apple.system-task-ports
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/objcdt/objcdt.1:
--------------------------------------------------------------------------------
1 | .\" Copyright (c) 2019, Apple Computer, Inc. All rights reserved.
2 | .\"
3 | .Dd September 9, 2019 \" DATE
4 | .Dt objcdt 1 \" Program name and manual section number
5 | .Os "OS X"
6 | .Sh NAME
7 | .Nm objcdt
8 | .Nd Tool to debug objective-C usage in live processes
9 | .Sh SYNOPSIS
10 | .Nm objcdt
11 | .Sh DESCRIPTION
12 | The
13 | .Nm
14 | utility is a small CLI with embedded help that can dump some information about
15 | the Objective-C runtime state in live processes.
16 | .Pp
17 | Help can be obtained using
18 | .Nm
19 | .Ar help
20 |
--------------------------------------------------------------------------------
/objcdt/objcdt.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #include "objc-private.h"
25 | #include "objc-ptrauth.h"
26 | #include "NSObject-private.h"
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | int main(int argc, const char *argv[])
35 | {
36 | return EX_UNAVAILABLE;
37 | }
38 |
--------------------------------------------------------------------------------
/prebuild.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | echo prebuild: installing headers
4 | xcopy /Y "%ProjectDir%runtime\objc.h" "%DSTROOT%\AppleInternal\include\objc\"
5 | xcopy /Y "%ProjectDir%runtime\objc-api.h" "%DSTROOT%\AppleInternal\include\objc\"
6 | xcopy /Y "%ProjectDir%runtime\objc-auto.h" "%DSTROOT%\AppleInternal\include\objc\"
7 | xcopy /Y "%ProjectDir%runtime\objc-exception.h" "%DSTROOT%\AppleInternal\include\objc\"
8 | xcopy /Y "%ProjectDir%runtime\message.h" "%DSTROOT%\AppleInternal\include\objc\"
9 | xcopy /Y "%ProjectDir%runtime\runtime.h" "%DSTROOT%\AppleInternal\include\objc\"
10 | xcopy /Y "%ProjectDir%runtime\hashtable.h" "%DSTROOT%\AppleInternal\include\objc\"
11 | xcopy /Y "%ProjectDir%runtime\hashtable2.h" "%DSTROOT%\AppleInternal\include\objc\"
12 | xcopy /Y "%ProjectDir%runtime\maptable.h" "%DSTROOT%\AppleInternal\include\objc\"
13 |
14 | echo prebuild: setting version
15 | version
16 |
--------------------------------------------------------------------------------
/runtime/Module/module.modulemap:
--------------------------------------------------------------------------------
1 | module ObjectiveC [system] [extern_c] {
2 | umbrella "."
3 | export *
4 | module * {
5 | export *
6 | }
7 |
8 | module NSObject {
9 | requires objc
10 | header "NSObject.h"
11 | export *
12 | }
13 |
14 | #if defined(BUILD_FOR_OSX)
15 | module List {
16 | // Uses @defs, which does not work in ObjC++ or non-ARC.
17 | requires objc, !objc_arc, !cplusplus
18 | header "List.h"
19 | export *
20 | }
21 |
22 | module Object {
23 | requires objc
24 | header "Object.h"
25 | export *
26 | }
27 |
28 | module Protocol {
29 | requires objc
30 | header "Protocol.h"
31 | export *
32 | }
33 | #endif
34 |
35 | #if !defined(BUILD_FOR_OSX)
36 | // These file are not available outside macOS.
37 | exclude header "hashtable.h"
38 | exclude header "hashtable2.h"
39 | #endif
40 | }
41 |
--------------------------------------------------------------------------------
/runtime/ModulePrivate/module.modulemap:
--------------------------------------------------------------------------------
1 | module ObjectiveC_Private [system] {
2 | umbrella "."
3 | explicit module * { export * }
4 | }
5 |
--------------------------------------------------------------------------------
/runtime/NSObjCRuntime.h:
--------------------------------------------------------------------------------
1 | /* NSObjCRuntime.h
2 | Copyright (c) 1994-2012, Apple Inc. All rights reserved.
3 | */
4 |
5 | #ifndef _OBJC_NSOBJCRUNTIME_H_
6 | #define _OBJC_NSOBJCRUNTIME_H_
7 |
8 | #include
9 | #include
10 |
11 | #if __LP64__ || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
12 | typedef long NSInteger;
13 | typedef unsigned long NSUInteger;
14 | #else
15 | typedef int NSInteger;
16 | typedef unsigned int NSUInteger;
17 | #endif
18 |
19 | #define NSIntegerMax LONG_MAX
20 | #define NSIntegerMin LONG_MIN
21 | #define NSUIntegerMax ULONG_MAX
22 |
23 | #define NSINTEGER_DEFINED 1
24 |
25 | #ifndef NS_DESIGNATED_INITIALIZER
26 | #if __has_attribute(objc_designated_initializer)
27 | #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
28 | #else
29 | #define NS_DESIGNATED_INITIALIZER
30 | #endif
31 | #endif
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/runtime/NSObject-private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010-2021 Apple Inc. All rights reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _NSOBJECT_PRIVATE_H
25 | #define _NSOBJECT_PRIVATE_H
26 |
27 | #include "objc-private.h"
28 | #include "objc-weak.h"
29 | #include "DenseMapExtras.h"
30 |
31 | namespace {
32 |
33 | struct RefcountMapValuePurgeable {
34 | static inline bool isPurgeable(size_t x) {
35 | return x == 0;
36 | }
37 | };
38 |
39 | // RefcountMap disguises its pointers because we
40 | // don't want the table to act as a root for `leaks`.
41 | typedef objc::DenseMap,size_t,RefcountMapValuePurgeable> RefcountMap;
42 |
43 | // Template parameters.
44 | enum HaveOld { DontHaveOld = false, DoHaveOld = true };
45 | enum HaveNew { DontHaveNew = false, DoHaveNew = true };
46 |
47 | struct SideTable {
48 | spinlock_t slock;
49 | RefcountMap refcnts;
50 | weak_table_t weak_table;
51 |
52 | SideTable() {
53 | memset(&weak_table, 0, sizeof(weak_table));
54 | }
55 |
56 | ~SideTable() {
57 | _objc_fatal("Do not delete SideTable.");
58 | }
59 |
60 | void lock() { slock.lock(); }
61 | void unlock() { slock.unlock(); }
62 | void forceReset() { slock.forceReset(); }
63 |
64 | // Address-ordered lock discipline for a pair of side tables.
65 |
66 | template
67 | static void lockTwo(SideTable *lock1, SideTable *lock2);
68 | template
69 | static void unlockTwo(SideTable *lock1, SideTable *lock2);
70 | };
71 |
72 | }
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/runtime/Protocol.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2003, 2006-2007 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 | /*
24 | Protocol.h
25 | Copyright 1991-1996 NeXT Software, Inc.
26 | */
27 |
28 | #ifndef _OBJC_PROTOCOL_H_
29 | #define _OBJC_PROTOCOL_H_
30 |
31 | #if !__OBJC__
32 |
33 | // typedef Protocol is here:
34 | #include
35 |
36 |
37 | #elif __OBJC2__
38 |
39 | #include
40 |
41 | // All methods of class Protocol are unavailable.
42 | // Use the functions in objc/runtime.h instead.
43 |
44 | OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
45 | @interface Protocol : NSObject
46 | @end
47 |
48 | #endif
49 |
50 | #endif /* _OBJC_PROTOCOL_H_ */
51 |
--------------------------------------------------------------------------------
/runtime/hashtable.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
--------------------------------------------------------------------------------
/runtime/objc-block-trampolines.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 |
25 | #ifndef _OBJC_TRAMPOLINES_H
26 | #define _OBJC_TRAMPOLINES_H
27 |
28 | /*
29 | * WARNING DANGER HAZARD BEWARE EEK
30 | *
31 | * Everything in this file is for Apple Internal use only.
32 | * These will change in arbitrary OS updates and in unpredictable ways.
33 | * When your program breaks, you get to keep both pieces.
34 | */
35 |
36 | /*
37 | * objc-block-trampolines.h: Symbols for IMP block trampolines
38 | */
39 |
40 | // WARNING: remapped code and dtrace do not play well together. Dtrace
41 | // will place trap instructions to instrument the code, which then get
42 | // remapped along with everything else. The remapped traps are not
43 | // recognized by dtrace and the process crashes. To avoid this, dtrace
44 | // blacklists this library by name. Do not change the name of this
45 | // library. rdar://problem/42627391
46 |
47 | #include
48 |
49 | OBJC_EXPORT const char _objc_blockTrampolineImpl
50 | OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
51 |
52 | OBJC_EXPORT const char _objc_blockTrampolineStart
53 | OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
54 |
55 | OBJC_EXPORT const char _objc_blockTrampolineLast
56 | OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
57 |
58 |
59 | OBJC_EXPORT const char _objc_blockTrampolineImpl_stret
60 | OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0)
61 | OBJC_ARM64_UNAVAILABLE;
62 |
63 | OBJC_EXPORT const char _objc_blockTrampolineStart_stret
64 | OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0)
65 | OBJC_ARM64_UNAVAILABLE;
66 |
67 | OBJC_EXPORT const char _objc_blockTrampolineLast_stret
68 | OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0)
69 | OBJC_ARM64_UNAVAILABLE;
70 |
71 | #endif
72 |
--------------------------------------------------------------------------------
/runtime/objc-cache-old.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_CACHE_OLD_H
25 | #define _OBJC_CACHE_OLD_H
26 |
27 | #include "objc-private.h"
28 |
29 | __BEGIN_DECLS
30 |
31 | extern IMP _cache_getImp(Class cls, SEL sel);
32 | extern Method _cache_getMethod(Class cls, SEL sel, IMP objc_msgForward_internal_imp);
33 |
34 | extern void cache_init(void);
35 | extern void flush_cache(Class cls);
36 | extern bool _cache_fill(Class cls, Method meth, SEL sel);
37 | extern void _cache_addForwardEntry(Class cls, SEL sel);
38 | extern IMP _cache_addIgnoredEntry(Class cls, SEL sel);
39 | extern void _cache_free(Cache cache);
40 | extern void _cache_collect(bool collectALot);
41 |
42 | __END_DECLS
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/runtime/objc-class.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
--------------------------------------------------------------------------------
/runtime/objc-file-old.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_FILE_OLD_H
25 | #define _OBJC_FILE_OLD_H
26 |
27 | #if !__OBJC2__
28 |
29 | #include "objc-os.h"
30 |
31 | struct objc_module;
32 | struct old_protocol;
33 | struct old_class;
34 |
35 | __BEGIN_DECLS
36 |
37 | extern struct objc_module *_getObjcModules(const header_info *hi, size_t *nmodules);
38 | extern SEL *_getObjcSelectorRefs(const header_info *hi, size_t *nmess);
39 | extern struct old_protocol **_getObjcProtocols(const header_info *hi, size_t *nprotos);
40 | extern Class *_getObjcClassRefs(const header_info *hi, size_t *nclasses);
41 | extern const char *_getObjcClassNames(const header_info *hi, size_t *size);
42 |
43 | using UnsignedInitializer = void(*)(void);
44 | extern UnsignedInitializer* getLibobjcInitializers(const headerType *mhdr, size_t *count);
45 |
46 | __END_DECLS
47 |
48 | #endif
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/runtime/objc-initialize.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2005-2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_INITIALIZE_H
25 | #define _OBJC_INITIALIZE_H
26 |
27 | #include "objc-private.h"
28 |
29 | __BEGIN_DECLS
30 |
31 | struct _objc_initializing_classes;
32 |
33 | extern void initializeNonMetaClass(Class cls);
34 |
35 | extern void _destroyInitializingClassList(struct _objc_initializing_classes *list);
36 |
37 | extern bool _thisThreadIsInitializingClass(Class cls);
38 |
39 | __END_DECLS
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/runtime/objc-load.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2001, 2005-2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 | /*
24 | * objc-load.h
25 | * Copyright 1988-1996, NeXT Software, Inc.
26 | */
27 |
28 | #ifndef _OBJC_LOAD_H_
29 | #define _OBJC_LOAD_H_
30 |
31 | #include
32 |
33 | #include
34 |
35 | // This file intentionally left blank.
36 |
37 | #endif /* _OBJC_LOAD_H_ */
38 |
--------------------------------------------------------------------------------
/runtime/objc-loadmethod.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /***********************************************************************
25 | * objc-loadmethod.h
26 | * Support for +load methods.
27 | **********************************************************************/
28 |
29 | #ifndef _OBJC_LOADMETHOD_H
30 | #define _OBJC_LOADMETHOD_H
31 |
32 | #include "objc-private.h"
33 |
34 | __BEGIN_DECLS
35 |
36 | extern void add_class_to_loadable_list(Class cls);
37 | extern void add_category_to_loadable_list(Category cat);
38 | extern void remove_class_from_loadable_list(Class cls);
39 | extern void remove_category_from_loadable_list(Category cat);
40 |
41 | extern void call_load_methods(void);
42 |
43 | __END_DECLS
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/runtime/objc-locks-new.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /***********************************************************************
25 | * objc-locks-new.h
26 | * Declarations of all locks used in the runtime.
27 | **********************************************************************/
28 |
29 | #ifndef _OBJC_LOCKS_NEW_H
30 | #define _OBJC_LOCKS_NEW_H
31 |
32 | // fork() safety requires careful tracking of all locks used in the runtime.
33 | // Thou shalt not declare any locks outside this file.
34 |
35 | extern mutex_t runtimeLock;
36 | extern mutex_t DemangleCacheLock;
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/runtime/objc-locks-old.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /***********************************************************************
25 | * objc-locks-old.h
26 | * Declarations of all locks used in the runtime.
27 | **********************************************************************/
28 |
29 | #ifndef _OBJC_LOCKS_OLD_H
30 | #define _OBJC_LOCKS_OLD_H
31 |
32 | // fork() safety requires careful tracking of all locks used in the runtime.
33 | // Thou shalt not declare any locks outside this file.
34 |
35 | extern mutex_t classLock;
36 | extern mutex_t methodListLock;
37 | extern mutex_t NXUniqueStringLock;
38 | extern spinlock_t impLock;
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/runtime/objc-locks.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /***********************************************************************
25 | * objc-locks.h
26 | * Declarations of all locks used in the runtime.
27 | **********************************************************************/
28 |
29 | #ifndef _OBJC_LOCKS_H
30 | #define _OBJC_LOCKS_H
31 |
32 | // fork() safety requires careful tracking of all locks used in the runtime.
33 | // Thou shalt not declare any locks outside this file.
34 |
35 | // Lock ordering is declared in _objc_fork_prepare()
36 | // and is enforced by lockdebug.
37 |
38 | extern monitor_t classInitLock;
39 | extern mutex_t selLock;
40 | #if CONFIG_USE_CACHE_LOCK
41 | extern mutex_t cacheUpdateLock;
42 | #endif
43 | extern recursive_mutex_t loadMethodLock;
44 | extern mutex_t crashlog_lock;
45 | extern spinlock_t objcMsgLogLock;
46 | extern mutex_t AltHandlerDebugLock;
47 | extern mutex_t AssociationsManagerLock;
48 | extern StripedMap PropertyLocks;
49 | extern StripedMap StructLocks;
50 | extern StripedMap CppObjectLocks;
51 |
52 | // SideTable lock is buried awkwardly. Call a function to manipulate it.
53 | extern void SideTableLockAll();
54 | extern void SideTableUnlockAll();
55 | extern void SideTableForceResetAll();
56 | extern void SideTableDefineLockOrder();
57 | extern void SideTableLocksPrecedeLock(const void *newlock);
58 | extern void SideTableLocksSucceedLock(const void *oldlock);
59 | extern void SideTableLocksPrecedeLocks(StripedMap& newlocks);
60 | extern void SideTableLocksSucceedLocks(StripedMap& oldlocks);
61 |
62 | #if __OBJC2__
63 | #include "objc-locks-new.h"
64 | #else
65 | #include "objc-locks-old.h"
66 | #endif
67 |
68 | #endif
69 |
--------------------------------------------------------------------------------
/runtime/objc-probes.d:
--------------------------------------------------------------------------------
1 | provider objc_runtime
2 | {
3 | probe objc_exception_throw(void *id);
4 | probe objc_exception_rethrow();
5 | };
6 |
--------------------------------------------------------------------------------
/runtime/objc-references.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2008 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 | /*
24 | * objc-references.h
25 | */
26 |
27 | #ifndef _OBJC_REFERENCES_H_
28 | #define _OBJC_REFERENCES_H_
29 |
30 | #include "objc-api.h"
31 | #include "objc-config.h"
32 |
33 | __BEGIN_DECLS
34 |
35 | extern void _objc_associations_init();
36 | extern void _object_set_associative_reference(id object, const void *key, id value, uintptr_t policy);
37 | extern id _object_get_associative_reference(id object, const void *key);
38 | extern void _object_remove_assocations(id object, bool deallocating);
39 |
40 | __END_DECLS
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/runtime/objc-runtime.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
--------------------------------------------------------------------------------
/runtime/objc-sel-set.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004 Apple Inc. All rights reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /*
25 | * objc-sel-set.h
26 | * A set of SELs used for SEL uniquing.
27 | */
28 |
29 | #ifndef _OBJC_SEL_SET_H_
30 | #define _OBJC_SEL_SET_H_
31 |
32 | #if !__OBJC2__
33 |
34 | #include
35 | #include "objc-os.h"
36 |
37 | __BEGIN_DECLS
38 |
39 | struct __objc_sel_set;
40 |
41 | extern struct __objc_sel_set *__objc_sel_set_create(size_t selrefCount);
42 | extern SEL __objc_sel_set_get(struct __objc_sel_set *sset, SEL candidate);
43 | extern void __objc_sel_set_add(struct __objc_sel_set *sset, SEL value);
44 |
45 | __END_DECLS
46 |
47 | #endif
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/runtime/objc-sel-table.s:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #if __LP64__
5 | #if __arm64e__
6 | // 0x6AE1
7 | # define PTR(x) .quad x@AUTH(da, 27361, addr)
8 | #else
9 | # define PTR(x) .quad x
10 | #endif
11 | #else
12 | # define PTR(x) .long x
13 | #endif
14 |
15 | // These offsets are populated by the dyld shared cache builder.
16 | // They point to memory allocatd elsewhere in the shared cache.
17 |
18 | .section __TEXT,__objc_opt_ro
19 | .align 3
20 | .private_extern __objc_opt_data
21 | __objc_opt_data:
22 | .long 16 /* table.version */
23 | .long 0 /* table.flags */
24 | .long 0 /* table.selopt_offset */
25 | .long 0 /* table.headeropt_ro_offset */
26 | .long 0 /* table.clsopt_offset */
27 | .long 0 /* table.protocolopt_offset */
28 | .long 0 /* table.headeropt_rw_offset */
29 | .long 0 /* table.unused_protocolopt2_offset */
30 | .long 0 /* table.largeSharedCachesClassOffset */
31 | .long 0 /* table.largeSharedCachesProtocolOffset */
32 | .space PAGE_MAX_SIZE-40
33 |
34 |
35 | /* section of pointers that the shared cache optimizer wants to know about */
36 | .section __DATA,__objc_opt_ptrs
37 | .align 3
38 |
39 | #if TARGET_OS_OSX && __i386__
40 | // old ABI
41 | .globl .objc_class_name_Protocol
42 | PTR(.objc_class_name_Protocol)
43 | #else
44 | // new ABI
45 | .globl _OBJC_CLASS_$_Protocol
46 | PTR(_OBJC_CLASS_$_Protocol)
47 | #endif
48 |
--------------------------------------------------------------------------------
/runtime/objc-sync.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002, 2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef __OBJC_SNYC_H_
25 | #define __OBJC_SNYC_H_
26 |
27 | #include
28 |
29 |
30 | /**
31 | * Begin synchronizing on 'obj'.
32 | * Allocates recursive pthread_mutex associated with 'obj' if needed.
33 | *
34 | * @param obj The object to begin synchronizing on.
35 | *
36 | * @return OBJC_SYNC_SUCCESS once lock is acquired.
37 | */
38 | OBJC_EXPORT int
39 | objc_sync_enter(id _Nonnull obj)
40 | OBJC_AVAILABLE(10.3, 2.0, 9.0, 1.0, 2.0);
41 |
42 | /**
43 | * End synchronizing on 'obj'.
44 | *
45 | * @param obj The object to end synchronizing on.
46 | *
47 | * @return OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
48 | */
49 | OBJC_EXPORT int
50 | objc_sync_exit(id _Nonnull obj)
51 | OBJC_AVAILABLE(10.3, 2.0, 9.0, 1.0, 2.0);
52 |
53 | enum {
54 | OBJC_SYNC_SUCCESS = 0,
55 | OBJC_SYNC_NOT_OWNING_THREAD_ERROR = -1
56 | };
57 |
58 |
59 | #endif // __OBJC_SYNC_H_
60 |
--------------------------------------------------------------------------------
/runtime/objcrt.h:
--------------------------------------------------------------------------------
1 | #ifndef _OBJC_RT_H_
2 | #define _OBJC_RT_H_
3 |
4 | #include
5 |
6 |
7 | typedef struct {
8 | int count; // number of pointer pairs that follow
9 | void *modStart;
10 | void *modEnd;
11 | void *protoStart;
12 | void *protoEnd;
13 | void *iiStart;
14 | void *iiEnd;
15 | void *selrefsStart;
16 | void *selrefsEnd;
17 | void *clsrefsStart;
18 | void *clsrefsEnd;
19 | } objc_sections;
20 |
21 | OBJC_EXPORT void *_objc_init_image(HMODULE image, const objc_sections *sects);
22 | OBJC_EXPORT void _objc_load_image(HMODULE image, void *hinfo);
23 | OBJC_EXPORT void _objc_unload_image(HMODULE image, void *hinfo);
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/test/ARCBase.h:
--------------------------------------------------------------------------------
1 | //
2 | // ARCBase.h
3 | // TestARCLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ARCMisalign : NSObject {
12 | char misalign1;
13 | }
14 | @end
15 |
16 | @interface ARCBase : ARCMisalign
17 | @property long number;
18 | @property(retain) id object;
19 | @property void *pointer;
20 | @property(weak) __weak id delegate;
21 | @end
22 |
--------------------------------------------------------------------------------
/test/ARCBase.m:
--------------------------------------------------------------------------------
1 | //
2 | // ARCBase.m
3 | // TestARCLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "ARCBase.h"
10 |
11 | // ARCMisalign->misalign1 and ARCBase->misalign2 together cause
12 | // ARCBase's instanceStart to be misaligned, which exercises handling
13 | // of storage that is not represented in the class's ivar layout bitmaps.
14 |
15 | @implementation ARCMisalign
16 | @end
17 |
18 | @interface ARCBase () {
19 | @private
20 | char misalign2;
21 | long number;
22 | id object;
23 | void *pointer;
24 | __weak id delegate;
25 | }
26 | @end
27 |
28 | @implementation ARCBase
29 | @synthesize number, object, pointer, delegate;
30 | @end
31 |
--------------------------------------------------------------------------------
/test/ARCLayoutsWithoutWeak.m:
--------------------------------------------------------------------------------
1 | // Same as test ARCLayouts but with MRC __weak support disabled.
2 | /*
3 | TEST_CONFIG MEM=arc
4 | TEST_BUILD
5 | mkdir -p $T{OBJDIR}
6 | $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRCBase.m -o $T{OBJDIR}/MRCBase.o -fno-objc-weak
7 | $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRCARC.m -o $T{OBJDIR}/MRCARC.o -fno-objc-weak
8 | $C{COMPILE_NOLINK} -c $DIR/ARCBase.m -o $T{OBJDIR}/ARCBase.o
9 | $C{COMPILE_NOLINK} -c $DIR/ARCMRC.m -o $T{OBJDIR}/ARCMRC.o
10 | $C{COMPILE} '-DNAME=\"ARCLayoutsWithoutWeak.m\"' -fobjc-arc $DIR/ARCLayouts.m -x none $T{OBJDIR}/MRCBase.o $T{OBJDIR}/MRCARC.o $T{OBJDIR}/ARCBase.o $T{OBJDIR}/ARCMRC.o -framework Foundation -o ARCLayoutsWithoutWeak.exe
11 | END
12 | */
13 |
--------------------------------------------------------------------------------
/test/ARCMRC.h:
--------------------------------------------------------------------------------
1 | //
2 | // ARCMRC.h
3 | // TestARCLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "MRCBase.h"
10 |
11 | @interface ARCMRC : MRCBase
12 | @property(retain) id dataSource;
13 | @end
14 |
--------------------------------------------------------------------------------
/test/ARCMRC.m:
--------------------------------------------------------------------------------
1 | //
2 | // ARCMRC.m
3 | //
4 |
5 | #import "ARCMRC.h"
6 |
7 | @implementation ARCMRC
8 |
9 | @synthesize dataSource;
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/test/MRCARC.h:
--------------------------------------------------------------------------------
1 | //
2 | // MRCARC.h
3 | // TestARCLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "ARCBase.h"
10 |
11 | @interface MRCARC : ARCBase
12 | @property(retain) id dataSource;
13 | @end
14 |
--------------------------------------------------------------------------------
/test/MRCARC.m:
--------------------------------------------------------------------------------
1 | //
2 | // MRCARC.m
3 | //
4 |
5 | #import "MRCARC.h"
6 |
7 | @implementation MRCARC
8 |
9 | @synthesize dataSource;
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/test/MRCBase.h:
--------------------------------------------------------------------------------
1 | //
2 | // MRCBase.h
3 | // TestARCLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | // YES if MRC compiler supports ARC-style weak
12 | extern bool supportsMRCWeak;
13 |
14 | #if __LP64__
15 | #define DOUBLEWORD_ALIGNED __attribute__((aligned(16)))
16 | #else
17 | #define DOUBLEWORD_ALIGNED __attribute__((aligned(8)))
18 | #endif
19 |
20 | @interface MRCBase : NSObject
21 | @property double number;
22 | @property(retain) id object;
23 | @property void *pointer;
24 | @property(weak) __weak id delegate;
25 | @end
26 |
27 | // Call object_copy from MRC.
28 | extern id __attribute__((ns_returns_retained)) docopy(id obj);
29 |
--------------------------------------------------------------------------------
/test/MRCBase.m:
--------------------------------------------------------------------------------
1 | //
2 | // MRCBase.m
3 | // TestARCLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #include "MRCBase.h"
10 | #include "test.h"
11 |
12 | // MRCBase->alignment ensures that there is a gap between the end of
13 | // NSObject's ivars and the start of MRCBase's ivars, which exercises
14 | // handling of storage that is not represented in any class's ivar
15 | // layout bitmaps.
16 |
17 | #if __has_feature(objc_arc_weak)
18 | bool supportsMRCWeak = true;
19 | #else
20 | bool supportsMRCWeak = false;
21 | #endif
22 |
23 | @interface MRCBase () {
24 | @private
25 | double DOUBLEWORD_ALIGNED alignment;
26 | uintptr_t pad[3]; // historically this made OBJC2 layout bitmaps match OBJC1
27 | double number;
28 | id object;
29 | void *pointer;
30 | #if __has_feature(objc_arc_weak)
31 | __weak
32 | #endif
33 | id delegate;
34 | }
35 | @end
36 |
37 | @implementation MRCBase
38 | @synthesize number, object, pointer, delegate;
39 | @end
40 |
41 | // Call object_copy from MRC.
42 | extern id __attribute__((ns_returns_retained))
43 | docopy(id obj)
44 | {
45 | return object_copy(obj, 0);
46 | }
47 |
--------------------------------------------------------------------------------
/test/accessors.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 |
3 | #import
4 | #import
5 | #import
6 | #include "test.h"
7 |
8 | @interface Test : NSObject {
9 | NSString *_value;
10 | // _object is at the last optimized property offset
11 | id _object __attribute__((aligned(64)));
12 | }
13 | @property(readonly) Class cls;
14 | @property(copy) NSString *value;
15 | @property(assign) id object;
16 | @end
17 |
18 | typedef struct {
19 | void *isa;
20 | void *_value;
21 | // _object is at the last optimized property offset
22 | void *_object __attribute__((aligned(64)));
23 | } TestDefs;
24 |
25 | @implementation Test
26 |
27 | // Question: why can't this code be automatically generated?
28 |
29 | #if !__has_feature(objc_arc)
30 | - (void)dealloc {
31 | self.value = nil;
32 | self.object = nil;
33 | [super dealloc];
34 | }
35 | #endif
36 |
37 | - (Class)cls { return objc_getProperty(self, _cmd, 0, YES); }
38 |
39 | - (NSString*)value { return (NSString*) objc_getProperty(self, _cmd, offsetof(TestDefs, _value), YES); }
40 | - (void)setValue:(NSString*)inValue { objc_setProperty(self, _cmd, offsetof(TestDefs, _value), inValue, YES, YES); }
41 |
42 | - (id)object { return objc_getProperty(self, _cmd, offsetof(TestDefs, _object), YES); }
43 | - (void)setObject:(id)inObject { objc_setProperty(self, _cmd, offsetof(TestDefs, _object), inObject, YES, NO); }
44 |
45 | - (NSString *)description {
46 | return [NSString stringWithFormat:@"value = %@, object = %@", self.value, self.object];
47 | }
48 |
49 | @end
50 |
51 | int main() {
52 | PUSH_POOL {
53 |
54 | NSMutableString *value = [NSMutableString stringWithUTF8String:"test"];
55 | id object = [NSNumber numberWithInt:11];
56 | Test *t = AUTORELEASE([Test new]);
57 | t.value = value;
58 | [value setString:@"yuck"]; // mutate the string.
59 | testassert(t.value != value); // must copy, since it was mutable.
60 | testassert([t.value isEqualToString:@"test"]);
61 |
62 | Class testClass = [Test class];
63 | Class cls = t.cls;
64 | testassert(testClass == cls);
65 | cls = t.cls;
66 | testassert(testClass == cls);
67 |
68 | t.object = object;
69 | t.object = object;
70 |
71 | // NSLog(@"t.object = %@, t.value = %@", t.object, t.value);
72 | // NSLog(@"t.object = %@, t.value = %@", t.object, t.value); // second call will optimized getters.
73 |
74 | } POP_POOL;
75 |
76 | succeed(__FILE__);
77 |
78 | return 0;
79 | }
80 |
--------------------------------------------------------------------------------
/test/applescriptobjc.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=macosx
2 | // TEST_CFLAGS -framework AppleScriptObjC -framework Foundation
3 |
4 | // Verify that trivial AppleScriptObjC apps run with GC off.
5 |
6 | #include
7 | #include "test.h"
8 |
9 | int main()
10 | {
11 | [NSBundle class];
12 | succeed(__FILE__);
13 | }
14 |
--------------------------------------------------------------------------------
/test/arr-cast.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | // objc.h redefines these calls into bridge casts.
6 | // This test verifies that the function implementations are exported.
7 | __BEGIN_DECLS
8 | extern void *retainedObject(void *arg) __asm__("_objc_retainedObject");
9 | extern void *unretainedObject(void *arg) __asm__("_objc_unretainedObject");
10 | extern void *unretainedPointer(void *arg) __asm__("_objc_unretainedPointer");
11 | __END_DECLS
12 |
13 | int main()
14 | {
15 | void *p = (void*)&main;
16 | testassert(p == retainedObject(p));
17 | testassert(p == unretainedObject(p));
18 | testassert(p == unretainedPointer(p));
19 | succeed(__FILE__);
20 | }
21 |
--------------------------------------------------------------------------------
/test/asm-placeholder.s:
--------------------------------------------------------------------------------
1 | .macro NOP16
2 | nop
3 | nop
4 | nop
5 | nop
6 | nop
7 | nop
8 | nop
9 | nop
10 | nop
11 | nop
12 | nop
13 | nop
14 | nop
15 | nop
16 | nop
17 | nop
18 | .endmacro
19 |
20 | .macro NOP256
21 | NOP16
22 | NOP16
23 | NOP16
24 | NOP16
25 | NOP16
26 | NOP16
27 | NOP16
28 | NOP16
29 | NOP16
30 | NOP16
31 | NOP16
32 | NOP16
33 | NOP16
34 | NOP16
35 | NOP16
36 | NOP16
37 | .endmacro
38 |
39 | .text
40 | .globl _main
41 | .align 14
42 | _main:
43 | // at least 1024 instruction bytes on all architectures
44 | NOP256
45 | NOP256
46 | NOP256
47 | NOP256
48 |
--------------------------------------------------------------------------------
/test/association-cf.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework CoreFoundation
2 | // TEST_CONFIG MEM=mrc
3 | // not for ARC because ARC memory management doesn't
4 | // work on CF types whose ObjC side is not yet loaded
5 |
6 | #include
7 | #include
8 |
9 | #include "test.h"
10 |
11 | #if __has_feature(objc_arc)
12 |
13 | int main()
14 | {
15 | testwarn("rdar://11368528 confused by Foundation");
16 | succeed(__FILE__);
17 | }
18 |
19 | #else
20 |
21 | int main()
22 | {
23 | // rdar://6164781 setAssociatedObject on unresolved future class crashes
24 |
25 | id mp = (id)CFMachPortCreate(0, 0, 0, 0);
26 | testassert(mp);
27 |
28 | testassert(! objc_getClass("NSMachPort"));
29 |
30 | objc_setAssociatedObject(mp, (void*)1, mp, OBJC_ASSOCIATION_ASSIGN);
31 |
32 | id obj = objc_getAssociatedObject(mp, (void*)1);
33 | testassert(obj == mp);
34 |
35 | CFRelease((CFTypeRef)mp);
36 |
37 | succeed(__FILE__);
38 | }
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/test/associationForbidden.h:
--------------------------------------------------------------------------------
1 | #include "testroot.i"
2 |
3 | @interface Normal : TestRoot
4 | @end
5 | @implementation Normal
6 | @end
7 |
8 | @interface Forbidden : TestRoot
9 | @end
10 | @implementation Forbidden
11 | @end
12 |
13 | struct minimal_unrealized_class {
14 | void *isa;
15 | void *superclass;
16 | void *cachePtr;
17 | uintptr_t maskAndOccupied;
18 | struct minimal_class_ro *ro;
19 | };
20 |
21 | struct minimal_class_ro {
22 | uint32_t flags;
23 | };
24 |
25 | extern struct minimal_unrealized_class OBJC_CLASS_$_Forbidden;
26 |
27 | #define RO_FORBIDS_ASSOCIATED_OBJECTS (1<<10)
28 |
29 | static void *key = &key;
30 |
31 | static void test(void);
32 |
33 | int main()
34 | {
35 | struct minimal_unrealized_class *localForbidden = &OBJC_CLASS_$_Forbidden;
36 | localForbidden->ro->flags |= RO_FORBIDS_ASSOCIATED_OBJECTS;
37 | test();
38 | }
39 |
40 | static inline void ShouldSucceed(id obj) {
41 | objc_setAssociatedObject(obj, key, obj, OBJC_ASSOCIATION_ASSIGN);
42 | id assoc = objc_getAssociatedObject(obj, key);
43 | fprintf(stderr, "Associated object is %p\n", assoc);
44 | testassert(obj == assoc);
45 | }
46 |
47 | static inline void ShouldFail(id obj) {
48 | objc_setAssociatedObject(obj, key, obj, OBJC_ASSOCIATION_ASSIGN);
49 | fail("should have crashed trying to set the associated object");
50 | }
51 |
--------------------------------------------------------------------------------
/test/associationForbidden.m:
--------------------------------------------------------------------------------
1 | // TEST_CRASHES
2 | /*
3 | TEST_RUN_OUTPUT
4 | Associated object is 0x[0-9a-fA-F]+
5 | objc\[\d+\]: objc_setAssociatedObject called on instance \(0x[0-9a-fA-F]+\) of class Forbidden which does not allow associated objects
6 | objc\[\d+\]: HALTED
7 | END
8 | */
9 |
10 | #include "associationForbidden.h"
11 |
12 | void test(void)
13 | {
14 | ShouldSucceed([Normal alloc]);
15 | ShouldFail([Forbidden alloc]);
16 | }
17 |
--------------------------------------------------------------------------------
/test/associationForbidden2.m:
--------------------------------------------------------------------------------
1 | // TEST_CRASHES
2 | /*
3 | TEST_RUN_OUTPUT
4 | Associated object is 0x[0-9a-fA-F]+
5 | objc\[\d+\]: objc_setAssociatedObject called on instance \(0x[0-9a-fA-F]+\) of class ForbiddenSubclass which does not allow associated objects
6 | objc\[\d+\]: HALTED
7 | END
8 | */
9 |
10 | #include "associationForbidden.h"
11 |
12 | void test(void)
13 | {
14 | ShouldSucceed([Normal alloc]);
15 | Class ForbiddenSubclass = objc_allocateClassPair([Forbidden class],
16 | "ForbiddenSubclass", 0);
17 | objc_registerClassPair(ForbiddenSubclass);
18 | ShouldFail([ForbiddenSubclass alloc]);
19 | }
20 |
--------------------------------------------------------------------------------
/test/associationForbidden3.m:
--------------------------------------------------------------------------------
1 | // TEST_CRASHES
2 | /*
3 | TEST_RUN_OUTPUT
4 | Associated object is 0x[0-9a-fA-F]+
5 | objc\[\d+\]: objc_setAssociatedObject called on instance \(0x[0-9a-fA-F]+\) of class ForbiddenSubclass which does not allow associated objects
6 | objc\[\d+\]: HALTED
7 | END
8 | */
9 |
10 | #include "associationForbidden.h"
11 |
12 | @interface ForbiddenSubclass : Forbidden
13 | @end
14 | @implementation ForbiddenSubclass
15 | @end
16 |
17 | void test(void)
18 | {
19 | ShouldSucceed([Normal alloc]);
20 | ShouldSucceed([ForbiddenSubclass alloc]);
21 | }
22 |
--------------------------------------------------------------------------------
/test/associationForbidden4.m:
--------------------------------------------------------------------------------
1 | // TEST_CRASHES
2 | /*
3 | TEST_RUN_OUTPUT
4 | Associated object is 0x[0-9a-fA-F]+
5 | objc\[\d+\]: objc_setAssociatedObject called on instance \(0x[0-9a-fA-F]+\) of class ForbiddenDuplicate which does not allow associated objects
6 | objc\[\d+\]: HALTED
7 | END
8 | */
9 |
10 | #include "associationForbidden.h"
11 |
12 | void test(void)
13 | {
14 | ShouldSucceed([Normal alloc]);
15 | Class ForbiddenDuplicate = objc_duplicateClass([Forbidden class],
16 | "ForbiddenDuplicate", 0);
17 | ShouldFail([ForbiddenDuplicate alloc]);
18 | }
19 |
--------------------------------------------------------------------------------
/test/atomicProperty.mm:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #import
7 |
8 | class SerialNumber {
9 | size_t _number;
10 | public:
11 | SerialNumber() : _number(42) {}
12 | SerialNumber(const SerialNumber &number) : _number(number._number + 1) {}
13 | SerialNumber &operator=(const SerialNumber &number) { _number = number._number + 1; return *this; }
14 |
15 | int operator==(const SerialNumber &number) { return _number == number._number; }
16 | int operator!=(const SerialNumber &number) { return _number != number._number; }
17 | };
18 |
19 | @interface TestAtomicProperty : NSObject {
20 | SerialNumber number;
21 | }
22 | @property(atomic) SerialNumber number;
23 | @end
24 |
25 | @implementation TestAtomicProperty
26 |
27 | @synthesize number;
28 |
29 | @end
30 |
31 | int main()
32 | {
33 | PUSH_POOL {
34 | SerialNumber number;
35 | TestAtomicProperty *test = [TestAtomicProperty new];
36 | test.number = number;
37 | testassert(test.number != number);
38 | } POP_POOL;
39 |
40 | succeed(__FILE__);
41 | }
42 |
--------------------------------------------------------------------------------
/test/badCache.m:
--------------------------------------------------------------------------------
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 {
48 | uintptr_t buckets;
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;
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 |
87 | # define COUNT 4
88 | # define COUNTSHIFT 14
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 |
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 | }
107 |
108 | cache->occupied = 0;
109 |
110 | fprintf(stderr, "crash now\n");
111 | [obj self];
112 |
113 | fail("should have crashed");
114 | }
115 |
116 | #endif
117 |
--------------------------------------------------------------------------------
/test/badPool.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 | // TEST_CRASHES
3 |
4 | // Test badPoolCompat also uses this file.
5 |
6 | /*
7 | TEST_RUN_OUTPUT
8 | objc\[\d+\]: [Ii]nvalid or prematurely-freed autorelease pool 0x[0-9a-fA-F]+\.?
9 | objc\[\d+\]: HALTED
10 | END
11 | */
12 |
13 | #include "test.h"
14 |
15 | int main()
16 | {
17 | void *outer = objc_autoreleasePoolPush();
18 | void *inner = objc_autoreleasePoolPush();
19 | objc_autoreleasePoolPop(outer);
20 | objc_autoreleasePoolPop(inner);
21 |
22 | #if !OLD
23 | fail("should have crashed already with new SDK");
24 | #else
25 | // should only warn once
26 | outer = objc_autoreleasePoolPush();
27 | inner = objc_autoreleasePoolPush();
28 | objc_autoreleasePoolPop(outer);
29 | objc_autoreleasePoolPop(inner);
30 |
31 | succeed(__FILE__);
32 | #endif
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/test/badPoolCompat-ios.m:
--------------------------------------------------------------------------------
1 | // Run test badPool as if it were built with an old SDK.
2 |
3 | // TEST_CONFIG MEM=mrc OS=iphoneos,iphonesimulator ARCH=x86_64,arm64
4 | // TEST_CRASHES
5 | // TEST_CFLAGS -DOLD=1 -Xlinker -platform_version -Xlinker ios -Xlinker 9.0 -Xlinker 9.0 -miphoneos-version-min=9.0
6 |
7 | /*
8 | TEST_BUILD_OUTPUT
9 | ld: warning: passed two min versions.*for platform.*
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .* Proceeding anyway .*
14 | OK: badPool.m
15 | END
16 | */
17 |
18 | #include "badPool.m"
19 |
--------------------------------------------------------------------------------
/test/badPoolCompat-macos.m:
--------------------------------------------------------------------------------
1 | // Run test badPool as if it were built with an old SDK.
2 |
3 | // TEST_CONFIG MEM=mrc OS=macosx ARCH=x86_64
4 | // TEST_CRASHES
5 | // TEST_CFLAGS -DOLD=1 -Xlinker -platform_version -Xlinker macos -Xlinker 10.11 -Xlinker 10.11 -mmacosx-version-min=10.11
6 |
7 | /*
8 | TEST_BUILD_OUTPUT
9 | ld: warning: passed two min versions.*for platform.*
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .* Proceeding anyway .*
14 | OK: badPool.m
15 | END
16 | */
17 |
18 | #include "badPool.m"
19 |
--------------------------------------------------------------------------------
/test/badPoolCompat-tvos.m:
--------------------------------------------------------------------------------
1 | // Run test badPool as if it were built with an old SDK.
2 |
3 | // TEST_CONFIG MEM=mrc OS=appletvos,appletvsimulator ARCH=x86_64,arm64
4 | // TEST_CRASHES
5 | // TEST_CFLAGS -DOLD=1 -Xlinker -platform_version -Xlinker tvos -Xlinker 9.0 -Xlinker 9.0 -mtvos-version-min=9.0
6 |
7 | /*
8 | TEST_BUILD_OUTPUT
9 | ld: warning: passed two min versions.*for platform.*
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .* Proceeding anyway .*
14 | OK: badPool.m
15 | END
16 | */
17 |
18 | #include "badPool.m"
19 |
--------------------------------------------------------------------------------
/test/badPoolCompat-watchos.m:
--------------------------------------------------------------------------------
1 | // Run test badPool as if it were built with an old SDK.
2 |
3 | // TEST_CONFIG MEM=mrc OS=watchos,watchsimulator
4 | // TEST_CRASHES
5 | // TEST_CFLAGS -DOLD=1 -Xlinker -platform_version -Xlinker watchos -Xlinker 2.0 -Xlinker 2.0 -mwatchos-version-min=2.0
6 |
7 | /*
8 | TEST_BUILD_OUTPUT
9 | ld: warning: passed two min versions.*for platform.*
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .* Proceeding anyway .*
14 | OK: badPool.m
15 | END
16 | */
17 |
18 | #include "badPool.m"
19 |
--------------------------------------------------------------------------------
/test/badSuperclass.m:
--------------------------------------------------------------------------------
1 | // TEST_CRASHES
2 | /*
3 | TEST_RUN_OUTPUT
4 | objc\[\d+\]: Memory corruption in class list\.
5 | objc\[\d+\]: HALTED
6 | END
7 | */
8 |
9 | #include "test.h"
10 | #include "testroot.i"
11 |
12 | @interface Super : TestRoot @end
13 | @implementation Super @end
14 |
15 | @interface Sub : Super @end
16 | @implementation Sub @end
17 |
18 | int main()
19 | {
20 | alarm(10);
21 |
22 | Class supercls = [Super class];
23 | Class subcls = [Sub class];
24 | id subobj __unused = [Sub alloc];
25 |
26 | // Create a cycle in a superclass chain (Sub->supercls == Sub)
27 | // then attempt to walk that chain. Runtime should halt eventually.
28 | _objc_flush_caches(supercls);
29 | ((Class __ptrauth_objc_super_pointer *)(__bridge void *)subcls)[1] = subcls;
30 | #ifdef CACHE_FLUSH
31 | _objc_flush_caches(supercls);
32 | #else
33 | [subobj class];
34 | #endif
35 |
36 | fail("should have crashed");
37 | }
38 |
--------------------------------------------------------------------------------
/test/badSuperclass2.m:
--------------------------------------------------------------------------------
1 | // TEST_CRASHES
2 | /*
3 | TEST_RUN_OUTPUT
4 | objc\[\d+\]: Memory corruption in class list\.
5 | objc\[\d+\]: HALTED
6 | OR
7 | old abi
8 | OK: badSuperclass\.m
9 | END
10 | */
11 |
12 | #define CACHE_FLUSH
13 | #include "badSuperclass.m"
14 |
--------------------------------------------------------------------------------
/test/badTagClass.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CRASHES
3 | TEST_BUILD_OUTPUT
4 | .*badTagClass.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
5 | END
6 | TEST_RUN_OUTPUT
7 | objc\[\d+\]: tag index 1 used for two different classes \(was 0x[0-9a-fA-F]+ NSObject, now 0x[0-9a-fA-F]+ TestRoot\)
8 | objc\[\d+\]: HALTED
9 | OR
10 | no tagged pointers
11 | OK: badTagClass.m
12 | END
13 | */
14 |
15 | #include "test.h"
16 | #include "testroot.i"
17 |
18 | #include
19 | #include
20 |
21 | #if OBJC_HAVE_TAGGED_POINTERS
22 |
23 | int main()
24 | {
25 | // re-registration and nil registration allowed
26 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [NSObject class]);
27 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [NSObject class]);
28 | _objc_registerTaggedPointerClass(OBJC_TAG_1, nil);
29 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [NSObject class]);
30 |
31 | // colliding registration disallowed
32 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [TestRoot class]);
33 |
34 | fail(__FILE__);
35 | }
36 |
37 | #else
38 |
39 | int main()
40 | {
41 | // provoke the same nullability warning as the real test
42 | objc_getClass(nil);
43 |
44 | fprintf(stderr, "no tagged pointers\n");
45 | succeed(__FILE__);
46 | }
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/test/badTagIndex.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CRASHES
3 | TEST_RUN_OUTPUT
4 | objc\[\d+\]: tag index 264 is invalid
5 | objc\[\d+\]: HALTED
6 | OR
7 | no tagged pointers
8 | OK: badTagIndex.m
9 | END
10 | */
11 |
12 | #include "test.h"
13 |
14 | #include
15 | #include
16 |
17 | #if OBJC_HAVE_TAGGED_POINTERS
18 |
19 | int main()
20 | {
21 | _objc_registerTaggedPointerClass((objc_tag_index_t)(OBJC_TAG_Last52BitPayload+1), [NSObject class]);
22 | fail(__FILE__);
23 | }
24 |
25 | #else
26 |
27 | int main()
28 | {
29 | fprintf(stderr, "no tagged pointers\n");
30 | succeed(__FILE__);
31 | }
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/test/bigrc.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 |
6 | static size_t LOTS;
7 |
8 | @interface Deallocator : TestRoot @end
9 | @implementation Deallocator
10 |
11 | -(void)dealloc
12 | {
13 | id o = self;
14 |
15 |
16 | testprintf("Retain/release during dealloc\n");
17 |
18 | testassertequal([o retainCount], 0);
19 | [o retain];
20 | testassertequal([o retainCount], 0);
21 | [o release];
22 | testassertequal([o retainCount], 0);
23 |
24 | [super dealloc];
25 | }
26 |
27 | @end
28 |
29 | size_t clz(uintptr_t isa) {
30 | if (sizeof(uintptr_t) == 4)
31 | return __builtin_clzl(isa);
32 | testassert(sizeof(uintptr_t) == 8);
33 | return __builtin_clzll(isa);
34 | }
35 |
36 | int main()
37 | {
38 | Deallocator *o = [Deallocator new];
39 | size_t rc = 1;
40 |
41 | [o retain];
42 |
43 | uintptr_t isa = *(uintptr_t *)o;
44 | if (isa & 1) {
45 | // Assume refcount in high bits.
46 | LOTS = 1 << (4 + clz(isa));
47 | testprintf("LOTS %zu via cntlzw\n", LOTS);
48 | } else {
49 | LOTS = 0x1000000;
50 | testprintf("LOTS %zu via guess\n", LOTS);
51 | }
52 |
53 | [o release];
54 |
55 |
56 | testprintf("Retain a lot\n");
57 |
58 | testassert(rc == 1);
59 | testassert([o retainCount] == rc);
60 | do {
61 | [o retain];
62 | if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
63 | } while (++rc < LOTS);
64 |
65 | testassert([o retainCount] == rc);
66 |
67 | do {
68 | [o release];
69 | if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
70 | } while (--rc > 1);
71 |
72 | testassert(rc == 1);
73 | testassert([o retainCount] == rc);
74 |
75 |
76 | testprintf("tryRetain a lot\n");
77 |
78 | id w;
79 | objc_storeWeak(&w, o);
80 | testassert(w == o);
81 |
82 | testassert(rc == 1);
83 | testassert([o retainCount] == rc);
84 | do {
85 | objc_loadWeakRetained(&w);
86 | if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
87 | } while (++rc < LOTS);
88 |
89 | testassert([o retainCount] == rc);
90 |
91 | do {
92 | [o release];
93 | if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
94 | } while (--rc > 1);
95 |
96 | testassert(rc == 1);
97 | testassert([o retainCount] == rc);
98 |
99 | testprintf("dealloc\n");
100 |
101 | testassert(TestRootDealloc == 0);
102 | testassert(w != nil);
103 | [o release];
104 | testassert(TestRootDealloc == 1);
105 | testassert(w == nil);
106 |
107 | succeed(__FILE__);
108 | }
109 |
--------------------------------------------------------------------------------
/test/bool.c:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -funsigned-char
2 | // (verify -funsigned-char doesn't change the definition of BOOL)
3 |
4 | #include "test.h"
5 | #include
6 |
7 | #if TARGET_OS_OSX
8 | # if __x86_64__
9 | # define RealBool 0
10 | # else
11 | # define RealBool 1
12 | # endif
13 | #elif TARGET_OS_IOS || TARGET_OS_BRIDGE
14 | # if (__arm__ && !__armv7k__) || __i386__
15 | # define RealBool 0
16 | # else
17 | # define RealBool 1
18 | # endif
19 | #else
20 | # define RealBool 1
21 | #endif
22 |
23 | #if __OBJC__ && !defined(__OBJC_BOOL_IS_BOOL)
24 | # error no __OBJC_BOOL_IS_BOOL
25 | #endif
26 |
27 | #if RealBool != OBJC_BOOL_IS_BOOL
28 | # error wrong OBJC_BOOL_IS_BOOL
29 | #endif
30 |
31 | #if RealBool == OBJC_BOOL_IS_CHAR
32 | # error wrong OBJC_BOOL_IS_CHAR
33 | #endif
34 |
35 | int main()
36 | {
37 | const char *expected __unused =
38 | #if RealBool
39 | "B"
40 | #else
41 | "c"
42 | #endif
43 | ;
44 | #if __OBJC__
45 | const char *enc = @encode(BOOL);
46 | testassert(0 == strcmp(enc, expected));
47 | #endif
48 | succeed(__FILE__);
49 | }
50 |
--------------------------------------------------------------------------------
/test/cacheflush-constant.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | /*
3 | TEST_RUN_OUTPUT
4 | foo
5 | bar
6 | bar
7 | foo
8 | END
9 | */
10 |
11 | // NOTE: This test won't catch problems when running against a root, so it's of
12 | // limited utility, but it would at least catch things when testing against the
13 | // shared cache.
14 |
15 | #include
16 | #include
17 |
18 | @interface NSBlock: NSObject @end
19 |
20 | // NSBlock is a conveniently accessible superclass that (currently) has a constant cache.
21 | @interface MyBlock: NSBlock
22 | +(void)foo;
23 | +(void)bar;
24 | @end
25 | @implementation MyBlock
26 | +(void)foo {
27 | printf("foo\n");
28 | }
29 | +(void)bar {
30 | printf("bar\n");
31 | }
32 | @end
33 |
34 | int main() {
35 | [MyBlock foo];
36 | [MyBlock bar];
37 |
38 | Method m1 = class_getClassMethod([MyBlock class], @selector(foo));
39 | Method m2 = class_getClassMethod([MyBlock class], @selector(bar));
40 | method_exchangeImplementations(m1, m2);
41 |
42 | [MyBlock foo];
43 | [MyBlock bar];
44 | }
45 |
--------------------------------------------------------------------------------
/test/cacheflush.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include "test.h"
3 |
4 | @interface TestRoot(cat)
5 | +(int)classMethod;
6 | -(int)instanceMethod;
7 | @end
8 |
--------------------------------------------------------------------------------
/test/cacheflush.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/cacheflush0.m -o cacheflush0.dylib -dynamiclib
4 | $C{COMPILE} $DIR/cacheflush2.m -x none cacheflush0.dylib -o cacheflush2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/cacheflush3.m -x none cacheflush0.dylib -o cacheflush3.dylib -dynamiclib
6 | $C{COMPILE} $DIR/cacheflush.m -x none cacheflush0.dylib -o cacheflush.exe
7 | END
8 | */
9 |
10 | #include "test.h"
11 | #include
12 | #include
13 |
14 | #include "cacheflush.h"
15 |
16 | @interface Sub : TestRoot @end
17 | @implementation Sub @end
18 |
19 |
20 | int main()
21 | {
22 | TestRoot *sup = [TestRoot new];
23 | Sub *sub = [Sub new];
24 |
25 | // Fill method cache
26 | testassert(1 == [TestRoot classMethod]);
27 | testassert(1 == [sup instanceMethod]);
28 | testassert(1 == [TestRoot classMethod]);
29 | testassert(1 == [sup instanceMethod]);
30 |
31 | testassert(1 == [Sub classMethod]);
32 | testassert(1 == [sub instanceMethod]);
33 | testassert(1 == [Sub classMethod]);
34 | testassert(1 == [sub instanceMethod]);
35 |
36 | // Dynamically load a category
37 | dlopen("cacheflush2.dylib", 0);
38 |
39 | // Make sure old cache results are gone
40 | testassert(2 == [TestRoot classMethod]);
41 | testassert(2 == [sup instanceMethod]);
42 |
43 | testassert(2 == [Sub classMethod]);
44 | testassert(2 == [sub instanceMethod]);
45 |
46 | // Dynamically load another category
47 | dlopen("cacheflush3.dylib", 0);
48 |
49 | // Make sure old cache results are gone
50 | testassert(3 == [TestRoot classMethod]);
51 | testassert(3 == [sup instanceMethod]);
52 |
53 | testassert(3 == [Sub classMethod]);
54 | testassert(3 == [sub instanceMethod]);
55 |
56 | // fixme test subclasses
57 |
58 | // fixme test objc_flush_caches(), class_addMethod(), class_addMethods()
59 |
60 | succeed(__FILE__);
61 | }
62 |
--------------------------------------------------------------------------------
/test/cacheflush0.m:
--------------------------------------------------------------------------------
1 | #include "cacheflush.h"
2 | #include "testroot.i"
3 |
4 | @implementation TestRoot(cat)
5 | +(int)classMethod { return 1; }
6 | -(int)instanceMethod { return 1; }
7 | @end
8 |
--------------------------------------------------------------------------------
/test/cacheflush2.m:
--------------------------------------------------------------------------------
1 | #include "cacheflush.h"
2 |
3 | @implementation TestRoot (Category2)
4 | +(int)classMethod { return 2; }
5 | -(int)instanceMethod { return 2; }
6 | @end
7 |
--------------------------------------------------------------------------------
/test/cacheflush3.m:
--------------------------------------------------------------------------------
1 | #include "cacheflush.h"
2 |
3 | @implementation TestRoot (Category3)
4 | +(int)classMethod { return 3; }
5 | -(int)instanceMethod { return 3; }
6 | @end
7 |
--------------------------------------------------------------------------------
/test/classgetclass.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #import
7 |
8 | @interface Foo:NSObject
9 | @end
10 | @implementation Foo
11 | @end
12 |
13 | int main()
14 | {
15 | testassert(gdb_class_getClass([Foo class]) == [Foo class]);
16 | succeed(__FILE__);
17 | }
18 |
--------------------------------------------------------------------------------
/test/classname.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 | #include
7 | #include
8 |
9 | @interface Fake : TestRoot @end
10 | @implementation Fake @end
11 |
12 | int main()
13 | {
14 | TestRoot *obj = [TestRoot new];
15 | void *buf = (__bridge void *)(obj);
16 | *(Class __ptrauth_objc_isa_pointer *)buf = [Fake class];
17 |
18 | testassert(object_getClass(obj) == [Fake class]);
19 | testassert(object_setClass(obj, [TestRoot class]) == [Fake class]);
20 | testassert(object_getClass(obj) == [TestRoot class]);
21 | testassert(object_setClass(nil, [TestRoot class]) == nil);
22 |
23 | testassert(malloc_size(buf) >= sizeof(id));
24 | bzero(buf, malloc_size(buf));
25 | testassert(object_setClass(obj, [TestRoot class]) == nil);
26 |
27 | testassert(object_getClass(obj) == [TestRoot class]);
28 | testassert(object_getClass([TestRoot class]) == object_getClass([TestRoot class]));
29 | testassert(object_getClass(nil) == Nil);
30 |
31 | testassert(0 == strcmp(object_getClassName(obj), "TestRoot"));
32 | testassert(0 == strcmp(object_getClassName([TestRoot class]), "TestRoot"));
33 | testassert(0 == strcmp(object_getClassName(nil), "nil"));
34 |
35 | testassert(0 == strcmp(class_getName([TestRoot class]), "TestRoot"));
36 | testassert(0 == strcmp(class_getName(object_getClass([TestRoot class])), "TestRoot"));
37 | testassert(0 == strcmp(class_getName(nil), "nil"));
38 |
39 | succeed(__FILE__);
40 | }
41 |
--------------------------------------------------------------------------------
/test/classversion.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | int main()
8 | {
9 | Class cls = [TestRoot class];
10 | testassert(class_getVersion(cls) == 0);
11 | testassert(class_getVersion(object_getClass(cls)) > 5);
12 | class_setVersion(cls, 100);
13 | testassert(class_getVersion(cls) == 100);
14 |
15 | testassert(class_getVersion(Nil) == 0);
16 | class_setVersion(Nil, 100);
17 |
18 | succeed(__FILE__);
19 | }
20 |
--------------------------------------------------------------------------------
/test/concurrentcat_category.m:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #import
4 |
5 | @interface TargetClass : NSObject
6 | @end
7 |
8 | @interface TargetClass(LoadedMethods)
9 | - (void) m0;
10 | - (void) m1;
11 | - (void) m2;
12 | - (void) m3;
13 | - (void) m4;
14 | - (void) m5;
15 | - (void) m6;
16 | - (void) m7;
17 | - (void) m8;
18 | - (void) m9;
19 | - (void) m10;
20 | - (void) m11;
21 | - (void) m12;
22 | - (void) m13;
23 | - (void) m14;
24 | - (void) m15;
25 | @end
26 |
27 | @interface TN:TargetClass
28 | @end
29 |
30 | @implementation TN
31 | - (void) m1 { [super m1]; }
32 | - (void) m3 { [self m1]; }
33 |
34 | - (void) m2
35 | {
36 | [self willChangeValueForKey: @"m4"];
37 | [self didChangeValueForKey: @"m4"];
38 | }
39 |
40 | - (void)observeValueForKeyPath:(NSString *) keyPath
41 | ofObject:(id)object
42 | change:(NSDictionary *)change
43 | context:(void *)context
44 | {
45 | // suppress warning
46 | keyPath = nil;
47 | object = nil;
48 | change = nil;
49 | context = NULL;
50 | }
51 | @end
52 |
53 | @implementation TargetClass(LoadedMethods)
54 | - (void) m0 { ; }
55 | - (void) m1 { ; }
56 | - (void) m2 { ; }
57 | - (void) m3 { ; }
58 | - (void) m4 { ; }
59 | - (void) m5 { ; }
60 | - (void) m6 { ; }
61 | - (void) m7 { ; }
62 | - (void) m8 { ; }
63 | - (void) m9 { ; }
64 | - (void) m10 { ; }
65 | - (void) m11 { ; }
66 | - (void) m12 { ; }
67 | - (void) m13 { ; }
68 | - (void) m14 { ; }
69 | - (void) m15 { ; }
70 | @end
71 |
--------------------------------------------------------------------------------
/test/copyProtocolList.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #include
7 |
8 | @protocol Proto1
9 | +(id)proto1ClassMethod;
10 | -(id)proto1InstanceMethod;
11 | @end
12 |
13 | void noNullEntries(Protocol * _Nonnull __unsafe_unretained * _Nullable protolist,
14 | unsigned int count)
15 | {
16 | for (unsigned int i = 0; i != count; ++i) {
17 | testassert(protolist[i]);
18 | testassert(protocol_getName(protolist[i]));
19 | testprintf("Protocol[%d/%d]: %p %s\n", i, count, protolist[i], protocol_getName(protolist[i]));
20 | }
21 | }
22 |
23 | Protocol* getProtocol(Protocol * _Nonnull __unsafe_unretained * _Nullable protolist,
24 | unsigned int count, const char* name) {
25 | for (unsigned int i = 0; i != count; ++i) {
26 | if (!strcmp(protocol_getName(protolist[i]), name))
27 | return protolist[i];
28 | }
29 | return nil;
30 | }
31 |
32 | int main()
33 | {
34 | Protocol * _Nonnull __unsafe_unretained * _Nullable protolist;
35 | unsigned int count;
36 |
37 | count = 100;
38 | protolist = objc_copyProtocolList(&count);
39 | testassert(protolist);
40 | testassert(count != 0);
41 | testassert(malloc_size(protolist) >= (count * sizeof(Protocol*)));
42 | noNullEntries(protolist, count);
43 | testassert(protolist[count] == nil);
44 | // Check for a shared cache protocol, ie, the one we know comes from libobjc
45 | testassert(getProtocol(protolist, count, "NSObject"));
46 | // Test for a protocol we know isn't in the cache
47 | testassert(getProtocol(protolist, count, "Proto1") == @protocol(Proto1));
48 | // Test for a protocol we know isn't there
49 | testassert(!getProtocol(protolist, count, "Proto2"));
50 | free(protolist);
51 |
52 | // Now add it
53 | Protocol* newproto = objc_allocateProtocol("Proto2");
54 | objc_registerProtocol(newproto);
55 |
56 | Protocol * _Nonnull __unsafe_unretained * _Nullable newProtolist;
57 | unsigned int newCount;
58 |
59 | newCount = 100;
60 | newProtolist = objc_copyProtocolList(&newCount);
61 | testassert(newProtolist);
62 | testassert(newCount == (count + 1));
63 | testassert(getProtocol(newProtolist, newCount, "Proto2"));
64 | free(newProtolist);
65 |
66 |
67 | succeed(__FILE__);
68 | return 0;
69 | }
70 |
--------------------------------------------------------------------------------
/test/createInstance.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #import
4 | #import
5 | #include "test.h"
6 | #include "testroot.i"
7 |
8 | @interface Super : TestRoot @end
9 | @implementation Super @end
10 |
11 | @interface Sub : Super { int array[128]; } @end
12 | @implementation Sub @end
13 |
14 | #if __has_feature(objc_arc)
15 | #define object_dispose(x) do {} while (0)
16 | #endif
17 |
18 | int main()
19 | {
20 | Super *s;
21 |
22 | s = class_createInstance([Super class], 0);
23 | testassert(s);
24 | testassert(object_getClass(s) == [Super class]);
25 | testassert(malloc_size((__bridge const void *)s) >= class_getInstanceSize([Super class]));
26 |
27 | object_dispose(s);
28 |
29 | s = class_createInstance([Sub class], 0);
30 | testassert(s);
31 | testassert(object_getClass(s) == [Sub class]);
32 | testassert(malloc_size((__bridge const void *)s) >= class_getInstanceSize([Sub class]));
33 |
34 | object_dispose(s);
35 |
36 | s = class_createInstance([Super class], 100);
37 | testassert(s);
38 | testassert(object_getClass(s) == [Super class]);
39 | testassert(malloc_size((__bridge const void *)s) >= class_getInstanceSize([Super class]) + 100);
40 |
41 | object_dispose(s);
42 |
43 | s = class_createInstance([Sub class], 100);
44 | testassert(s);
45 | testassert(object_getClass(s) == [Sub class]);
46 | testassert(malloc_size((__bridge const void *)s) >= class_getInstanceSize([Sub class]) + 100);
47 |
48 | object_dispose(s);
49 |
50 | s = class_createInstance(Nil, 0);
51 | testassert(!s);
52 |
53 | testassert(TestRootAlloc == 0);
54 |
55 | #if __has_feature(objc_arc)
56 | // ARC version didn't use object_dispose()
57 | // and should have called -dealloc on 4 objects
58 | testassert(TestRootDealloc == 4);
59 | #else
60 | // MRC version used object_dispose()
61 | // which doesn't call -dealloc
62 | testassert(TestRootDealloc == 0);
63 | #endif
64 |
65 | succeed(__FILE__);
66 | }
67 |
--------------------------------------------------------------------------------
/test/customrr-cat1.m:
--------------------------------------------------------------------------------
1 | @interface InheritingSubCat @end
2 |
3 | @interface InheritingSubCat (NonClobberingCategory) @end
4 |
5 | @implementation InheritingSubCat (NonClobberingCategory)
6 | -(id) unrelatedMethod { return self; }
7 | @end
8 |
--------------------------------------------------------------------------------
/test/customrr-cat2.m:
--------------------------------------------------------------------------------
1 | @interface InheritingSubCat @end
2 |
3 | @interface InheritingSubCat (ClobberingCategory) @end
4 |
5 | @implementation InheritingSubCat (ClobberingCategory)
6 | -(int) retainCount { return 1; }
7 | @end
8 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-awz.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES OBJC_PRINT_CUSTOM_CORE=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-awz.exe -DSWIZZLE_AWZ=1 -fno-objc-convert-messages-to-runtime-calls
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | objc\[\d+\]: CUSTOM AWZ: NSObject \(meta\)
12 | OK: customrr-nsobject-awz.exe
13 | END
14 |
15 | */
16 |
17 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-core.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES OBJC_PRINT_CUSTOM_CORE=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-core.exe -DSWIZZLE_CORE=1 -fno-objc-convert-messages-to-runtime-calls
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | objc\[\d+\]: CUSTOM Core: NSObject
12 | objc\[\d+\]: CUSTOM Core: NSObject \(meta\)
13 | OK: customrr-nsobject-core.exe
14 | END
15 |
16 | */
17 |
18 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-none.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES OBJC_PRINT_CUSTOM_CORE=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-none.exe -fno-objc-convert-messages-to-runtime-calls
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | OK: customrr-nsobject-none.exe
12 | END
13 |
14 | */
15 |
16 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-rr.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES OBJC_PRINT_CUSTOM_CORE=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-rr.exe -DSWIZZLE_RELEASE=1 -fno-objc-convert-messages-to-runtime-calls
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | objc\[\d+\]: CUSTOM RR: NSObject
12 | OK: customrr-nsobject-rr.exe
13 | END
14 |
15 | */
16 |
17 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-rrawz.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES OBJC_PRINT_CUSTOM_CORE=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-rrawz.exe -DSWIZZLE_RELEASE=1 -DSWIZZLE_AWZ=1 -fno-objc-convert-messages-to-runtime-calls
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | objc\[\d+\]: CUSTOM AWZ: NSObject \(meta\)
12 | objc\[\d+\]: CUSTOM RR: NSObject
13 | OK: customrr-nsobject-rrawz.exe
14 | END
15 |
16 | */
17 |
18 |
--------------------------------------------------------------------------------
/test/customrr2.m:
--------------------------------------------------------------------------------
1 | // These options must match customrr.m
2 | // TEST_CONFIG MEM=mrc
3 | /*
4 | TEST_BUILD
5 | $C{COMPILE} $DIR/customrr.m -fvisibility=default -o customrr2.exe -DTEST_EXCHANGEIMPLEMENTATIONS=1 -fno-objc-convert-messages-to-runtime-calls
6 | $C{COMPILE} -bundle -bundle_loader customrr2.exe $DIR/customrr-cat1.m -o customrr-cat1.bundle
7 | $C{COMPILE} -bundle -bundle_loader customrr2.exe $DIR/customrr-cat2.m -o customrr-cat2.bundle
8 | END
9 | */
10 |
--------------------------------------------------------------------------------
/test/debugScanWeakTables.m:
--------------------------------------------------------------------------------
1 | // TEST_ENV OBJC_DEBUG_SCAN_WEAK_TABLES=YES OBJC_DEBUG_SCAN_WEAK_TABLES_INTERVAL_NANOSECONDS=1000
2 | // TEST_CRASHES
3 | // TEST_CONFIG MEM=mrc
4 | /*
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: Starting background scan of weak references.
7 | objc\[\d+\]: Weak reference at 0x[0-9a-fA-F]+ contains 0x[0-9a-fA-F]+, should contain 0x[0-9a-fA-F]+
8 | objc\[\d+\]: HALTED
9 | END
10 | */
11 |
12 | #include "test.h"
13 | #include "testroot.i"
14 |
15 | #include
16 |
17 | int main() {
18 | id obj = [TestRoot new];
19 | id weakLoc = nil;
20 |
21 | objc_storeWeak(&weakLoc, obj);
22 | memset_s(&weakLoc, sizeof(weakLoc), 0x35, sizeof(weakLoc));
23 |
24 | uint64_t startTime = clock_gettime_nsec_np(CLOCK_UPTIME_RAW_APPROX);
25 | while (clock_gettime_nsec_np(CLOCK_UPTIME_RAW_APPROX) - startTime < 5000000000) {
26 | sleep(1);
27 | printf(".\n");
28 | }
29 |
30 | fail("Should have crashed scanning weakLoc");
31 | }
--------------------------------------------------------------------------------
/test/defines.c:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG MEM=mrc LANGUAGE=c
3 |
4 | TEST_BUILD
5 | $DIR/defines.sh '$C{TESTINCLUDEDIR}' '$C{TESTLOCALINCLUDEDIR}' '$C{COMPILE_C}' '$C{COMPILE_CXX}' '$C{COMPILE_M}' '$C{COMPILE_MM}' '$VERBOSE'
6 | $C{COMPILE_C} $DIR/defines.c -o defines.exe
7 | END
8 |
9 | TEST_BUILD_OUTPUT
10 | (.|\n)*No unexpected #defines found\.
11 | END
12 | */
13 |
14 |
15 | #include "test.h"
16 |
17 | int main()
18 | {
19 | succeed(__FILE__);
20 | }
21 |
--------------------------------------------------------------------------------
/test/defines.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Check ObjC headers for unwanted defines exposed to clients.
4 |
5 | TESTINCLUDEDIR=$1; shift
6 | TESTLOCALINCLUDEDIR=$1; shift
7 | COMPILE_C=$1; shift
8 | COMPILE_CXX=$1; shift
9 | COMPILE_M=$1; shift
10 | COMPILE_MM=$1; shift
11 | VERBOSE=$1; shift
12 |
13 | # stop after any command error
14 | set -e
15 |
16 | # echo commands when verbose
17 | if [ "$VERBOSE" != "0" ]; then
18 | set -x
19 | fi
20 |
21 | FILES="$TESTINCLUDEDIR/objc/*.h $TESTLOCALINCLUDEDIR/objc/*.h"
22 | CFLAGS='-fsyntax-only -Wno-unused-function -D_OBJC_PRIVATE_H_'
23 |
24 | INCLUDES=$(grep -h '#include' $FILES | grep -v ' defines.expected
27 |
28 | ERROR=
29 |
30 | extract_defines() {
31 | echo "$INCLUDES" | $1 - -dM -E \
32 | | sed 's/\(#define [^(]*\)[( ].*/\1/g' \
33 | | sort | uniq
34 | }
35 |
36 | get_new_lines() {
37 | diff --old-line-format= --unchanged-line-format= --new-line-format=%L -b $1 $2 || true
38 | }
39 |
40 | run_test() {
41 | extract_defines "$1 $CFLAGS" > base-defines
42 | extract_defines "$1 $CFLAGS $FILES" > objc-defines
43 | get_new_lines base-defines objc-defines > objc-defines-only
44 | if [[ ! -s objc-defines-only ]]; then
45 | echo "ERROR: objc-defines-only is somehow empty."
46 | exit 1
47 | fi
48 | get_new_lines defines.expected objc-defines-only > objc-defines-unexpected
49 | if [[ -s objc-defines-unexpected ]]; then
50 | echo "ERROR: unknown #defines found in headers. If these are expected, add them to test/defines.expected."
51 | echo "$1"
52 | cat objc-defines-unexpected
53 | ERROR=1
54 | fi
55 | rm base-defines objc-defines objc-defines-only objc-defines-unexpected
56 | }
57 |
58 | run_test "$COMPILE_C $CFLAGS"
59 | run_test "$COMPILE_CXX $CFLAGS"
60 | run_test "$COMPILE_M $CFLAGS"
61 | run_test "$COMPILE_MM $CFLAGS"
62 | for STDC in '99' '11' ; do
63 | run_test "$COMPILE_C $CFLAGS -std=c$STDC"
64 | run_test "$COMPILE_M $CFLAGS -std=c$STDC"
65 | done
66 | for STDCXX in '98' '03' '11' '14' '17' ; do
67 | run_test "$COMPILE_CXX $CFLAGS -std=c++$STDCXX"
68 | run_test "$COMPILE_MM $CFLAGS -std=c++$STDCXX"
69 | done
70 |
71 | if [[ $ERROR == "" ]]; then
72 | echo "No unexpected #defines found."
73 | else
74 | echo "Unknown #defines found in headers."
75 | fi
76 |
--------------------------------------------------------------------------------
/test/definitions.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | // DO NOT include anything else here
4 | #include
5 | // DO NOT include anything else here
6 | Class c = Nil;
7 | SEL s;
8 | IMP i;
9 | id o = nil;
10 | BOOL b = YES;
11 | BOOL b2 = NO;
12 | #if !__has_feature(objc_arc)
13 | __strong void *p;
14 | #endif
15 | id __unsafe_unretained u;
16 | #if __has_feature(objc_arc_weak)
17 | id __weak w;
18 | #endif
19 |
20 | void fn(void) __unused;
21 | void fn(void) {
22 | id __autoreleasing a __unused;
23 | }
24 |
25 | // check type inference for blocks returning YES and NO (rdar://10118972)
26 | BOOL (^block1)(void) = ^{ return YES; };
27 | BOOL (^block2)(void) = ^{ return NO; };
28 |
29 | #include "test.h"
30 |
31 | int main()
32 | {
33 | testassert(YES);
34 | testassert(!NO);
35 | #if __cplusplus
36 | testwarn("rdar://12371870 -Wnull-conversion");
37 | testassert(!(bool)nil);
38 | testassert(!(bool)Nil);
39 | #else
40 | testassert(!nil);
41 | testassert(!Nil);
42 | #endif
43 |
44 | #if __has_feature(objc_bool)
45 | // YES[array] is disallowed for objc just as true[array] is for C++
46 | #else
47 | // this will fail if YES and NO do not have enough parentheses
48 | int array[2] = { 888, 999 };
49 | testassert(NO[array] == 888);
50 | testassert(YES[array] == 999);
51 | #endif
52 |
53 | succeed(__FILE__);
54 | }
55 |
--------------------------------------------------------------------------------
/test/designatedinit.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | /* TEST_BUILD_OUTPUT
3 | .*designatedinit.m:\d+:\d+: warning: designated initializer should only invoke a designated initializer on 'super'.*
4 | .*designatedinit.m:\d+:\d+: note: .*
5 | .*designatedinit.m:\d+:\d+: warning: method override for the designated initializer of the superclass '-init' not found.*
6 | .*NSObject.h:\d+:\d+: note: .*
7 | END */
8 |
9 | #define NS_ENFORCE_NSOBJECT_DESIGNATED_INITIALIZER 1
10 | #include "test.h"
11 | #include
12 |
13 | @interface C : NSObject
14 | -(id) initWithInt:(int)i NS_DESIGNATED_INITIALIZER;
15 | @end
16 |
17 | @implementation C
18 | -(id) initWithInt:(int)__unused i {
19 | return [self init];
20 | }
21 | @end
22 |
23 | int main()
24 | {
25 | succeed(__FILE__);
26 | }
27 |
--------------------------------------------------------------------------------
/test/duplicateProtocols.m:
--------------------------------------------------------------------------------
1 |
2 | #include "test.h"
3 |
4 | // This test assumes
5 | // - that on launch we don't have NSCoding, NSSecureCoding, or NSDictionary, ie, libSystem doesn't contain those
6 | // - that after dlopening CF, we get NSDictionary and it conforms to NSSecureCoding which conforms to NSCoding
7 | // - that our NSCoding will be used if we ask either NSSecureCoding or NSDictionary if they conform to our test protocol
8 |
9 | @protocol NewNSCodingSuperProto
10 | @end
11 |
12 | @protocol NSCoding
13 | @end
14 |
15 | int main()
16 | {
17 | // Before we dlopen, make sure we are using our NSCoding, not the shared cache version
18 | Protocol* codingSuperProto = objc_getProtocol("NewNSCodingSuperProto");
19 | Protocol* codingProto = objc_getProtocol("NSCoding");
20 | if (@protocol(NewNSCodingSuperProto) != codingSuperProto) fail("Protocol mismatch");
21 | if (@protocol(NSCoding) != codingProto) fail("Protocol mismatch");
22 | if (!protocol_conformsToProtocol(codingProto, codingSuperProto)) fail("Our NSCoding should conform to NewNSCodingSuperProto");
23 |
24 | // Also make sure we don't yet have an NSSecureCoding or NSDictionary
25 | if (objc_getProtocol("NSSecureCoding")) fail("Test assumes we don't have NSSecureCoding yet");
26 | if (objc_getClass("NSDictionary")) fail("Test assumes we don't have NSDictionary yet");
27 |
28 | void *dl = dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY);
29 | if (!dl) fail("couldn't open CoreFoundation");
30 |
31 | // We should now have NSSecureCoding and NSDictionary
32 | Protocol* secureCodingProto = objc_getProtocol("NSSecureCoding");
33 | id dictionaryClass = objc_getClass("NSDictionary");
34 | if (!secureCodingProto) fail("Should have got NSSecureCoding from CoreFoundation");
35 | if (!dictionaryClass) fail("Should have got NSDictionary from CoreFoundation");
36 |
37 | // Now make sure that NSDictionary and NSSecureCoding find our new protocols
38 | if (!protocol_conformsToProtocol(secureCodingProto, codingProto)) fail("NSSecureCoding should conform to our NSCoding");
39 | if (!protocol_conformsToProtocol(secureCodingProto, codingSuperProto)) fail("NSSecureCoding should conform to our NewNSCodingSuperProto");
40 | if (!class_conformsToProtocol(dictionaryClass, codingProto)) fail("NSDictionary should conform to our NSCoding");
41 | if (!class_conformsToProtocol(dictionaryClass, codingSuperProto)) fail("NSDictionary should conform to our NewNSCodingSuperProto");
42 | }
43 |
--------------------------------------------------------------------------------
/test/duplicatedClasses.m:
--------------------------------------------------------------------------------
1 | // fixme rdar://24624435 duplicate class warning fails with the shared cache
2 | // OBJC_DISABLE_PREOPTIMIZATION=YES works around that problem.
3 |
4 | // TEST_ENV OBJC_DEBUG_DUPLICATE_CLASSES=YES OBJC_DISABLE_PREOPTIMIZATION=YES
5 | // TEST_CRASHES
6 | /*
7 | TEST_RUN_OUTPUT
8 | objc\[\d+\]: Class [^\s]+ is implemented in both .+ \(0x[0-9a-f]+\) and .+ \(0x[0-9a-f]+\)\. One of the two will be used\. Which one is undefined\.
9 | objc\[\d+\]: HALTED
10 | OR
11 | OK: duplicatedClasses.m
12 | END
13 | */
14 |
15 | #include "test.h"
16 | #include "testroot.i"
17 |
18 | @interface WKWebView : TestRoot @end
19 | @implementation WKWebView @end
20 |
21 | int main()
22 | {
23 | void *dl = dlopen("/System/Library/Frameworks/WebKit.framework/WebKit", RTLD_LAZY);
24 | if (!dl) fail("couldn't open WebKit");
25 | fail("should have crashed already");
26 | }
27 |
--------------------------------------------------------------------------------
/test/fakeRealizedClass.m:
--------------------------------------------------------------------------------
1 | /*
2 | Make sure we detect classes with the RW_REALIZED bit set in the binary. rdar://problem/67692760
3 | TEST_CONFIG OS=macosx
4 | TEST_CRASHES
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: realized class 0x[0-9a-fA-F]+ has corrupt data pointer: malloc_size\(0x[0-9a-fA-F]+\) = 0
7 | objc\[\d+\]: HALTED
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 |
15 | #define RW_REALIZED (1U<<31)
16 |
17 | struct ObjCClass {
18 | struct ObjCClass * __ptrauth_objc_isa_pointer isa;
19 | struct ObjCClass * __ptrauth_objc_super_pointer superclass;
20 | void *cachePtr;
21 | uintptr_t zero;
22 | uintptr_t data;
23 | };
24 |
25 | struct ObjCClass_ro {
26 | uint32_t flags;
27 | uint32_t instanceStart;
28 | uint32_t instanceSize;
29 | #ifdef __LP64__
30 | uint32_t reserved;
31 | #endif
32 |
33 | union {
34 | const uint8_t * ivarLayout;
35 | struct ObjCClass * nonMetaClass;
36 | };
37 |
38 | const char * name;
39 | struct ObjCMethodList * __ptrauth_objc_method_list_pointer baseMethodList;
40 | struct protocol_list_t * baseProtocols;
41 | const struct ivar_list_t * ivars;
42 |
43 | const uint8_t * weakIvarLayout;
44 | struct property_list_t *baseProperties;
45 | };
46 |
47 | extern struct ObjCClass OBJC_METACLASS_$_NSObject;
48 | extern struct ObjCClass OBJC_CLASS_$_NSObject;
49 |
50 | struct ObjCClass_ro FakeSuperclassRO = {
51 | .flags = RW_REALIZED
52 | };
53 |
54 | struct ObjCClass FakeSuperclass = {
55 | &OBJC_METACLASS_$_NSObject,
56 | &OBJC_METACLASS_$_NSObject,
57 | NULL,
58 | 0,
59 | (uintptr_t)&FakeSuperclassRO
60 | };
61 |
62 | struct ObjCClass_ro FakeSubclassRO;
63 |
64 | struct ObjCClass FakeSubclass = {
65 | &FakeSuperclass,
66 | &FakeSuperclass,
67 | NULL,
68 | 0,
69 | (uintptr_t)&FakeSubclassRO
70 | };
71 |
72 | static struct ObjCClass *class_ptr __attribute__((used)) __attribute((section("__DATA,__objc_nlclslist"))) = &FakeSubclass;
73 |
74 | int main() {}
75 |
--------------------------------------------------------------------------------
/test/fakeRealizedClass2.m:
--------------------------------------------------------------------------------
1 | /*
2 | Variant on fakeRealizedClass which tests a fake class with no superclass rdar://problem/67692760
3 | TEST_CONFIG OS=macosx
4 | TEST_CRASHES
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: realized class 0x[0-9a-fA-F]+ has corrupt data pointer: malloc_size\(0x[0-9a-fA-F]+\) = 0
7 | objc\[\d+\]: HALTED
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 |
15 | #define RW_REALIZED (1U<<31)
16 |
17 | struct ObjCClass {
18 | struct ObjCClass * __ptrauth_objc_isa_pointer isa;
19 | struct ObjCClass * __ptrauth_objc_super_pointer superclass;
20 | void *cachePtr;
21 | uintptr_t zero;
22 | uintptr_t data;
23 | };
24 |
25 | struct ObjCClass_ro {
26 | uint32_t flags;
27 | uint32_t instanceStart;
28 | uint32_t instanceSize;
29 | #ifdef __LP64__
30 | uint32_t reserved;
31 | #endif
32 |
33 | union {
34 | const uint8_t * ivarLayout;
35 | struct ObjCClass * nonMetaClass;
36 | };
37 |
38 | const char * name;
39 | struct ObjCMethodList * __ptrauth_objc_method_list_pointer baseMethodList;
40 | struct protocol_list_t * baseProtocols;
41 | const struct ivar_list_t * ivars;
42 |
43 | const uint8_t * weakIvarLayout;
44 | struct property_list_t *baseProperties;
45 | };
46 |
47 | extern struct ObjCClass OBJC_METACLASS_$_NSObject;
48 | extern struct ObjCClass OBJC_CLASS_$_NSObject;
49 |
50 | struct ObjCClass_ro FakeSuperclassRO = {
51 | .flags = RW_REALIZED
52 | };
53 |
54 | struct ObjCClass FakeSuperclass = {
55 | &OBJC_METACLASS_$_NSObject,
56 | NULL,
57 | NULL,
58 | 0,
59 | (uintptr_t)&FakeSuperclassRO
60 | };
61 |
62 | struct ObjCClass_ro FakeSubclassRO;
63 |
64 | struct ObjCClass FakeSubclass = {
65 | &FakeSuperclass,
66 | &FakeSuperclass,
67 | NULL,
68 | 0,
69 | (uintptr_t)&FakeSubclassRO
70 | };
71 |
72 | static struct ObjCClass *class_ptr __attribute__((used)) __attribute((section("__DATA,__objc_nlclslist"))) = &FakeSubclass;
73 |
74 | int main() {}
75 |
--------------------------------------------------------------------------------
/test/fork.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | void *flushthread(void *arg __unused)
6 | {
7 | while (1) {
8 | _objc_flush_caches(nil);
9 | }
10 | }
11 |
12 | int main()
13 | {
14 | pthread_t th;
15 | pthread_create(&th, nil, &flushthread, nil);
16 |
17 | alarm(120);
18 |
19 | [NSObject self];
20 | [NSObject self];
21 |
22 | int max = is_guardmalloc() ? 10: 100;
23 |
24 | for (int i = 0; i < max; i++) {
25 | pid_t child;
26 | switch ((child = fork())) {
27 | case -1:
28 | abort();
29 | case 0:
30 | // child
31 | alarm(10);
32 | [NSObject self];
33 | _exit(0);
34 | default: {
35 | // parent
36 | int result = 0;
37 | while (waitpid(child, &result, 0) < 0) {
38 | if (errno != EINTR) {
39 | fail("waitpid failed (errno %d %s)",
40 | errno, strerror(errno));
41 | }
42 | }
43 | if (!WIFEXITED(result)) {
44 | fail("child crashed (waitpid result %d)", result);
45 | }
46 |
47 | [NSObject self];
48 | break;
49 | }
50 | }
51 | }
52 |
53 | succeed(__FILE__ " parent");
54 | }
55 |
--------------------------------------------------------------------------------
/test/forkInitializeDisabled.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG OS=macosx MEM=mrc ARCH=x86_64
3 | (confused by ARC which loads Foundation which provokes more +initialize logs)
4 | (also confused by i386 OS_object +load workaround)
5 |
6 | TEST_ENV OBJC_PRINT_INITIALIZE_METHODS=YES
7 |
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: INITIALIZE: disabling \+initialize fork safety enforcement because the app has a __DATA,__objc_fork_ok section
10 | OK: forkInitializeDisabled\.m
11 | END
12 | */
13 |
14 | #include "test.h"
15 |
16 | asm(".section __DATA, __objc_fork_ok\n.long 0\n");
17 |
18 | int main()
19 | {
20 | succeed(__FILE__);
21 | }
22 |
--------------------------------------------------------------------------------
/test/forkInitializeSingleThreaded.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_RUN_OUTPUT
3 | OK: forkInitialize\.m
4 | OK: forkInitialize\.m
5 | END
6 | */
7 | #define SINGLETHREADED 1
8 | #include "forkInitialize.m"
9 |
--------------------------------------------------------------------------------
/test/forwardDefault.m:
--------------------------------------------------------------------------------
1 | /*
2 | no arc, rdar://11368528 confused by Foundation
3 | TEST_CONFIG MEM=mrc
4 | TEST_CRASHES
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: \+\[NSObject fakeorama\]: unrecognized selector sent to instance 0x[0-9a-fA-F]+ \(no message forward handler is installed\)
7 | objc\[\d+\]: HALTED
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 |
15 | @interface NSObject (Fake)
16 | -(void)fakeorama;
17 | @end
18 |
19 | int main()
20 | {
21 | [NSObject fakeorama];
22 | fail("should have crashed");
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/test/forwardDefaultStret.m:
--------------------------------------------------------------------------------
1 | /*
2 | no arc, rdar://11368528 confused by Foundation
3 | TEST_CONFIG MEM=mrc
4 | TEST_CRASHES
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: \+\[NSObject fakeorama\]: unrecognized selector sent to instance 0x[0-9a-fA-F]+ \(no message forward handler is installed\)
7 | objc\[\d+\]: HALTED
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 |
15 | @interface NSObject (Fake)
16 | -(struct stret)fakeorama;
17 | @end
18 |
19 | int main()
20 | {
21 | [NSObject fakeorama];
22 | fail("should have crashed");
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/test/future.h:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | @interface Sub1 : TestRoot
4 | +(int)method;
5 | +(Class)classref;
6 | @end
7 |
8 | @interface Sub2 : TestRoot
9 | +(int)method;
10 | +(Class)classref;
11 | @end
12 |
13 | @interface SubSub1 : Sub1 @end
14 |
15 | @interface SubSub2 : Sub2 @end
16 |
--------------------------------------------------------------------------------
/test/future.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/future0.m -o future0.dylib -dynamiclib
4 | $C{COMPILE} $DIR/future2.m -x none future0.dylib -o future2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/future.m -x none future0.dylib -o future.exe
6 | END
7 | */
8 |
9 | #include "test.h"
10 |
11 | #if __has_feature(objc_arc)
12 |
13 | int main()
14 | {
15 | testwarn("rdar://10041403 future class API is not ARC-compatible");
16 | succeed(__FILE__);
17 | }
18 |
19 |
20 | #else
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include "future.h"
27 |
28 | @implementation Sub2
29 | +(int)method {
30 | return 2;
31 | }
32 | +(Class)classref {
33 | return [Sub2 class];
34 | }
35 | @end
36 |
37 | @implementation SubSub2
38 | +(int)method {
39 | return 1 + [super method];
40 | }
41 | @end
42 |
43 | int main()
44 | {
45 | Class oldTestRoot;
46 | Class oldSub1;
47 | Class newSub1;
48 |
49 | // objc_getFutureClass with existing class
50 | oldTestRoot = objc_getFutureClass("TestRoot");
51 | testassert(oldTestRoot == [TestRoot class]);
52 | testassert(! _class_isFutureClass(oldTestRoot));
53 |
54 | // objc_getFutureClass with missing class
55 | oldSub1 = objc_getFutureClass("Sub1");
56 | testassert(oldSub1);
57 | testassert(malloc_size((__bridge void*)oldSub1) > 0);
58 | testassert(objc_getClass("Sub1") == Nil);
59 | testassert(_class_isFutureClass(oldSub1));
60 | testassert(0 == strcmp(class_getName(oldSub1), "Sub1"));
61 | testassert(object_getClass(oldSub1) == Nil); // CF expects this
62 |
63 | // objc_getFutureClass a second time
64 | testassert(oldSub1 == objc_getFutureClass("Sub1"));
65 |
66 | // Load class Sub1
67 | dlopen("future2.dylib", 0);
68 |
69 | // Verify use of future class
70 | newSub1 = objc_getClass("Sub1");
71 | testassert(oldSub1 == newSub1);
72 | testassert(newSub1 == [newSub1 classref]);
73 | testassert(newSub1 == class_getSuperclass(objc_getClass("SubSub1")));
74 | testassert(! _class_isFutureClass(newSub1));
75 |
76 | testassert(1 == [oldSub1 method]);
77 | testassert(1 == [newSub1 method]);
78 |
79 | succeed(__FILE__);
80 | }
81 |
82 | #endif
83 |
--------------------------------------------------------------------------------
/test/future0.m:
--------------------------------------------------------------------------------
1 | #include "future.h"
2 | #include "testroot.i"
3 |
--------------------------------------------------------------------------------
/test/future2.m:
--------------------------------------------------------------------------------
1 | #include "future.h"
2 |
3 |
4 | @implementation Sub1
5 | +(Class)classref {
6 | return [Sub1 class];
7 | }
8 | +(int)method {
9 | return 1;
10 | }
11 | @end
12 |
13 | @implementation SubSub1
14 | +(int)method {
15 | return 1 + [super method];
16 | }
17 | @end
18 |
--------------------------------------------------------------------------------
/test/gdb.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -Wno-deprecated-declarations
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 | #include
7 |
8 | #define SwiftV1MangledName4 "_TtC6Swiftt13SwiftV1Class4"
9 | __attribute__((objc_runtime_name(SwiftV1MangledName4)))
10 | @interface SwiftV1Class4 : TestRoot @end
11 | @implementation SwiftV1Class4 @end
12 |
13 | int main()
14 | {
15 | // Class hashes
16 | Class result;
17 |
18 | // Class should not be realized yet
19 | // fixme not true during class hash rearrangement
20 | // result = NXMapGet(gdb_objc_realized_classes, "TestRoot");
21 | // testassert(!result);
22 |
23 | [TestRoot class];
24 | // Now class should be realized
25 |
26 | if (!testdyld3()) {
27 | // In dyld3 mode, the class will be in the launch closure and not in our table.
28 | result = (__bridge Class)(NXMapGet(gdb_objc_realized_classes, "TestRoot"));
29 | testassert(result);
30 | testassert(result == [TestRoot class]);
31 | }
32 |
33 | Class dynamic = objc_allocateClassPair([TestRoot class], "Dynamic", 0);
34 | objc_registerClassPair(dynamic);
35 | result = (__bridge Class)(NXMapGet(gdb_objc_realized_classes, "Dynamic"));
36 | testassert(result);
37 | testassert(result == dynamic);
38 |
39 | Class *realizedClasses = objc_copyRealizedClassList(NULL);
40 | bool foundTestRoot = false;
41 | bool foundDynamic = false;
42 | for (Class *cursor = realizedClasses; *cursor; cursor++) {
43 | if (*cursor == [TestRoot class])
44 | foundTestRoot = true;
45 | if (*cursor == dynamic)
46 | foundDynamic = true;
47 | }
48 | free(realizedClasses);
49 | testassert(foundTestRoot);
50 | testassert(foundDynamic);
51 |
52 | result = (__bridge Class)(NXMapGet(gdb_objc_realized_classes, "DoesNotExist"));
53 | testassert(!result);
54 |
55 | // Class structure decoding
56 |
57 | uintptr_t *maskp = (uintptr_t *)dlsym(RTLD_DEFAULT, "objc_debug_class_rw_data_mask");
58 | testassert(maskp);
59 |
60 | // Raw class names
61 | testassert(strcmp(objc_debug_class_getNameRaw([SwiftV1Class4 class]), SwiftV1MangledName4) == 0);
62 | testassert(strcmp(objc_debug_class_getNameRaw([TestRoot class]), "TestRoot") == 0);
63 |
64 |
65 | succeed(__FILE__);
66 | }
67 |
--------------------------------------------------------------------------------
/test/get_task_allow_entitlement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | get-task-allow
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/test/headers.c:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $DIR/headers.sh '$C{TESTINCLUDEDIR}' '$C{TESTLOCALINCLUDEDIR}' '$C{COMPILE_C}' '$C{COMPILE_CXX}' '$C{COMPILE_M}' '$C{COMPILE_MM}' '$VERBOSE'
4 | $C{COMPILE_C} $DIR/headers.c -o headers.exe
5 | END
6 |
7 | allow `sh -x` output from headers.sh
8 | TEST_BUILD_OUTPUT
9 | (\+ .*\n)*(\+ .*)?done
10 | END
11 | */
12 |
13 |
14 | #include "test.h"
15 |
16 | int main()
17 | {
18 | succeed(__FILE__);
19 | }
20 |
--------------------------------------------------------------------------------
/test/headers.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Compile every exported ObjC header as if it were a file in every language.
4 | # This script is executed by test headers.c's TEST_BUILD command.
5 |
6 | TESTINCLUDEDIR=$1; shift
7 | TESTLOCALINCLUDEDIR=$1; shift
8 | COMPILE_C=$1; shift
9 | COMPILE_CXX=$1; shift
10 | COMPILE_M=$1; shift
11 | COMPILE_MM=$1; shift
12 | VERBOSE=$1; shift
13 |
14 | # stop after any command error
15 | set -e
16 |
17 | # echo commands when verbose
18 | if [ "$VERBOSE" != "0" ]; then
19 | set -x
20 | fi
21 |
22 | FILES="$TESTINCLUDEDIR/objc/*.h $TESTLOCALINCLUDEDIR/objc/*.h"
23 | CFLAGS='-fsyntax-only -Wno-unused-function -D_OBJC_PRIVATE_H_'
24 |
25 | $COMPILE_C $CFLAGS $FILES
26 | $COMPILE_CXX $CFLAGS $FILES
27 | $COMPILE_M $CFLAGS $FILES
28 | $COMPILE_MM $CFLAGS $FILES
29 | for STDC in '99' '11' ; do
30 | $COMPILE_C $CFLAGS $FILES -std=c$STDC
31 | $COMPILE_M $CFLAGS $FILES -std=c$STDC
32 | done
33 | for STDCXX in '98' '03' '11' '14' '17' ; do
34 | $COMPILE_CXX $CFLAGS $FILES -std=c++$STDCXX
35 | $COMPILE_MM $CFLAGS $FILES -std=c++$STDCXX
36 | done
37 |
38 | echo done
39 |
--------------------------------------------------------------------------------
/test/imageAPIs.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include
4 | #include
5 |
6 | #include "test.h"
7 | #include "testroot.i"
8 |
9 | @interface Foo: TestRoot @end
10 | @implementation Foo @end
11 | @interface Bar: Foo @end
12 | @implementation Bar @end
13 |
14 | int main(int argc __unused, const char **argv)
15 | {
16 | // Make sure we show up in the list of image names.
17 | unsigned int count;
18 | const char **imageNames = objc_copyImageNames(&count);
19 | testassert(imageNames);
20 | testassertequal(imageNames[count], NULL);
21 |
22 | char myBaseName[MAXPATHLEN];
23 | basename_r(argv[0], myBaseName);
24 | const char *myImageName = NULL;
25 | for (unsigned int i = 0; i < count; i++) {
26 | char imageBaseName[MAXPATHLEN];
27 | basename_r(imageNames[i], imageBaseName);
28 | if (strcmp(imageBaseName, myBaseName) == 0)
29 | myImageName = imageNames[i];
30 | }
31 | testassert(myImageName);
32 | free(imageNames);
33 |
34 | // Make sure our classes show up in the class names.
35 | const char **classNames = objc_copyClassNamesForImage(myImageName, &count);
36 | testassert(classNames);
37 | testassertequal(classNames[count], NULL);
38 |
39 | int sawFoo = 0;
40 | int sawBar = 0;
41 | for (unsigned int i = 0; i < count; i++) {
42 | if (strcmp(classNames[i], "Foo") == 0)
43 | sawFoo++;
44 | if (strcmp(classNames[i], "Bar") == 0)
45 | sawBar++;
46 | }
47 | testassertequal(sawFoo, 1);
48 | testassertequal(sawBar, 1);
49 | free(classNames);
50 |
51 | // Make sure our classes show up in the classes list.
52 | sawFoo = 0;
53 | sawBar = 0;
54 | Class *classes = objc_copyClassesForImage(myImageName, &count);
55 | testassert(classes);
56 | testassertequal(classes[count], NULL);
57 | for (unsigned int i = 0; i < count; i++) {
58 | if (strcmp(class_getName(classes[i]), "Foo") == 0)
59 | sawFoo++;
60 | if (strcmp(class_getName(classes[i]), "Bar") == 0)
61 | sawBar++;
62 | }
63 | testassertequal(sawFoo, 1);
64 | testassertequal(sawBar, 1);
65 | free(classes);
66 |
67 | // Make sure bad names return NULL.
68 | testassertequal(objc_copyClassNamesForImage("aaaaaaaaaaaaaaaaaaa", NULL), NULL);
69 | testassertequal(objc_copyClassesForImage("aaaaaaaaaaaaaaaaaaa", NULL), NULL);
70 |
71 | succeed(__FILE__);
72 | }
73 |
--------------------------------------------------------------------------------
/test/imageorder.h:
--------------------------------------------------------------------------------
1 | extern int state;
2 | extern int cstate;
3 |
4 | OBJC_ROOT_CLASS
5 | @interface Super { id isa; }
6 | +(void) method;
7 | +(void) method0;
8 | @end
9 |
10 | @interface Super (cat1)
11 | +(void) method1;
12 | @end
13 |
14 | @interface Super (cat2)
15 | +(void) method2;
16 | @end
17 |
18 | @interface Super (cat3)
19 | +(void) method3;
20 | @end
21 |
--------------------------------------------------------------------------------
/test/imageorder.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/imageorder1.m -o imageorder1.dylib -dynamiclib
4 | $C{COMPILE} $DIR/imageorder2.m -x none imageorder1.dylib -o imageorder2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/imageorder3.m -x none imageorder2.dylib imageorder1.dylib -o imageorder3.dylib -dynamiclib
6 | $C{COMPILE} $DIR/imageorder.m -x none imageorder3.dylib imageorder2.dylib imageorder1.dylib -o imageorder.exe
7 | END
8 | */
9 |
10 | #include "test.h"
11 | #include "imageorder.h"
12 | #include
13 | #include
14 |
15 | int main()
16 | {
17 | // +load methods and C static initializers
18 | testassert(state == 3);
19 | testassert(cstate == 3);
20 |
21 | Class cls = objc_getClass("Super");
22 | testassert(cls);
23 |
24 | // make sure all categories arrived
25 | state = -1;
26 | [Super method0];
27 | testassert(state == 0);
28 | [Super method1];
29 | testassert(state == 1);
30 | [Super method2];
31 | testassert(state == 2);
32 | [Super method3];
33 | testassert(state == 3);
34 |
35 | // make sure imageorder3.dylib is the last category to attach
36 | state = 0;
37 | [Super method];
38 | testassert(state == 3);
39 |
40 | succeed(__FILE__);
41 | }
42 |
--------------------------------------------------------------------------------
/test/imageorder1.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "imageorder.h"
3 |
4 | int state = -1;
5 | int cstate = 0;
6 |
7 | static void c1(void) __attribute__((constructor));
8 | static void c1(void)
9 | {
10 | testassert(state == 1); // +load before C/C++
11 | testassert(cstate == 0);
12 | cstate = 1;
13 | }
14 |
15 |
16 | #if __clang__
17 | #pragma clang diagnostic push
18 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
19 | #endif
20 |
21 | @implementation Super (cat1)
22 | +(void) method {
23 | fail("+[Super(cat1) method] not replaced!");
24 | }
25 | +(void) method1 {
26 | state = 1;
27 | }
28 | +(void) load {
29 | testassert(state == 0);
30 | state = 1;
31 | }
32 | @end
33 |
34 | #if __clang__
35 | #pragma clang diagnostic pop
36 | #endif
37 |
38 |
39 | @implementation Super
40 | +(void) initialize { }
41 | +(void) method {
42 | fail("+[Super method] not replaced!");
43 | }
44 | +(void) method0 {
45 | state = 0;
46 | }
47 | +(void) load {
48 | testassert(state == -1);
49 | state = 0;
50 | }
51 | @end
52 |
53 |
--------------------------------------------------------------------------------
/test/imageorder2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "imageorder.h"
3 |
4 | static void c2(void) __attribute__((constructor));
5 | static void c2(void)
6 | {
7 | testassert(state == 2); // +load before C/C++
8 | testassert(cstate == 1);
9 | cstate = 2;
10 | }
11 |
12 |
13 | #if __clang__
14 | #pragma clang diagnostic push
15 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
16 | #endif
17 |
18 | @implementation Super (cat2)
19 | +(void) method {
20 | fail("+[Super(cat2) method] not replaced!");
21 | }
22 | +(void) method2 {
23 | state = 2;
24 | }
25 | +(void) load {
26 | testassert(state == 1);
27 | state = 2;
28 | }
29 | @end
30 |
31 | #if __clang__
32 | #pragma clang diagnostic pop
33 | #endif
34 |
--------------------------------------------------------------------------------
/test/imageorder3.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "imageorder.h"
3 |
4 | static void c3(void) __attribute__((constructor));
5 | static void c3(void)
6 | {
7 | testassert(state == 3); // +load before C/C++
8 | testassert(cstate == 2);
9 | cstate = 3;
10 | }
11 |
12 |
13 | #if __clang__
14 | #pragma clang diagnostic push
15 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
16 | #endif
17 |
18 | @implementation Super (cat3)
19 | +(void) method {
20 | state = 3;
21 | }
22 | +(void) method3 {
23 | state = 3;
24 | }
25 | +(void) load {
26 | testassert(state == 2);
27 | state = 3;
28 | }
29 | @end
30 |
31 | #if __clang__
32 | #pragma clang diagnostic pop
33 | #endif
34 |
--------------------------------------------------------------------------------
/test/imports.c:
--------------------------------------------------------------------------------
1 | /*
2 | Disallow some imports into and exports from libobjc.A.dylib.
3 |
4 | To debug, re-run libobjc's link command with
5 | -Xlinker -dead_strip -Xlinker -why_live -Xlinker SYMBOL_NAME_HERE
6 |
7 | Disallowed imports (nm -u):
8 | ___cxa_guard_acquire (C++ function-scope static initializer)
9 | ___cxa_guard_release (C++ function-scope static initializer)
10 | ___cxa_atexit (C++ static destructor)
11 | weak external (any weak externals, including operators new and delete)
12 |
13 | Whitelisted imports:
14 | weak external ____chkstk_darwin (from libSystem)
15 | weak external _objc_bp_assist_cfg_np (from libSystem)
16 |
17 | Disallowed exports (nm -U):
18 | __Z* (any C++-mangled export)
19 | weak external (any weak externals, including operators new and delete)
20 |
21 | fixme rdar://13354718 should disallow anything from libc++ (i.e. not libc++abi)
22 | */
23 |
24 | /*
25 | TEST_BUILD
26 | echo $C{XCRUN} nm -m -arch $C{ARCH} $C{TESTLIB}
27 | $C{XCRUN} nm -u -m -arch $C{ARCH} $C{TESTLIB} | grep -v 'weak external ____chkstk_darwin \(from libSystem\)' | grep -v 'weak external _objc_bp_assist_cfg_np \(from libSystem\)' | egrep '(weak external| external (___cxa_atexit|___cxa_guard_acquire|___cxa_guard_release))' || true
28 | $C{XCRUN} nm -U -m -arch $C{ARCH} $C{TESTLIB} | egrep '(weak external| external __Z)' || true
29 | $C{COMPILE_C} $DIR/imports.c -o imports.exe
30 | END
31 |
32 | TEST_BUILD_OUTPUT
33 | .*libobjc.A.dylib
34 | END
35 | */
36 |
37 | #include "test.h"
38 | int main()
39 | {
40 | succeed(__FILE__);
41 | }
42 |
--------------------------------------------------------------------------------
/test/include-warnings.c:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/include-warnings.c -o include-warnings.exe -Wsystem-headers -Weverything -Wno-undef -Wno-old-style-cast -Wno-nullability-extension -Wno-c++98-compat 2>&1 | grep -v 'In file' | grep objc || true
4 | END
5 |
6 | TEST_RUN_OUTPUT
7 | OK: includes.c
8 | END
9 | */
10 |
11 | // Detect warnings inside any header.
12 | // The build command above filters out warnings inside non-objc headers
13 | // (which are noisy with -Weverything).
14 | // -Wno-undef suppresses warnings about `#if __cplusplus` and the like.
15 | // -Wno-old-style-cast is tough to avoid in mixed C/C++ code.
16 | // -Wno-nullability-extension disables a warning about non-portable
17 | // _Nullable etc which we already handle correctly in objc-abi.h.
18 | // -Wno-c++98-compat disables warnings about things that already
19 | // have guards against C++98.
20 |
21 | #include "includes.c"
22 |
--------------------------------------------------------------------------------
/test/includes-objc2.c:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -D__OBJC2__
2 |
3 | // Verify that all headers can be included in any language, even if
4 | // the client is C code that defined __OBJC2__.
5 |
6 | // This is the definition that Instruments uses in its build.
7 | #if defined(__OBJC2__)
8 | #undef __OBJC2__
9 | #endif
10 | #define __OBJC2__ 1
11 |
12 | #define NAME "includes-objc2.c"
13 | #include "includes.c"
14 |
--------------------------------------------------------------------------------
/test/includes.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | // Verify that all headers can be included in any language.
4 | // See also test/include-warnings.c which checks for warnings in these headers.
5 | // See also test/includes-objc2.c which checks for safety even if
6 | // the client is C code that defined __OBJC2__.
7 |
8 | #ifndef NAME
9 | #define NAME "includes.c"
10 | #endif
11 |
12 | #include
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | #if TARGET_OS_OSX
34 | #include
35 | #include
36 | #include
37 | #endif
38 |
39 | #pragma clang diagnostic push
40 | #pragma clang diagnostic ignored "-Weverything"
41 | #include "test.h"
42 | #pragma clang diagnostic pop
43 |
44 | int main()
45 | {
46 | succeed(NAME);
47 | }
48 |
--------------------------------------------------------------------------------
/test/instanceSize.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 |
8 | @interface Sub1 : TestRoot {
9 | // id isa; // 0..4
10 | BOOL b; // 4..5
11 | }
12 | @end
13 |
14 | @implementation Sub1 @end
15 |
16 | @interface Sub2 : Sub1 {
17 | // id isa // 0..4 0..8
18 | // BOOL b // 4..5 8..9
19 | BOOL b2; // 5..6 9..10
20 | id o; // 8..12 16..24
21 | }
22 | @end
23 | @implementation Sub2 @end
24 |
25 | @interface Sub3 : Sub1 {
26 | // id isa; // 0..4 0..8
27 | // BOOL b; // 4..5 8..9
28 | id o; // 8..12 16..24
29 | BOOL b2; // 12..13 24..25
30 | }
31 | @end
32 | @implementation Sub3 @end
33 |
34 | int main()
35 | {
36 | testassert(sizeof(id) == class_getInstanceSize([TestRoot class]));
37 | testassert(2*sizeof(id) == class_getInstanceSize([Sub1 class]));
38 | testassert(3*sizeof(id) == class_getInstanceSize([Sub2 class]));
39 | testassert(4*sizeof(id) == class_getInstanceSize([Sub3 class]));
40 |
41 | #if !__has_feature(objc_arc)
42 | id o;
43 |
44 | o = [TestRoot new];
45 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
46 | RELEASE_VAR(o);
47 | o = [Sub1 new];
48 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
49 | RELEASE_VAR(o);
50 | o = [Sub2 new];
51 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
52 | RELEASE_VAR(o);
53 | o = [Sub3 new];
54 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
55 | RELEASE_VAR(o);
56 | #endif
57 |
58 | succeed(__FILE__);
59 | }
60 |
--------------------------------------------------------------------------------
/test/ismeta.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | int main()
8 | {
9 | testassert(!class_isMetaClass([TestRoot class]));
10 | testassert(class_isMetaClass(object_getClass([TestRoot class])));
11 | testassert(!class_isMetaClass(nil));
12 | succeed(__FILE__);
13 | }
14 |
--------------------------------------------------------------------------------
/test/ivarSlide.h:
--------------------------------------------------------------------------------
1 | @interface Super : TestRoot {
2 | @public
3 | #if OLD
4 | // nothing
5 | #else
6 | char superIvar;
7 | #endif
8 | }
9 | @end
10 |
11 |
12 | @interface ShrinkingSuper : TestRoot {
13 | @public
14 | #if OLD
15 | id superIvar[5];
16 | __weak id superIvar2[5];
17 | #else
18 | // nothing
19 | #endif
20 | }
21 | @end;
22 |
23 |
24 | @interface MoreStrongSuper : TestRoot {
25 | @public
26 | #if OLD
27 | void *superIvar;
28 | #else
29 | id superIvar;
30 | #endif
31 | }
32 | @end;
33 |
34 |
35 | @interface MoreWeakSuper : TestRoot {
36 | @public
37 | #if OLD
38 | id superIvar;
39 | #else
40 | __weak id superIvar;
41 | #endif
42 | }
43 | @end;
44 |
45 | @interface MoreWeak2Super : TestRoot {
46 | @public
47 | #if OLD
48 | void *superIvar;
49 | #else
50 | __weak id superIvar;
51 | #endif
52 | }
53 | @end;
54 |
55 | @interface LessStrongSuper : TestRoot {
56 | @public
57 | #if OLD
58 | id superIvar;
59 | #else
60 | void *superIvar;
61 | #endif
62 | }
63 | @end;
64 |
65 | @interface LessWeakSuper : TestRoot {
66 | @public
67 | #if OLD
68 | __weak id superIvar;
69 | #else
70 | id superIvar;
71 | #endif
72 | }
73 | @end;
74 |
75 | @interface LessWeak2Super : TestRoot {
76 | @public
77 | #if OLD
78 | __weak id superIvar;
79 | #else
80 | void *superIvar;
81 | #endif
82 | }
83 | @end;
84 |
85 | @interface NoGCChangeSuper : TestRoot {
86 | @public
87 | intptr_t d;
88 | char superc1;
89 | #if OLD
90 | // nothing
91 | #else
92 | char superc2;
93 | #endif
94 | }
95 | @end
96 |
97 | @interface RunsOf15 : TestRoot {
98 | @public
99 | id scan1;
100 | intptr_t skip15[15];
101 | id scan15[15];
102 | intptr_t skip15_2[15];
103 | id scan15_2[15];
104 | #if OLD
105 | // nothing
106 | #else
107 | intptr_t skip1;
108 | #endif
109 | }
110 | @end
111 |
--------------------------------------------------------------------------------
/test/ivarSlide1.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include
3 | #include
4 |
5 | #define OLD 0
6 | #include "ivarSlide.h"
7 |
8 | #include "testroot.i"
9 |
10 | @implementation Super @end
11 |
12 | @implementation ShrinkingSuper @end
13 |
14 | @implementation MoreStrongSuper @end
15 | @implementation LessStrongSuper @end
16 | @implementation MoreWeakSuper @end
17 | @implementation MoreWeak2Super @end
18 | @implementation LessWeakSuper @end
19 | @implementation LessWeak2Super @end
20 | @implementation NoGCChangeSuper @end
21 | @implementation RunsOf15 @end
22 |
--------------------------------------------------------------------------------
/test/libraryPath.c:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -lobjc
2 |
3 | #include "test.h"
4 | #include
5 |
6 | // We use DYLD_LIBRARY_PATH to run the tests against a particular copy of
7 | // libobjc. If this fails somehow (path is wrong, codesigning prevents loading,
8 | // etc.) then the typical result is a silent failure and we end up testing
9 | // /usr/lib/libobjc.A.dylib instead. This test detects when DYLD_LIBRARY_PATH is
10 | // set but libobjc isn't loaded from it.
11 | int main(int argc __unused, char **argv) {
12 | char *containingDirectory = realpath(dirname(argv[0]), NULL);
13 | testprintf("containingDirectory is %s\n", containingDirectory);
14 |
15 | char *dyldLibraryPath = getenv("DYLD_LIBRARY_PATH");
16 | testprintf("DYLD_LIBRARY_PATH is %s\n", dyldLibraryPath);
17 |
18 | if (dyldLibraryPath != NULL && strlen(dyldLibraryPath) > 0) {
19 | int foundMatch = 0;
20 | int foundNonMatch = 0;
21 |
22 | dyldLibraryPath = strdup(dyldLibraryPath);
23 |
24 | Dl_info info;
25 | int success = dladdr((void *)objc_msgSend, &info);
26 | testassert(success);
27 |
28 | testprintf("libobjc is located at %s\n", info.dli_fname);
29 |
30 | char *cursor = dyldLibraryPath;
31 | char *path;
32 | while ((path = strsep(&cursor, ":"))) {
33 | char *resolved = realpath(path, NULL);
34 | testprintf("Resolved %s to %s\n", path, resolved);
35 | if (strcmp(resolved, containingDirectory) == 0) {
36 | testprintf("This is equal to our containing directory, ignoring.\n");
37 | continue;
38 | }
39 | testprintf("Comparing %s and %s\n", resolved, info.dli_fname);
40 | int comparison = strncmp(resolved, info.dli_fname, strlen(resolved));
41 | free(resolved);
42 | if (comparison == 0) {
43 | testprintf("Found a match!\n");
44 | foundMatch = 1;
45 | break;
46 | } else {
47 | foundNonMatch = 1;
48 | }
49 | }
50 |
51 | testprintf("Finished searching, foundMatch=%d foundNonMatch=%d\n", foundMatch, foundNonMatch);
52 | testassert(foundMatch || !foundNonMatch);
53 | }
54 | succeed(__FILE__);
55 | }
56 |
--------------------------------------------------------------------------------
/test/literals.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 |
3 | #import
4 | #import
5 | #import
6 | #import
7 | #import
8 | #include "test.h"
9 |
10 | int main() {
11 | PUSH_POOL {
12 |
13 | #if __has_feature(objc_bool) // placeholder until we get a more precise macro.
14 | NSArray *array = @[ @1, @2, @YES, @NO, @"Hello", @"World" ];
15 | testassert([array count] == 6);
16 | NSDictionary *dict = @{ @"Name" : @"John Q. Public", @"Age" : @42 };
17 | testassert([dict count] == 2);
18 | NSDictionary *numbers = @{ @"π" : @M_PI, @"e" : @M_E };
19 | testassert([[numbers objectForKey:@"π"] doubleValue] == M_PI);
20 | testassert([[numbers objectForKey:@"e"] doubleValue] == M_E);
21 |
22 | BOOL yesBool = YES;
23 | BOOL noBool = NO;
24 | array = @[
25 | @(true),
26 | @(YES),
27 | [NSNumber numberWithBool:YES],
28 | @YES,
29 | @(yesBool),
30 | @((BOOL)YES),
31 |
32 | @(false),
33 | @(NO),
34 | [NSNumber numberWithBool:NO],
35 | @NO,
36 | @(noBool),
37 | @((BOOL)NO),
38 | ];
39 | NSData * jsonData = [NSJSONSerialization dataWithJSONObject:array options:0 error:nil];
40 | NSString * string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
41 | #if __cplusplus
42 | testassert([string isEqualToString:@"[true,true,true,true,true,true,false,false,false,false,false,false]"]);
43 | #else
44 | // C99 @(true) and @(false) evaluate to @(1) and @(0).
45 | testassert([string isEqualToString:@"[1,true,true,true,true,true,0,false,false,false,false,false]"]);
46 | #endif
47 |
48 | #endif
49 |
50 | } POP_POOL;
51 |
52 | succeed(__FILE__);
53 |
54 | return 0;
55 | }
56 |
--------------------------------------------------------------------------------
/test/load-image-notification-dylib.m:
--------------------------------------------------------------------------------
1 | #import "test.h"
2 |
3 | #import
4 |
5 | @interface CLASSNAME: NSObject @end
6 | @implementation CLASSNAME @end
7 |
8 |
--------------------------------------------------------------------------------
/test/load-order.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/load-order3.m -o load-order3.dylib -dynamiclib
4 | $C{COMPILE} $DIR/load-order2.m -o load-order2.dylib -x none load-order3.dylib -dynamiclib
5 | $C{COMPILE} $DIR/load-order1.m -o load-order1.dylib -x none load-order3.dylib load-order2.dylib -dynamiclib
6 | $C{COMPILE} $DIR/load-order.m -o load-order.exe -x none load-order3.dylib load-order2.dylib load-order1.dylib
7 | END
8 | */
9 |
10 | #include "test.h"
11 |
12 | extern int state1, state2, state3;
13 |
14 | int main()
15 | {
16 | testassert(state1 == 1 && state2 == 2 && state3 == 3);
17 | succeed(__FILE__);
18 | }
19 |
--------------------------------------------------------------------------------
/test/load-order1.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | extern int state2, state3;
4 |
5 | int state1 = 0;
6 |
7 | OBJC_ROOT_CLASS
8 | @interface One @end
9 | @implementation One
10 | +(void)load
11 | {
12 | testassert(state2 == 2 && state3 == 3);
13 | state1 = 1;
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/test/load-order2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | extern int state3;
4 |
5 | int state2 = 0;
6 |
7 | OBJC_ROOT_CLASS
8 | @interface Two @end
9 | @implementation Two
10 | +(void)load
11 | {
12 | testassert(state3 == 3);
13 | state2 = 2;
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/test/load-order3.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | int state3 = 0;
4 |
5 | OBJC_ROOT_CLASS
6 | @interface Three @end
7 | @implementation Three
8 | +(void)load
9 | {
10 | state3 = 3;
11 | }
12 | @end
13 |
--------------------------------------------------------------------------------
/test/load-parallel.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/load-parallel00.m -o load-parallel00.dylib -dynamiclib
4 | $C{COMPILE} $DIR/load-parallel.m -x none load-parallel00.dylib -o load-parallel.exe -DCOUNT=10
5 |
6 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel0.dylib -dynamiclib -DN=0
7 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel1.dylib -dynamiclib -DN=1
8 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel2.dylib -dynamiclib -DN=2
9 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel3.dylib -dynamiclib -DN=3
10 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel4.dylib -dynamiclib -DN=4
11 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel5.dylib -dynamiclib -DN=5
12 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel6.dylib -dynamiclib -DN=6
13 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel7.dylib -dynamiclib -DN=7
14 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel8.dylib -dynamiclib -DN=8
15 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel9.dylib -dynamiclib -DN=9
16 | END
17 | */
18 |
19 | #include "test.h"
20 |
21 | #include
22 | #include
23 |
24 | #ifndef COUNT
25 | #error -DCOUNT=c missing
26 | #endif
27 |
28 | extern atomic_int state;
29 |
30 | void *thread(void *arg)
31 | {
32 | uintptr_t num = (uintptr_t)arg;
33 | char *buf;
34 |
35 | asprintf(&buf, "load-parallel%lu.dylib", (unsigned long)num);
36 | testprintf("%s\n", buf);
37 | void *dlh = dlopen(buf, RTLD_LAZY);
38 | if (!dlh) {
39 | fail("dlopen failed: %s", dlerror());
40 | }
41 | free(buf);
42 |
43 | return NULL;
44 | }
45 |
46 | int main()
47 | {
48 | pthread_t t[COUNT];
49 | uintptr_t i;
50 |
51 | for (i = 0; i < COUNT; i++) {
52 | pthread_create(&t[i], NULL, thread, (void *)i);
53 | }
54 |
55 | for (i = 0; i < COUNT; i++) {
56 | pthread_join(t[i], NULL);
57 | }
58 |
59 | testprintf("loaded %d/%d\n", (int)state, COUNT*26);
60 | testassert(state == COUNT*26);
61 |
62 | succeed(__FILE__);
63 | }
64 |
--------------------------------------------------------------------------------
/test/load-parallel0.m:
--------------------------------------------------------------------------------
1 | #ifndef N
2 | #error -DN=n missing
3 | #endif
4 |
5 | #import
6 | #include
7 | #include
8 | #include
9 | #include "test.h"
10 | extern atomic_int state;
11 |
12 | #define CLASS0(n,nn) \
13 | OBJC_ROOT_CLASS \
14 | @interface C_##n##_##nn @end \
15 | @implementation C_##n##_##nn \
16 | +(void)load { \
17 | atomic_fetch_add_explicit(&state, 1, memory_order_relaxed); \
18 | usleep(10); } \
19 | @end
20 |
21 | #define CLASS(n,nn) CLASS0(n,nn)
22 |
23 | CLASS(a,N)
24 | CLASS(b,N)
25 | CLASS(c,N)
26 | CLASS(d,N)
27 | CLASS(e,N)
28 | CLASS(f,N)
29 | CLASS(g,N)
30 | CLASS(h,N)
31 | CLASS(i,N)
32 | CLASS(j,N)
33 | CLASS(k,N)
34 | CLASS(l,N)
35 | CLASS(m,N)
36 | CLASS(n,N)
37 | CLASS(o,N)
38 | CLASS(p,N)
39 | CLASS(q,N)
40 | CLASS(r,N)
41 | CLASS(s,N)
42 | CLASS(t,N)
43 | CLASS(u,N)
44 | CLASS(v,N)
45 | CLASS(w,N)
46 | CLASS(x,N)
47 | CLASS(y,N)
48 | CLASS(z,N)
49 |
--------------------------------------------------------------------------------
/test/load-parallel00.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | atomic_int state;
3 |
--------------------------------------------------------------------------------
/test/load-reentrant.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/load-reentrant.m -o load-reentrant.exe
4 | $C{COMPILE} $DIR/load-reentrant2.m -o libload-reentrant2.dylib -bundle -bundle_loader load-reentrant.exe
5 | END
6 | */
7 |
8 | #include "test.h"
9 | #include
10 |
11 | int state1 = 0;
12 | int *state2_p;
13 |
14 | OBJC_ROOT_CLASS
15 | @interface One @end
16 | @implementation One
17 | +(void)load
18 | {
19 | state1 = 111;
20 |
21 | // Re-entrant +load doesn't get to complete until we do
22 | void *dlh = dlopen("libload-reentrant2.dylib", RTLD_LAZY);
23 | testassert(dlh);
24 | state2_p = (int *)dlsym(dlh, "state2");
25 | testassert(state2_p);
26 | testassert(*state2_p == 0);
27 |
28 | state1 = 1;
29 | }
30 | @end
31 |
32 | int main()
33 | {
34 | testassert(state1 == 1 && state2_p && *state2_p == 2);
35 | succeed(__FILE__);
36 | }
37 |
--------------------------------------------------------------------------------
/test/load-reentrant2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | int state2 = 0;
4 | extern int state1;
5 |
6 | static void ctor(void) __attribute__((constructor));
7 | static void ctor(void)
8 | {
9 | // should be called during One's dlopen(), before Two's +load
10 | testassert(state1 == 111);
11 | testassert(state2 == 0);
12 | }
13 |
14 | OBJC_ROOT_CLASS
15 | @interface Two @end
16 | @implementation Two
17 | +(void) load
18 | {
19 | // Does not run until One's +load completes
20 | testassert(state1 == 1);
21 | state2 = 2;
22 | }
23 | @end
24 |
--------------------------------------------------------------------------------
/test/load.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 |
6 | int state = 0;
7 | int catstate = 0;
8 | int deallocstate = 0;
9 |
10 | @interface Deallocator : TestRoot @end
11 | @implementation Deallocator
12 | -(void)dealloc {
13 | deallocstate = 1;
14 | SUPER_DEALLOC();
15 | }
16 | @end
17 |
18 |
19 | @interface Super : TestRoot @end
20 | @implementation Super
21 | +(void)initialize {
22 | if (self == [Super class]) {
23 | testprintf("in +[Super initialize]\n");
24 | testassert(state == 2);
25 | state = 3;
26 | } else {
27 | testprintf("in +[Super initialize] on behalf of Sub\n");
28 | testassert(state == 3);
29 | state = 4;
30 | }
31 | }
32 | -(void)load { fail("-[Super load] called!"); }
33 | +(void)load {
34 | testprintf("in +[Super load]\n");
35 | testassert(state == 0);
36 | state = 1;
37 | }
38 | @end
39 |
40 | @interface Sub : Super { } @end
41 | @implementation Sub
42 | +(void)load {
43 | testprintf("in +[Sub load]\n");
44 | testassert(state == 1);
45 | state = 2;
46 | }
47 | -(void)load { fail("-[Sub load] called!"); }
48 | @end
49 |
50 | @interface SubNoLoad : Super { } @end
51 | @implementation SubNoLoad @end
52 |
53 | @interface Super (Category) @end
54 | @implementation Super (Category)
55 | -(void)load { fail("-[Super(Category) load called!"); }
56 | +(void)load {
57 | testprintf("in +[Super(Category) load]\n");
58 | testassert(state >= 1);
59 | catstate++;
60 | }
61 | @end
62 |
63 |
64 | @interface Sub (Category) @end
65 | @implementation Sub (Category)
66 | -(void)load { fail("-[Sub(Category) load called!"); }
67 | +(void)load {
68 | testprintf("in +[Sub(Category) load]\n");
69 | testassert(state >= 2);
70 | catstate++;
71 |
72 | // test autorelease pool
73 | __autoreleasing id x;
74 | x = AUTORELEASE([Deallocator new]);
75 | }
76 | @end
77 |
78 |
79 | @interface SubNoLoad (Category) @end
80 | @implementation SubNoLoad (Category)
81 | -(void)load { fail("-[SubNoLoad(Category) load called!"); }
82 | +(void)load {
83 | testprintf("in +[SubNoLoad(Category) load]\n");
84 | testassert(state >= 1);
85 | catstate++;
86 | }
87 | @end
88 |
89 | int main()
90 | {
91 | testassert(state == 2);
92 | testassert(catstate == 3);
93 | testassert(deallocstate == 1);
94 | [Sub class];
95 | testassert(state == 4);
96 | testassert(catstate == 3);
97 |
98 | succeed(__FILE__);
99 | }
100 |
--------------------------------------------------------------------------------
/test/methodCacheLeaks.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc LANGUAGE=objective-c
2 | /*
3 | TEST_RUN_OUTPUT
4 | [\S\s]*0 leaks for 0 total leaked bytes[\S\s]*
5 | END
6 | */
7 |
8 | #include "test.h"
9 | #include "testroot.i"
10 |
11 | #include
12 | #include
13 |
14 | void noopIMP(id self __unused, SEL _cmd __unused) {}
15 |
16 | id test(int n, int methodCount) {
17 | char *name;
18 | asprintf(&name, "TestClass%d", n);
19 | Class c = objc_allocateClassPair([TestRoot class], name, 0);
20 | free(name);
21 |
22 | SEL *sels = malloc(methodCount * sizeof(*sels));
23 | for(int i = 0; i < methodCount; i++) {
24 | asprintf(&name, "selector%d", i);
25 | sels[i] = sel_getUid(name);
26 | free(name);
27 | }
28 |
29 | for(int i = 0; i < methodCount; i++) {
30 | class_addMethod(c, sels[i], (IMP)noopIMP, "v@:");
31 | }
32 |
33 | objc_registerClassPair(c);
34 |
35 | id obj = [[c alloc] init];
36 | for (int i = 0; i < methodCount; i++) {
37 | ((void (*)(id, SEL))objc_msgSend)(obj, sels[i]);
38 | }
39 | free(sels);
40 | return obj;
41 | }
42 |
43 | int main()
44 | {
45 | int classCount = 16;
46 | id *objs = malloc(classCount * sizeof(*objs));
47 | for (int i = 0; i < classCount; i++) {
48 | objs[i] = test(i, 1 << i);
49 | }
50 |
51 | char *pidstr;
52 | int result = asprintf(&pidstr, "%u", getpid());
53 | testassert(result);
54 |
55 | extern char **environ;
56 | char *argv[] = { "/usr/bin/leaks", pidstr, NULL };
57 | pid_t pid;
58 | result = posix_spawn(&pid, "/usr/bin/leaks", NULL, NULL, argv, environ);
59 | if (result) {
60 | perror("posix_spawn");
61 | exit(1);
62 | }
63 | wait4(pid, NULL, 0, NULL);
64 |
65 | // Clean up. Otherwise leaks can end up seeing this as a leak, oddly enough.
66 | for (int i = 0; i < classCount; i++) {
67 | [objs[i] release];
68 | }
69 | free(objs);
70 | }
71 |
--------------------------------------------------------------------------------
/test/methodListSize.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | // rdar://8052003 rdar://8077031
3 |
4 | #include "test.h"
5 |
6 | #include
7 | #include
8 |
9 | // add SELCOUNT methods to each of CLASSCOUNT classes
10 | #define CLASSCOUNT 100
11 | #define SELCOUNT 200
12 |
13 | int main()
14 | {
15 | int i, j;
16 | malloc_statistics_t start, end;
17 |
18 | Class root;
19 | root = objc_allocateClassPair(NULL, "Root", 0);
20 | objc_registerClassPair(root);
21 |
22 | Class classes[CLASSCOUNT];
23 | for (i = 0; i < CLASSCOUNT; i++) {
24 | char *classname;
25 | asprintf(&classname, "GrP_class_%d", i);
26 | classes[i] = objc_allocateClassPair(root, classname, 0);
27 | objc_registerClassPair(classes[i]);
28 | free(classname);
29 | }
30 |
31 | SEL selectors[SELCOUNT];
32 | for (i = 0; i < SELCOUNT; i++) {
33 | char *selname;
34 | asprintf(&selname, "GrP_sel_%d", i);
35 | selectors[i] = sel_registerName(selname);
36 | free(selname);
37 | }
38 |
39 | malloc_zone_statistics(NULL, &start);
40 |
41 | for (i = 0; i < CLASSCOUNT; i++) {
42 | for (j = 0; j < SELCOUNT; j++) {
43 | class_addMethod(classes[i], selectors[j], (IMP)main, "");
44 | }
45 | }
46 |
47 | malloc_zone_statistics(NULL, &end);
48 |
49 | // expected: 3-word method struct plus two other words
50 | ssize_t expected = (sizeof(void*) * (3+2)) * SELCOUNT * CLASSCOUNT;
51 | ssize_t actual = end.size_in_use - start.size_in_use;
52 | testassert(actual < expected * 3); // allow generous fudge factor
53 |
54 | succeed(__FILE__);
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/test/nilAPIArgs.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD_OUTPUT
3 | .*nilAPIArgs.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
4 | .*nilAPIArgs.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
5 | END
6 | */
7 |
8 | #include "test.h"
9 |
10 | #import
11 |
12 | int main() {
13 | // ensure various bits of API don't crash when tossed nil parameters
14 | class_conformsToProtocol(nil, nil);
15 | method_setImplementation(nil, NULL);
16 |
17 | succeed(__FILE__);
18 | }
19 |
--------------------------------------------------------------------------------
/test/nopool.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 |
6 | @implementation TestRoot (Loader)
7 | +(void)load
8 | {
9 | [[TestRoot new] autorelease];
10 | testassert(TestRootAutorelease == 1);
11 | testassert(TestRootDealloc == 0);
12 | }
13 | @end
14 |
15 | int main()
16 | {
17 | // +load's autoreleased object should have deallocated
18 | testassert(TestRootDealloc == 1);
19 |
20 | [[TestRoot new] autorelease];
21 | testassert(TestRootAutorelease == 2);
22 |
23 |
24 | objc_autoreleasePoolPop(objc_autoreleasePoolPush());
25 | [[TestRoot new] autorelease];
26 | testassert(TestRootAutorelease == 3);
27 |
28 |
29 | testonthread(^{
30 | [[TestRoot new] autorelease];
31 | testassert(TestRootAutorelease == 4);
32 | testassert(TestRootDealloc == 1);
33 | });
34 | // thread's autoreleased object should have deallocated
35 | testassert(TestRootDealloc == 2);
36 |
37 |
38 | // Test no-pool autorelease after a pool was pushed and popped.
39 | // The simplest POOL_SENTINEL check during pop gets this wrong.
40 | testonthread(^{
41 | objc_autoreleasePoolPop(objc_autoreleasePoolPush());
42 | [[TestRoot new] autorelease];
43 | testassert(TestRootAutorelease == 5);
44 | testassert(TestRootDealloc == 2);
45 | });
46 | testassert(TestRootDealloc == 3
47 | );
48 | succeed(__FILE__);
49 | }
50 |
--------------------------------------------------------------------------------
/test/nscdtors.mm:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | // test cdtors, with NSObject instead of TestRoot as the root class
3 |
4 | #define USE_FOUNDATION 1
5 | #include "cdtors.mm"
6 |
7 |
--------------------------------------------------------------------------------
/test/nsexc.m:
--------------------------------------------------------------------------------
1 | /*
2 | need exception-safe ARC for exception deallocation tests
3 | TEST_CFLAGS -fobjc-arc-exceptions -framework Foundation
4 | */
5 |
6 | #define USE_FOUNDATION 1
7 | #include "exc.m"
8 |
--------------------------------------------------------------------------------
/test/nsprotocol.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 |
6 | int main()
7 | {
8 | // Class Protocol is always a subclass of NSObject
9 |
10 | testassert(objc_getClass("NSObject"));
11 |
12 | Class cls = objc_getClass("Protocol");
13 | testassert(class_getInstanceMethod(cls, sel_registerName("isProxy")));
14 | testassert(class_getSuperclass(cls) == objc_getClass("NSObject"));
15 |
16 | succeed(__FILE__);
17 | }
18 |
--------------------------------------------------------------------------------
/test/objectCopy.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include
5 |
6 | @interface Test : NSObject {
7 | @public
8 | char bytes[32-sizeof(void*)];
9 | }
10 | @end
11 | @implementation Test
12 | @end
13 |
14 |
15 | int main()
16 | {
17 | Test *o0 = [Test new];
18 | [o0 retain];
19 | Test *o1 = class_createInstance([Test class], 32);
20 | [o1 retain];
21 | id o2 = object_copy(o0, 0);
22 | id o3 = object_copy(o1, 0);
23 | id o4 = object_copy(o1, 32);
24 |
25 | testassert(malloc_size(o0) == 32);
26 | testassert(malloc_size(o1) == 64);
27 | testassert(malloc_size(o2) == 32);
28 | testassert(malloc_size(o3) == 32);
29 | testassert(malloc_size(o4) == 64);
30 |
31 | testassert([o0 retainCount] == 2);
32 | testassert([o1 retainCount] == 2);
33 | testassert([o2 retainCount] == 1);
34 | testassert([o3 retainCount] == 1);
35 | testassert([o4 retainCount] == 1);
36 |
37 | succeed(__FILE__);
38 | }
39 |
--------------------------------------------------------------------------------
/test/preopt-caches.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.springboard-ui.client
6 |
7 | com.apple.security.system-groups
8 |
9 | systemgroup.com.apple.powerlog
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/test/rawisa.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CFLAGS -Xlinker -sectcreate -Xlinker __DATA -Xlinker __objc_rawisa -Xlinker /dev/null
3 | TEST_ENV OBJC_PRINT_RAW_ISA=YES
4 |
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: RAW ISA: disabling non-pointer isa because the app has a __DATA,__objc_rawisa section
7 | (.* RAW ISA: .*\n)*
8 | OK: rawisa.m(\n.* RAW ISA: .*)*
9 | OR
10 | (.* RAW ISA: .*\n)*
11 | no __DATA,__rawisa support
12 | OK: rawisa.m(\n.* RAW ISA: .*)*
13 | END
14 |
15 | "RAW ISA" is allowed after "OK" because of static destructors
16 | that provoke class realization.
17 | */
18 |
19 | #include "test.h"
20 |
21 | int main()
22 | {
23 | fprintf(stderr, "\n");
24 | #if ! (SUPPORT_NONPOINTER_ISA && TARGET_OS_OSX)
25 | // only 64-bit Mac supports this
26 | fprintf(stderr, "no __DATA,__rawisa support\n");
27 | #endif
28 | succeed(__FILE__);
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/test/realizedClassGenerationCount.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 |
6 | #include
7 |
8 | extern uintptr_t objc_debug_realized_class_generation_count;
9 |
10 | int main()
11 | {
12 | testassert(objc_debug_realized_class_generation_count > 0);
13 | uintptr_t prev = objc_debug_realized_class_generation_count;
14 |
15 | void *handle = dlopen("/System/Library/Frameworks/Foundation.framework/Foundation", RTLD_LAZY);
16 | testassert(handle);
17 | Class c = objc_getClass("NSFileManager");
18 | testassert(c);
19 | testassert(objc_debug_realized_class_generation_count > prev);
20 |
21 | prev = objc_debug_realized_class_generation_count;
22 | c = objc_allocateClassPair([TestRoot class], "Dynamic", 0);
23 | testassert(objc_debug_realized_class_generation_count > prev);
24 | prev = objc_debug_realized_class_generation_count;
25 | objc_registerClassPair(c);
26 | testassert(objc_debug_realized_class_generation_count == prev);
27 |
28 | succeed(__FILE__);
29 | }
--------------------------------------------------------------------------------
/test/release-workaround.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG ARCH=x86_64 MEM=mrc
2 | // TEST_CFLAGS -framework Foundation
3 |
4 | // rdar://20206767
5 |
6 | #include
7 | #include "test.h"
8 |
9 |
10 | @interface Test : NSObject @end
11 | @implementation Test
12 | @end
13 |
14 |
15 | int main()
16 | {
17 | id buf[1];
18 | buf[0] = [Test class];
19 | id obj = (id)buf;
20 | [obj retain];
21 | [obj retain];
22 |
23 | uintptr_t rax;
24 |
25 | [obj release];
26 | asm("mov %%rax, %0" : "=r" (rax));
27 | testassert(rax == 0);
28 |
29 | objc_release(obj);
30 | asm("mov %%rax, %0" : "=r" (rax));
31 | testassert(rax == 0);
32 |
33 | succeed(__FILE__);
34 | }
35 |
--------------------------------------------------------------------------------
/test/restartableRangesSynchronizeStress.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=macosx,iphoneos,tvos,watchos
2 | // TEST_ENV OBJC_DEBUG_SCRIBBLE_CACHES=YES
3 | // TEST_NO_MALLOC_SCRIBBLE
4 |
5 | // This test checks that objc_msgSend's recovery path works correctly.
6 | // It continuously runs msgSend on some background threads, then
7 | // triggers the recovery path constantly as a stress test.
8 |
9 | #include "test.h"
10 | #include "testroot.i"
11 | #include
12 |
13 | struct Big {
14 | uintptr_t a, b, c, d, e, f, g;
15 | };
16 |
17 | @interface C1: TestRoot
18 | @end
19 | @implementation C1
20 | - (id)idret { return nil; }
21 | - (double)fpret { return 0.0; }
22 | - (long double)lfpret { return 0.0; }
23 | - (struct Big)stret { return (struct Big){}; }
24 | @end
25 |
26 | @interface C2: C1
27 | @end
28 | @implementation C2
29 | - (id)idret { return [super idret]; }
30 | - (double)fpret { return [super fpret]; }
31 | - (long double)lfpret { return [super lfpret]; }
32 | - (struct Big)stret { return [super stret]; }
33 | @end
34 |
35 | EXTERN_C kern_return_t task_restartable_ranges_synchronize(task_t task);
36 |
37 | EXTERN_C void sendWithMsgLookup(id self, SEL _cmd);
38 |
39 | #if defined(__arm64__) && !__has_feature(ptrauth_calls)
40 | asm(
41 | "_sendWithMsgLookup: \n"
42 | " stp fp, lr, [sp, #-16]! \n"
43 | " mov fp, sp \n"
44 | " bl _objc_msgLookup \n"
45 | " mov sp, fp \n"
46 | " ldp fp, lr, [sp], #16 \n"
47 | " br x17 \n"
48 | );
49 | #elif defined(__x86_64__)
50 | asm(
51 | "_sendWithMsgLookup: \n"
52 | " pushq %rbp \n"
53 | " movq %rsp, %rbp \n"
54 | " callq _objc_msgLookup \n"
55 | " popq %rbp \n"
56 | " jmpq *%r11 \n"
57 | );
58 | #else
59 | // Just skip it.
60 | void sendWithMsgLookup(id self __unused, SEL _cmd __unused) {}
61 | #endif
62 |
63 | int main() {
64 | id obj = [C2 new];
65 | for(int i = 0; i < 2; i++) {
66 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
67 | while(1) {
68 | [obj idret];
69 | [obj fpret];
70 | [obj lfpret];
71 | [obj stret];
72 | sendWithMsgLookup(obj, @selector(idret));
73 | }
74 | });
75 | }
76 | for(int i = 0; i < 1000000; i++) {
77 | task_restartable_ranges_synchronize(mach_task_self());
78 | }
79 | Class c = [C1 class];
80 | for(int i = 0; i < 1000000; i++) {
81 | _objc_flush_caches(c);
82 | }
83 | succeed(__FILE__);
84 | }
85 |
--------------------------------------------------------------------------------
/test/restartableRangesSynchronizeStress2.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=arc LANGUAGE=objective-c
2 | // TEST_ENV OBJC_DEBUG_SCRIBBLE_CACHES=YES
3 | // TEST_NO_MALLOC_SCRIBBLE
4 |
5 | // Stress test thread-safe cache deallocation and reallocation.
6 |
7 | #include "test.h"
8 | #include "testroot.i"
9 | #include
10 |
11 | @interface MyClass1 : TestRoot
12 | @end
13 | @implementation MyClass1
14 | @end
15 |
16 | @interface MyClass2 : TestRoot
17 | @end
18 | @implementation MyClass2
19 | @end
20 |
21 | @interface MyClass3 : TestRoot
22 | @end
23 | @implementation MyClass3
24 | @end
25 |
26 | @interface MyClass4 : TestRoot
27 | @end
28 | @implementation MyClass4
29 | @end
30 |
31 | int main() {
32 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
33 | usleep(200000);
34 | while (1) {
35 | usleep(1000);
36 | _objc_flush_caches(MyClass1.class);
37 | _objc_flush_caches(MyClass2.class);
38 | _objc_flush_caches(MyClass3.class);
39 | _objc_flush_caches(MyClass4.class);
40 | }
41 | });
42 |
43 | for (int i = 0; i < 6; i++) {
44 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
45 | long j = 0;
46 | while (1) {
47 | j++;
48 | (void)[[MyClass1 alloc] init];
49 | (void)[[MyClass2 alloc] init];
50 | (void)[[MyClass3 alloc] init];
51 | (void)[[MyClass4 alloc] init];
52 | }
53 | });
54 | }
55 |
56 | sleep(5);
57 |
58 | succeed(__FILE__);
59 |
60 | return 0;
61 | }
62 |
--------------------------------------------------------------------------------
/test/rr-autorelease-stacklogging.m:
--------------------------------------------------------------------------------
1 | // Test OBJC_DEBUG_POOL_ALLOCATION (which is also enabled by MallocStackLogging)
2 |
3 | // TEST_ENV OBJC_DEBUG_POOL_ALLOCATION=YES
4 | // TEST_CFLAGS -framework Foundation
5 | // TEST_CONFIG MEM=mrc
6 |
7 | #include "test.h"
8 |
9 | #define FOUNDATION 0
10 | #define NAME "rr-autorelease-stacklogging"
11 | #define DEBUG_POOL_ALLOCATION 1
12 |
13 | #include "rr-autorelease2.m"
14 |
--------------------------------------------------------------------------------
/test/rr-autorelease.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | // TEST_CONFIG MEM=mrc
3 |
4 | #include "test.h"
5 |
6 | #define FOUNDATION 0
7 | #define NAME "rr-autorelease"
8 |
9 | #include "rr-autorelease2.m"
10 |
--------------------------------------------------------------------------------
/test/rr-nsautorelease.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | // TEST_CONFIG MEM=mrc
3 |
4 | #define FOUNDATION 1
5 | #define NAME "rr-nsautorelease"
6 |
7 | #include "rr-autorelease2.m"
8 |
--------------------------------------------------------------------------------
/test/rr-sidetable.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | // TEST_CONFIG MEM=mrc ARCH=x86_64
3 |
4 | // Stress-test nonpointer isa's side table retain count transfers.
5 |
6 | // x86_64 only. arm64's side table limit is high enough that bugs
7 | // are harder to reproduce.
8 |
9 | #include "test.h"
10 | #import
11 |
12 | #define OBJECTS 10
13 | #define LOOPS 256
14 | #define THREADS 16
15 | #if __x86_64__
16 | # define RC_HALF (1ULL<<7)
17 | #else
18 | # error sorry
19 | #endif
20 | #define RC_DELTA RC_HALF
21 |
22 | static bool Deallocated = false;
23 | @interface Deallocator : NSObject @end
24 | @implementation Deallocator
25 | -(void)dealloc {
26 | Deallocated = true;
27 | [super dealloc];
28 | }
29 | @end
30 |
31 | // This is global to avoid extra retains by the dispatch block objects.
32 | static Deallocator *obj;
33 |
34 | int main() {
35 | dispatch_queue_t queue =
36 | dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
37 |
38 | for (size_t i = 0; i < OBJECTS; i++) {
39 | obj = [Deallocator new];
40 |
41 | dispatch_apply(THREADS, queue, ^(size_t i __unused) {
42 | for (size_t a = 0; a < LOOPS; a++) {
43 | for (size_t b = 0; b < RC_DELTA; b++) {
44 | [obj retain];
45 | }
46 | for (size_t b = 0; b < RC_DELTA; b++) {
47 | [obj release];
48 | }
49 | }
50 | });
51 |
52 | testassert(!Deallocated);
53 | [obj release];
54 | testassert(Deallocated);
55 | Deallocated = false;
56 | }
57 |
58 | succeed(__FILE__);
59 | }
60 |
--------------------------------------------------------------------------------
/test/sel.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD_OUTPUT
3 | .*sel.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
4 | .*sel.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
5 | END
6 | */
7 |
8 | #include "test.h"
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | int main()
15 | {
16 | // Make sure @selector values are correctly fixed up
17 | testassert(@selector(foo) == sel_registerName("foo"));
18 |
19 | // sel_getName recognizes the zero SEL
20 | testassert(0 == strcmp("", sel_getName(0)));
21 |
22 | // sel_lookUpByName returns NULL for NULL string
23 | testassert(NULL == sel_lookUpByName(NULL));
24 |
25 | // sel_lookUpByName returns NULL for unregistered and matches later registered selector
26 | {
27 | SEL sel;
28 | testassert(NULL == sel_lookUpByName("__testSelectorLookUp:"));
29 | testassert(NULL != (sel = sel_registerName("__testSelectorLookUp:")));
30 | testassert(sel == sel_lookUpByName("__testSelectorLookUp:"));
31 | }
32 |
33 | // sel_lookUpByName matches @selector value
34 | testassert(@selector(foo2) == sel_lookUpByName("foo2"));
35 |
36 | succeed(__FILE__);
37 | }
38 |
--------------------------------------------------------------------------------
/test/setAssociatedObjectHook.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG MEM=mrc
3 | TEST_ENV OBJC_DISABLE_NONPOINTER_ISA=YES
4 | */
5 |
6 | #include "test.h"
7 | #include "testroot.i"
8 |
9 | bool hasAssociations = false;
10 |
11 | @interface TestRoot (AssocHooks)
12 | @end
13 |
14 | @implementation TestRoot (AssocHooks)
15 |
16 | - (void)_noteAssociatedObjects {
17 | hasAssociations = true;
18 | }
19 |
20 | // -_noteAssociatedObjects is currently limited to raw-isa custom-rr to avoid overhead
21 | - (void) release {
22 | }
23 |
24 | @end
25 |
26 | int main() {
27 | id obj = [TestRoot new];
28 | id value = [TestRoot new];
29 | const void *key = "key";
30 | objc_setAssociatedObject(obj, key, value, OBJC_ASSOCIATION_RETAIN);
31 | testassert(hasAssociations == true);
32 |
33 | id out = objc_getAssociatedObject(obj, key);
34 | testassert(out == value);
35 |
36 | hasAssociations = false;
37 | key = "key2";
38 | objc_setAssociatedObject(obj, key, value, OBJC_ASSOCIATION_RETAIN);
39 | testassert(hasAssociations == false); //only called once
40 |
41 |
42 | out = objc_getAssociatedObject(obj, key);
43 | testassert(out == value);
44 |
45 | succeed(__FILE__);
46 | }
47 |
--------------------------------------------------------------------------------
/test/setSuper.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | @interface Super1 : TestRoot @end
8 | @implementation Super1
9 | +(int)classMethod { return 1; }
10 | -(int)instanceMethod { return 10000; }
11 | @end
12 |
13 | @interface Super2 : TestRoot @end
14 | @implementation Super2
15 | +(int)classMethod { return 2; }
16 | -(int)instanceMethod { return 20000; }
17 | @end
18 |
19 | @interface Sub : Super1 @end
20 | @implementation Sub
21 | +(int)classMethod { return [super classMethod] + 100; }
22 | -(int)instanceMethod {
23 | return [super instanceMethod] + 1000000;
24 | }
25 | @end
26 |
27 | int main()
28 | {
29 | Class cls;
30 | Sub *obj = [Sub new];
31 |
32 | testassert(101 == [[Sub class] classMethod]);
33 | testassert(1010000 == [obj instanceMethod]);
34 |
35 | cls = class_setSuperclass([Sub class], [Super2 class]);
36 |
37 | testassert(cls == [Super1 class]);
38 | testassert(object_getClass(cls) == object_getClass([Super1 class]));
39 |
40 | testassert(102 == [[Sub class] classMethod]);
41 | testassert(1020000 == [obj instanceMethod]);
42 |
43 | succeed(__FILE__);
44 | }
45 |
--------------------------------------------------------------------------------
/test/super.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | @interface Sub : TestRoot @end
8 | @implementation Sub @end
9 |
10 | int main()
11 | {
12 | // [super ...] messages are tested in msgSend.m
13 |
14 | testassert(class_getSuperclass([Sub class]) == [TestRoot class]);
15 | testassert(class_getSuperclass(object_getClass([Sub class])) == object_getClass([TestRoot class]));
16 | testassert(class_getSuperclass([TestRoot class]) == Nil);
17 | testassert(class_getSuperclass(object_getClass([TestRoot class])) == [TestRoot class]);
18 | testassert(class_getSuperclass(Nil) == Nil);
19 |
20 | succeed(__FILE__);
21 | }
22 |
--------------------------------------------------------------------------------
/test/supported-inline-refcnt.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 | // TEST_CFLAGS -framework CoreFoundation -Weverything
3 |
4 | #pragma clang diagnostic push
5 | #pragma clang diagnostic ignored "-Weverything"
6 | #include "test.h"
7 | #pragma clang diagnostic pop
8 | #include
9 | #include
10 | #include
11 |
12 |
13 | // Some warnings just aren't feasible to work around. We'll disable them instead.
14 | #pragma clang diagnostic ignored "-Watomic-implicit-seq-cst"
15 | #pragma clang diagnostic ignored "-Wdirect-ivar-access"
16 | #pragma clang diagnostic ignored "-Wold-style-cast"
17 |
18 | static int deallocCount;
19 | @interface Refcnt: NSObject @end
20 | @implementation Refcnt {
21 | int _rc;
22 | }
23 |
24 | _OBJC_SUPPORTED_INLINE_REFCNT(_rc)
25 |
26 | - (void)dealloc {
27 | deallocCount++;
28 | [super dealloc];
29 | }
30 |
31 | @end
32 |
33 | @interface MainRefcnt: NSObject @end
34 | @implementation MainRefcnt {
35 | int _rc;
36 | }
37 |
38 | _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc)
39 |
40 | - (void)dealloc {
41 | testassert(pthread_main_np());
42 | deallocCount++;
43 | [super dealloc];
44 | }
45 |
46 | @end
47 |
48 | int main()
49 | {
50 | Refcnt *obj = [Refcnt new];
51 | [obj retain];
52 | [obj retain];
53 | [obj retain];
54 | [obj release];
55 | [obj release];
56 | [obj release];
57 | [obj release];
58 | testassert(deallocCount == 1);
59 |
60 | MainRefcnt *obj2 = [MainRefcnt new];
61 | [obj2 retain];
62 | [obj2 retain];
63 | [obj2 retain];
64 |
65 | dispatch_group_t group = dispatch_group_create();
66 | dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
67 | [obj2 release];
68 | });
69 | dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
70 | [obj2 release];
71 | });
72 | dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
73 | [obj2 release];
74 | });
75 | dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
76 | [obj2 release];
77 | });
78 |
79 | dispatch_group_notify(group, dispatch_get_main_queue(), ^{
80 | testassert(deallocCount == 2);
81 | succeed(__FILE__);
82 | });
83 |
84 | CFRunLoopRun();
85 | }
86 |
--------------------------------------------------------------------------------
/test/swiftMetadataInitializer.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include "swift-class-def.m"
5 |
6 |
7 | SWIFT_CLASS(SwiftSuper, NSObject, initSuper);
8 | SWIFT_CLASS(SwiftSub, SwiftSuper, initSub);
9 |
10 | // _objc_swiftMetadataInitializer hooks for the fake Swift classes
11 |
12 | Class initSuper(Class cls __unused, void *arg __unused)
13 | {
14 | // This test provokes objc's callback out of superclass order.
15 | // SwiftSub's init is first. SwiftSuper's init is never called.
16 |
17 | fail("SwiftSuper's init should not have been called");
18 | }
19 |
20 | bool isRealized(Class cls)
21 | {
22 | // check the is-realized bits directly
23 |
24 | #if __LP64__
25 | # define mask (~(uintptr_t)7)
26 | #else
27 | # define mask (~(uintptr_t)3)
28 | #endif
29 | #define RW_REALIZED (1<<31)
30 |
31 | uintptr_t rw = ((uintptr_t *)cls)[4] & mask; // class_t->data
32 | return ((uint32_t *)rw)[0] & RW_REALIZED; // class_rw_t->flags
33 | }
34 |
35 | static int SubInits = 0;
36 | Class initSub(Class cls, void *arg)
37 | {
38 | testprintf("initSub callback\n");
39 |
40 | testassert(SubInits == 0);
41 | SubInits++;
42 | testassert(arg == nil);
43 | testassert(0 == strcmp(class_getName(cls), "SwiftSub"));
44 | testassert(cls == RawSwiftSub);
45 | testassert(!isRealized(RawSwiftSuper));
46 | testassert(!isRealized(RawSwiftSub));
47 |
48 | testprintf("initSub beginning _objc_realizeClassFromSwift\n");
49 | _objc_realizeClassFromSwift(cls, cls);
50 | testprintf("initSub finished _objc_realizeClassFromSwift\n");
51 |
52 | testassert(isRealized(RawSwiftSuper));
53 | testassert(isRealized(RawSwiftSub));
54 |
55 | return cls;
56 | }
57 |
58 |
59 | int main()
60 | {
61 | testassert(SubInits == 0);
62 | testprintf("calling [SwiftSub class]\n");
63 | [SwiftSub class];
64 | testprintf("finished [SwiftSub class]\n");
65 | testassert(SubInits == 1);
66 | [SwiftSuper class];
67 | succeed(__FILE__);
68 | }
69 |
--------------------------------------------------------------------------------
/test/swiftMetadataInitializerRealloc-dylib1.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "swift-class-def.m"
3 |
4 | SWIFT_CLASS(RealSwiftDylib1A, NSObject, nop);
5 | SWIFT_STUB_CLASS(SwiftDylib1A, initSwiftDylib1A);
6 |
7 | SWIFT_CLASS(RealSwiftDylib1B, NSObject, nop);
8 | SWIFT_STUB_CLASS(SwiftDylib1B, initSwiftDylib1B);
9 |
10 | int Dylib1AInits = 0;
11 |
12 | @interface SwiftDylib1A: NSObject @end
13 | @interface SwiftDylib1B: NSObject @end
14 |
15 | @implementation SwiftDylib1A (Category)
16 | - (const char *)dylib1ACategoryInSameDylib { return "dylib1ACategoryInSameDylib"; }
17 | @end
18 | @implementation SwiftDylib1B (Category)
19 | - (const char *)dylib1BCategoryInSameDylib { return "dylib1BCategoryInSameDylib"; }
20 | @end
21 |
22 | EXTERN_C Class initSwiftDylib1A(Class cls, void *arg)
23 | {
24 | Dylib1AInits++;
25 | testassert(arg == nil);
26 | testassert(cls == RawSwiftDylib1A);
27 |
28 | if (Dylib1AInits == 1)
29 | _objc_realizeClassFromSwift(RawRealSwiftDylib1A, cls);
30 |
31 | return RawRealSwiftDylib1A;
32 | }
33 |
34 | int Dylib1BInits = 0;
35 |
36 | EXTERN_C Class initSwiftDylib1B(Class cls, void *arg)
37 | {
38 | Dylib1BInits++;
39 | testassert(arg == nil);
40 | testassert(cls == RawSwiftDylib1B);
41 |
42 | if (Dylib1BInits == 1)
43 | _objc_realizeClassFromSwift(RawRealSwiftDylib1B, cls);
44 |
45 | return RawRealSwiftDylib1B;
46 | }
47 |
48 | EXTERN_C Class objc_loadClassref(_Nullable Class * _Nonnull clsref);
49 |
50 | void Dylib1Test(void) {
51 | testassert((uintptr_t)SwiftDylib1AClassref & 1);
52 | Class SwiftDylib1A = objc_loadClassref(&SwiftDylib1AClassref);
53 | testassert(((uintptr_t)SwiftDylib1AClassref & 1) == 0);
54 | testassert(SwiftDylib1A == [SwiftDylib1A class]);
55 | testassert(SwiftDylib1A == SwiftDylib1AClassref);
56 | testassert(Dylib1AInits == 2);
57 |
58 | testassert((uintptr_t)SwiftDylib1BClassref & 1);
59 | Class SwiftDylib1B = objc_loadClassref(&SwiftDylib1BClassref);
60 | testassert(((uintptr_t)SwiftDylib1BClassref & 1) == 0);
61 | testassert(SwiftDylib1B == [SwiftDylib1B class]);
62 | testassert(SwiftDylib1B == SwiftDylib1BClassref);
63 | testassert(Dylib1BInits == 2);
64 | }
65 |
--------------------------------------------------------------------------------
/test/swiftMetadataInitializerRealloc-dylib2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "swift-class-def.m"
3 |
4 | @interface SwiftDylib1A: NSObject @end
5 | @interface SwiftDylib1B: NSObject @end
6 |
7 | @interface NSObject (DylibCategories)
8 | - (char *)dylib1ACategoryInSameDylib;
9 | - (char *)dylib1BCategoryInSameDylib;
10 | - (char *)dylib1ACategoryInOtherDylib;
11 | - (char *)dylib1BCategoryInOtherDylib;
12 | - (char *)dylib1ACategoryInApp;
13 | - (char *)dylib1BCategoryInApp;
14 | + (void)testFromOtherDylib;
15 | @end
16 |
17 | @implementation SwiftDylib1A (Category)
18 | - (const char *)dylib1ACategoryInOtherDylib { return "dylib1ACategoryInOtherDylib"; }
19 | @end
20 | @implementation SwiftDylib1B (Category)
21 | - (const char *)dylib1BCategoryInOtherDylib { return "dylib1BCategoryInOtherDylib"; }
22 | @end
23 |
24 | SWIFT_STUB_CLASSREF(SwiftDylib1A);
25 | SWIFT_STUB_CLASSREF(SwiftDylib1B);
26 |
27 | Class objc_loadClassref(_Nullable Class * _Nonnull clsref);
28 |
29 | @implementation SwiftDylib1A (Test)
30 | + (void)testFromOtherDylib {
31 | Class SwiftDylib1A = objc_loadClassref(&SwiftDylib1AClassref);
32 | Class SwiftDylib1B = objc_loadClassref(&SwiftDylib1BClassref);
33 | testassert(strcmp([[SwiftDylib1A new] dylib1ACategoryInSameDylib], "dylib1ACategoryInSameDylib") == 0);
34 | testassert(strcmp([[SwiftDylib1B new] dylib1BCategoryInSameDylib], "dylib1BCategoryInSameDylib") == 0);
35 | testassert(strcmp([[SwiftDylib1A new] dylib1ACategoryInApp], "dylib1ACategoryInApp") == 0);
36 | testassert(strcmp([[SwiftDylib1B new] dylib1BCategoryInApp], "dylib1BCategoryInApp") == 0);
37 | testassert(strcmp([[SwiftDylib1A new] dylib1ACategoryInOtherDylib], "dylib1ACategoryInOtherDylib") == 0);
38 | testassert(strcmp([[SwiftDylib1B new] dylib1BCategoryInOtherDylib], "dylib1BCategoryInOtherDylib") == 0);
39 | }
40 | @end
41 |
--------------------------------------------------------------------------------
/test/synchronized-counter.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | // synchronized stress test
13 | // Single locked counter incremented by many threads.
14 |
15 | #if defined(__arm__)
16 | #define THREADS 16
17 | #define COUNT 1024*24
18 | #else
19 | // 64 / 1024*24 test takes about 20s on 4x2.6GHz Mac Pro
20 | #define THREADS 64
21 | #define COUNT 1024*24
22 | #endif
23 |
24 | static id lock;
25 | static int count;
26 |
27 | static void *threadfn(void *arg)
28 | {
29 | int n, d;
30 | int depth = 1 + (int)(intptr_t)arg % 4;
31 |
32 | for (n = 0; n < COUNT; n++) {
33 | // Lock
34 | for (d = 0; d < depth; d++) {
35 | int err = objc_sync_enter(lock);
36 | testassert(err == OBJC_SYNC_SUCCESS);
37 | }
38 |
39 | // Increment
40 | count++;
41 |
42 | // Unlock
43 | for (d = 0; d < depth; d++) {
44 | int err = objc_sync_exit(lock);
45 | testassert(err == OBJC_SYNC_SUCCESS);
46 | }
47 | }
48 |
49 | // Verify lack of objc pthread data (should have used sync fast cache)
50 | #ifdef __PTK_FRAMEWORK_OBJC_KEY0
51 | testassert(! pthread_getspecific(__PTK_FRAMEWORK_OBJC_KEY0));
52 | #endif
53 |
54 | return NULL;
55 | }
56 |
57 | int main()
58 | {
59 | pthread_t threads[THREADS];
60 | int t;
61 | int err;
62 |
63 | lock = [[NSObject alloc] init];
64 |
65 | // Verify objc pthread data on this thread (from +initialize)
66 | // Worker threads shouldn't have any because of sync fast cache.
67 | #ifdef __PTK_FRAMEWORK_OBJC_KEY0
68 | testassert(pthread_getspecific(__PTK_FRAMEWORK_OBJC_KEY0));
69 | #endif
70 |
71 | // Start the threads
72 | for (t = 0; t < THREADS; t++) {
73 | pthread_create(&threads[t], NULL, &threadfn, (void*)(intptr_t)t);
74 | }
75 |
76 | // Wait for threads to finish
77 | for (t = 0; t < THREADS; t++) {
78 | pthread_join(threads[t], NULL);
79 | }
80 |
81 | // Verify lock: should be available
82 | // Verify count: should be THREADS*COUNT
83 | err = objc_sync_enter(lock);
84 | testassert(err == OBJC_SYNC_SUCCESS);
85 | testassert(count == THREADS*COUNT);
86 |
87 | succeed(__FILE__);
88 | }
89 |
--------------------------------------------------------------------------------
/test/taggedNSPointers.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 |
3 | #include "test.h"
4 | #include
5 | #import
6 |
7 | #if OBJC_HAVE_TAGGED_POINTERS
8 |
9 | void testTaggedNumber()
10 | {
11 | NSNumber *taggedNS = [NSNumber numberWithInt: 1234];
12 | CFNumberRef taggedCF = (__bridge CFNumberRef)taggedNS;
13 | int result;
14 |
15 | testassert( CFGetTypeID(taggedCF) == CFNumberGetTypeID() );
16 | testassert(_objc_getClassForTag(OBJC_TAG_NSNumber) == [taggedNS class]);
17 |
18 | CFNumberGetValue(taggedCF, kCFNumberIntType, &result);
19 | testassert(result == 1234);
20 |
21 | testassert(_objc_isTaggedPointer(taggedCF));
22 | testassert(_objc_getTaggedPointerTag(taggedCF) == OBJC_TAG_NSNumber);
23 | testassert(_objc_makeTaggedPointer(_objc_getTaggedPointerTag(taggedCF), _objc_getTaggedPointerValue(taggedCF)) == taggedCF);
24 |
25 | // do some generic object-y things to the taggedPointer instance
26 | CFRetain(taggedCF);
27 | CFRelease(taggedCF);
28 |
29 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
30 | [dict setObject: taggedNS forKey: @"fred"];
31 | testassert(taggedNS == [dict objectForKey: @"fred"]);
32 | [dict setObject: @"bob" forKey: taggedNS];
33 | testassert([@"bob" isEqualToString: [dict objectForKey: taggedNS]]);
34 |
35 | NSNumber *iM88 = [NSNumber numberWithInt:-88];
36 | NSNumber *i12346 = [NSNumber numberWithInt: 12346];
37 | NSNumber *i12347 = [NSNumber numberWithInt: 12347];
38 |
39 | NSArray *anArray = [NSArray arrayWithObjects: iM88, i12346, i12347, nil];
40 | testassert([anArray count] == 3);
41 | testassert([anArray indexOfObject: i12346] == 1);
42 |
43 | NSSet *aSet = [NSSet setWithObjects: iM88, i12346, i12347, nil];
44 | testassert([aSet count] == 3);
45 | testassert([aSet containsObject: i12346]);
46 |
47 | [taggedNS performSelector: @selector(intValue)];
48 | testassert(![taggedNS isProxy]);
49 | testassert([taggedNS isKindOfClass: [NSNumber class]]);
50 | testassert([taggedNS respondsToSelector: @selector(intValue)]);
51 |
52 | (void)[taggedNS description];
53 | }
54 |
55 | int main()
56 | {
57 | PUSH_POOL {
58 | testTaggedNumber(); // should be tested by CF... our tests are wrong, wrong, wrong.
59 | } POP_POOL;
60 |
61 | succeed(__FILE__);
62 | }
63 |
64 | // OBJC_HAVE_TAGGED_POINTERS
65 | #else
66 | // not OBJC_HAVE_TAGGED_POINTERS
67 |
68 | // Tagged pointers not supported. Crash if an NSNumber actually
69 | // is a tagged pointer (which means this test is out of date).
70 |
71 | int main()
72 | {
73 | PUSH_POOL {
74 | testassert(*(void **)(__bridge void *)[NSNumber numberWithInt:1234]);
75 | } POP_POOL;
76 |
77 | succeed(__FILE__);
78 | }
79 |
80 | #endif
81 |
--------------------------------------------------------------------------------
/test/taggedPointersAllClasses.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 | #include
7 |
8 | #if OBJC_HAVE_TAGGED_POINTERS
9 |
10 | @interface TagSuperclass: TestRoot
11 |
12 | - (void)test;
13 |
14 | @end
15 |
16 | @implementation TagSuperclass
17 |
18 | - (void)test {}
19 |
20 | @end
21 |
22 | int main()
23 | {
24 | Class classes[OBJC_TAG_Last52BitPayload + 1] = {};
25 |
26 | __block uintptr_t expectedPayload;
27 | __block uintptr_t sawPayload;
28 | __block int sawTag;
29 |
30 | for (int i = 0; i <= OBJC_TAG_Last52BitPayload; i++) {
31 | objc_tag_index_t tag = (objc_tag_index_t)i;
32 | if (i > OBJC_TAG_Last60BitPayload && i < OBJC_TAG_First52BitPayload)
33 | continue;
34 | if (_objc_getClassForTag(tag) != nil)
35 | continue;
36 |
37 | char *name;
38 | asprintf(&name, "Tag%d", i);
39 | classes[i] = objc_allocateClassPair([TagSuperclass class], name, 0);
40 | free(name);
41 |
42 | IMP testIMP = imp_implementationWithBlock(^(void *self) {
43 | testassert(i == _objc_getTaggedPointerTag(self));
44 | testassert(expectedPayload == _objc_getTaggedPointerValue(self));
45 | sawPayload = _objc_getTaggedPointerValue(self);
46 | sawTag = i;
47 | });
48 | class_addMethod(classes[i], @selector(test), testIMP, "v@@");
49 |
50 | objc_registerClassPair(classes[i]);
51 | _objc_registerTaggedPointerClass(tag, classes[i]);
52 | }
53 |
54 | for (int i = 0; i <= OBJC_TAG_Last52BitPayload; i++) {
55 | objc_tag_index_t tag = (objc_tag_index_t)i;
56 | if (classes[i] == nil)
57 | continue;
58 |
59 | for (int byte = 0; byte <= 0xff; byte++) {
60 | uintptr_t payload;
61 | memset(&payload, byte, sizeof(payload));
62 |
63 | if (i <= OBJC_TAG_Last60BitPayload)
64 | payload >>= _OBJC_TAG_PAYLOAD_RSHIFT;
65 | else
66 | payload >>= _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
67 |
68 | expectedPayload = payload;
69 | id obj = (__bridge id)_objc_makeTaggedPointer(tag, payload);
70 | [obj test];
71 | testassert(sawPayload == payload);
72 | testassert(sawTag == i);
73 | }
74 | }
75 |
76 | succeed(__FILE__);
77 | }
78 |
79 | #else
80 |
81 | int main()
82 | {
83 | succeed(__FILE__);
84 | }
85 |
86 | #endif
87 |
--------------------------------------------------------------------------------
/test/taggedPointersDisabled.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_ENV OBJC_DISABLE_TAGGED_POINTERS=YES
3 | TEST_CRASHES
4 |
5 | TEST_BUILD_OUTPUT
6 | .*taggedPointersDisabled.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
7 | END
8 |
9 | TEST_RUN_OUTPUT
10 | objc\[\d+\]: tagged pointers are disabled
11 | objc\[\d+\]: HALTED
12 | OR
13 | OK: taggedPointersDisabled.m
14 | END
15 | */
16 |
17 | #include "test.h"
18 | #include
19 |
20 | #if !OBJC_HAVE_TAGGED_POINTERS
21 |
22 | int main()
23 | {
24 | // provoke the same nullability warning as the real test
25 | objc_getClass(nil);
26 |
27 | succeed(__FILE__);
28 | }
29 |
30 | #else
31 |
32 | int main()
33 | {
34 | testassert(!_objc_taggedPointersEnabled());
35 | _objc_registerTaggedPointerClass((objc_tag_index_t)0, nil);
36 | fail("should have crashed in _objc_registerTaggedPointerClass()");
37 | }
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/test/taggedPointersTagObfuscationDisabled.m:
--------------------------------------------------------------------------------
1 | // TEST_ENV OBJC_DISABLE_TAG_OBFUSCATION=YES
2 |
3 | #include "test.h"
4 | #include
5 |
6 | #if !OBJC_HAVE_TAGGED_POINTERS
7 |
8 | int main()
9 | {
10 | succeed(__FILE__);
11 | }
12 |
13 | #else
14 |
15 | int main()
16 | {
17 | #if OBJC_SPLIT_TAGGED_POINTERS
18 | void *obj = (void *)0;
19 | #else
20 | void *obj = (void *)1;
21 | #endif
22 |
23 | testassert(_objc_getTaggedPointerTag(obj) == 0);
24 | succeed(__FILE__);
25 | }
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/test/tbi.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=iphoneos ARCH=arm64
2 |
3 | #include "test.h"
4 |
5 | #ifndef __arm64__
6 | #error wrong architecture for TBI hardware feature
7 | #endif
8 |
9 | volatile int x = 123456;
10 |
11 | int main(void) {
12 | testassert(*(int *)((unsigned long)&x | 0xFF00000000000000ul) == 123456);
13 | succeed(__FILE__);
14 | }
15 |
--------------------------------------------------------------------------------
/test/test-defines.h:
--------------------------------------------------------------------------------
1 | #define TEST_OVERRIDES_NEW 1
2 |
--------------------------------------------------------------------------------
/test/timeout.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl -w
2 |
3 | use strict;
4 |
5 | my $usage = "timeout \n";
6 | my $timeout = shift || die $usage;
7 | alarm($timeout);
8 | exec @ARGV;
9 | die "exec failed: @ARGV";
10 |
--------------------------------------------------------------------------------
/test/unload.h:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | @interface SmallClass : TestRoot @end
4 |
5 | @interface BigClass : TestRoot @end
6 |
7 |
--------------------------------------------------------------------------------
/test/unload2.m:
--------------------------------------------------------------------------------
1 | #include "unload.h"
2 | #include "testroot.i"
3 | #import
4 |
5 | @implementation SmallClass : TestRoot
6 | -(void)unload2_instance_method { }
7 | @end
8 |
9 |
10 | @implementation BigClass : TestRoot
11 | @end
12 |
13 | OBJC_ROOT_CLASS
14 | @interface UnusedClass { id isa; } @end
15 | @implementation UnusedClass @end
16 |
17 |
18 | @protocol SmallProtocol
19 | -(void)unload2_category_method;
20 | @end
21 |
22 | @interface SmallClass (Category) @end
23 |
24 | @implementation SmallClass (Category)
25 | -(void)unload2_category_method { }
26 | @end
27 |
28 | // This isn't really weak-import: we link with `-undefined dynamic_lookup`
29 | // instead of providing a valid definition at link time.
30 | // But it looks the same to the runtime.
31 | __attribute__((weak_import))
32 | @interface ClassThatIsWeakImportAndMissing : TestRoot @end
33 |
34 | @interface SubclassOfMissingWeakImport : ClassThatIsWeakImportAndMissing @end
35 | @implementation SubclassOfMissingWeakImport
36 | -(void)unload2_category_method { }
37 | @end
38 |
39 | @interface ClassThatIsWeakImportAndMissing (Category) @end
40 | @implementation ClassThatIsWeakImportAndMissing (Category)
41 | -(void)unload2_category_method { }
42 | @end
43 |
--------------------------------------------------------------------------------
/test/unload3.c:
--------------------------------------------------------------------------------
1 | // unload3: contains imageinfo but no other objc metadata
2 | // libobjc must not keep it open
3 |
4 | #include
5 |
6 | int fake[2] __attribute__((section("__DATA,__objc_imageinfo")))
7 | = { 0, TARGET_OS_SIMULATOR ? (1<<5) : 0 };
8 |
9 | // silence "no debug symbols in executable" warning
10 | void fn(void) { }
11 |
--------------------------------------------------------------------------------
/test/unload4.m:
--------------------------------------------------------------------------------
1 | // unload4: contains some objc metadata other than imageinfo
2 | // libobjc must keep it open
3 |
4 | int fake2 __attribute__((section("__DATA,__objc_foo"))) = 0;
5 |
6 | // getsectiondata() falls over if __TEXT has no contents
7 | const char *unload4 = "unload4";
8 |
--------------------------------------------------------------------------------
/test/unwind.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | static int state;
8 |
9 | @interface Foo : NSObject @end
10 | @interface Bar : NSObject @end
11 |
12 | @interface Foo (Unimplemented)
13 | +(void)method;
14 | @end
15 |
16 | @implementation Bar @end
17 |
18 | @implementation Foo
19 |
20 | -(void)check { state++; }
21 | +(void)check { testassert(!"caught class object, not instance"); }
22 |
23 | static id exc;
24 |
25 | static void handler(id unused, void *ctx) __attribute__((used));
26 | static void handler(id unused __unused, void *ctx __unused)
27 | {
28 | testassert(state == 3); state++;
29 | }
30 |
31 | +(BOOL) resolveClassMethod:(SEL)__unused name
32 | {
33 | testassert(state == 1); state++;
34 | #if TARGET_OS_OSX
35 | objc_addExceptionHandler(&handler, 0);
36 | testassert(state == 2);
37 | #else
38 | state++; // handler would have done this
39 | #endif
40 | state++;
41 | exc = [Foo new];
42 | @throw exc;
43 | }
44 |
45 |
46 | @end
47 |
48 | int main()
49 | {
50 | // unwind exception and alt handler through objc_msgSend()
51 |
52 | PUSH_POOL {
53 |
54 | const int count = is_guardmalloc() ? 1000 : 100000;
55 | state = 0;
56 | for (int i = 0; i < count; i++) {
57 | @try {
58 | testassert(state == 0); state++;
59 | [Foo method];
60 | testassert(0);
61 | } @catch (Bar *e) {
62 | testassert(0);
63 | } @catch (Foo *e) {
64 | testassert(e == exc);
65 | testassert(state == 4); state++;
66 | testassert(state == 5); [e check]; // state++
67 | RELEASE_VAR(exc);
68 | } @catch (id e) {
69 | testassert(0);
70 | } @catch (...) {
71 | testassert(0);
72 | } @finally {
73 | testassert(state == 6); state++;
74 | }
75 | testassert(state == 7); state = 0;
76 | }
77 |
78 | } POP_POOL;
79 |
80 | succeed(__FILE__);
81 | }
82 |
--------------------------------------------------------------------------------
/test/weak.h:
--------------------------------------------------------------------------------
1 | /*
2 | To test -weak-l or -weak-framework:
3 | * -DWEAK_IMPORT=
4 | * -DWEAK_FRAMEWORK=1
5 | * -UEMPTY when building the weak-not-missing library
6 | * -DEMPTY= when building the weak-missing library
7 |
8 | To test attribute((weak_import)):
9 | * -DWEAK_IMPORT=__attribute__((weak_import))
10 | * -UWEAK_FRAMEWORK
11 | * -UEMPTY when building the weak-not-missing library
12 | * -DEMPTY= when building the weak-missing library
13 |
14 | */
15 |
16 | #include "test.h"
17 | #include
18 |
19 | extern int state;
20 |
21 | WEAK_IMPORT OBJC_ROOT_CLASS
22 | @interface MissingRoot {
23 | id isa;
24 | }
25 | +(void) initialize;
26 | +(Class) class;
27 | +(id) alloc;
28 | -(id) init;
29 | -(void) dealloc;
30 | +(int) method;
31 | @end
32 |
33 | @interface MissingRoot (RR)
34 | -(id) retain;
35 | -(void) release;
36 | @end
37 |
38 | WEAK_IMPORT
39 | @interface MissingSuper : MissingRoot {
40 | @public
41 | int ivar;
42 | }
43 | @end
44 |
45 | OBJC_ROOT_CLASS
46 | @interface NotMissingRoot {
47 | id isa;
48 | }
49 | +(void) initialize;
50 | +(Class) class;
51 | +(id) alloc;
52 | -(id) init;
53 | -(void) dealloc;
54 | +(int) method;
55 | @end
56 |
57 | @interface NotMissingRoot (RR)
58 | -(id) retain;
59 | -(void) release;
60 | @end
61 |
62 | @interface NotMissingSuper : NotMissingRoot {
63 | @public
64 | int unused[100];
65 | int ivar;
66 | }
67 | @end
68 |
--------------------------------------------------------------------------------
/test/weakReferenceHook.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG MEM=mrc
3 | TEST_ENV OBJC_DISABLE_NONPOINTER_ISA=YES
4 | */
5 |
6 | #include "test.h"
7 | #include "testroot.i"
8 |
9 | bool hasWeakRefs = false;
10 |
11 | @interface TestRoot (WeakHooks)
12 | @end
13 |
14 | @implementation TestRoot (WeakHooks)
15 |
16 | - (void)_setWeaklyReferenced {
17 | hasWeakRefs = true;
18 | }
19 |
20 | // -_setWeaklyReferenced is currently limited to raw-isa custom-rr to avoid overhead
21 | - (void) release {
22 | }
23 |
24 | @end
25 |
26 | int main() {
27 | id obj = [TestRoot new];
28 | id wobj = nil;
29 | objc_storeWeak(&wobj, obj);
30 | testassert(hasWeakRefs == true);
31 |
32 | id out = objc_loadWeak(&wobj);
33 | testassert(out == obj);
34 |
35 | objc_storeWeak(&wobj, nil);
36 | out = objc_loadWeak(&wobj);
37 | testassert(out == nil);
38 |
39 | hasWeakRefs = false;
40 | objc_storeWeak(&wobj, obj);
41 | testassert(hasWeakRefs == true);
42 |
43 |
44 | out = objc_loadWeak(&wobj);
45 | testassert(out == obj);
46 | objc_storeWeak(&wobj, nil);
47 |
48 | succeed(__FILE__);
49 | }
50 |
--------------------------------------------------------------------------------
/test/weakcopy.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -fobjc-weak
2 |
3 | #include "test.h"
4 |
5 | #include "testroot.i"
6 | #include
7 | #include
8 | #include
9 |
10 | @interface Weak : TestRoot {
11 | @public
12 | __weak id value;
13 | }
14 | @end
15 | @implementation Weak
16 | @end
17 |
18 | Weak *oldObject;
19 | Weak *newObject;
20 |
21 | int main()
22 | {
23 | testonthread(^{
24 | TestRoot *value;
25 |
26 | PUSH_POOL {
27 | value = [TestRoot new];
28 | testassert(value);
29 | oldObject = [Weak new];
30 | testassert(oldObject);
31 |
32 | oldObject->value = value;
33 | testassert(oldObject->value == value);
34 |
35 | newObject = [oldObject copy];
36 | testassert(newObject);
37 | testassert(newObject->value == oldObject->value);
38 |
39 | newObject->value = nil;
40 | testassert(newObject->value == nil);
41 | testassert(oldObject->value == value);
42 | } POP_POOL;
43 |
44 | testcollect();
45 | TestRootDealloc = 0;
46 | RELEASE_VAR(value);
47 | });
48 |
49 | testcollect();
50 | testassert(TestRootDealloc);
51 |
52 | #if __has_feature(objc_arc_weak)
53 | testassert(oldObject->value == nil);
54 | #endif
55 | testassert(newObject->value == nil);
56 |
57 | RELEASE_VAR(newObject);
58 | RELEASE_VAR(oldObject);
59 |
60 | succeed(__FILE__);
61 | return 0;
62 | }
63 |
--------------------------------------------------------------------------------
/test/weakframework-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -DWEAK_FRAMEWORK=1 -DWEAK_IMPORT= -UEMPTY -dynamiclib -o libweakframework.dylib
4 |
5 | $C{COMPILE} $DIR/weakframework-missing.m -L. -weak-lweakframework -o weakframework-missing.exe
6 |
7 | $C{COMPILE} $DIR/weak2.m -DWEAK_FRAMEWORK=1 -DWEAK_IMPORT= -DEMPTY= -dynamiclib -o libweakframework.dylib
8 |
9 | END
10 | */
11 |
12 | #define WEAK_FRAMEWORK 1
13 | #define WEAK_IMPORT
14 | #include "weak.m"
15 |
--------------------------------------------------------------------------------
/test/weakframework-not-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -DWEAK_FRAMEWORK=1 -DWEAK_IMPORT= -UEMPTY -dynamiclib -o libweakframework.dylib
4 |
5 | $C{COMPILE} $DIR/weakframework-not-missing.m -L. -weak-lweakframework -o weakframework-not-missing.exe
6 | END
7 | */
8 |
9 | #define WEAK_FRAMEWORK 1
10 | #define WEAK_IMPORT
11 | #include "weak.m"
12 |
--------------------------------------------------------------------------------
/test/weakimport-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -UWEAK_FRAMEWORK -DWEAK_IMPORT=__attribute__\\(\\(weak_import\\)\\) -UEMPTY -dynamiclib -o libweakimport.dylib
4 |
5 | $C{COMPILE} $DIR/weakimport-missing.m -L. -weak-lweakimport -o weakimport-missing.exe
6 |
7 | $C{COMPILE} $DIR/weak2.m -UWEAK_FRAMEWORK -DWEAK_IMPORT=__attribute__\\(\\(weak_import\\)\\) -DEMPTY= -dynamiclib -o libweakimport.dylib
8 | END
9 | */
10 |
11 | // #define WEAK_FRAMEWORK
12 | #define WEAK_IMPORT __attribute__((weak_import))
13 | #include "weak.m"
14 |
--------------------------------------------------------------------------------
/test/weakimport-not-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -UWEAK_FRAMEWORK -DWEAK_IMPORT=__attribute__\\(\\(weak_import\\)\\) -UEMPTY -dynamiclib -o libweakimport.dylib
4 |
5 | $C{COMPILE} $DIR/weakimport-not-missing.m -L. -weak-lweakimport -o weakimport-not-missing.exe
6 | END
7 | */
8 |
9 | // #define WEAK_FRAMEWORK
10 | #define WEAK_IMPORT __attribute__((weak_import))
11 | #include "weak.m"
12 |
--------------------------------------------------------------------------------
/test/weakrace.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include
5 |
6 | static semaphore_t go1;
7 | static semaphore_t go2;
8 | static semaphore_t done;
9 |
10 | #define VARCOUNT 100000
11 | static id obj;
12 | static id vars[VARCOUNT];
13 |
14 |
15 | void *destroyer(void *arg __unused)
16 | {
17 | while (1) {
18 | semaphore_wait(go1);
19 | for (int i = 0; i < VARCOUNT; i++) {
20 | objc_destroyWeak(&vars[i]);
21 | }
22 | semaphore_signal(done);
23 | }
24 | }
25 |
26 |
27 | void *deallocator(void *arg __unused)
28 | {
29 | while (1) {
30 | semaphore_wait(go2);
31 | [obj release];
32 | semaphore_signal(done);
33 | }
34 | }
35 |
36 |
37 | void cycle(void)
38 | {
39 | // rdar://12896779 objc_destroyWeak() versus weak clear in dealloc
40 |
41 | // Clean up from previous cycle - objc_destroyWeak() doesn't set var to nil
42 | for (int i = 0; i < VARCOUNT; i++) {
43 | vars[i] = nil;
44 | }
45 |
46 | obj = [NSObject new];
47 | for (int i = 0; i < VARCOUNT; i++) {
48 | objc_storeWeak(&vars[i], obj);
49 | }
50 |
51 | // let destroyer start before deallocator runs
52 | semaphore_signal(go1);
53 | sched_yield();
54 | semaphore_signal(go2);
55 |
56 | semaphore_wait(done);
57 | semaphore_wait(done);
58 | }
59 |
60 |
61 | int main()
62 | {
63 | semaphore_create(mach_task_self(), &go1, 0, 0);
64 | semaphore_create(mach_task_self(), &go2, 0, 0);
65 | semaphore_create(mach_task_self(), &done, 0, 0);
66 |
67 | pthread_t th[2];
68 | pthread_create(&th[1], NULL, deallocator, NULL);
69 | pthread_create(&th[1], NULL, destroyer, NULL);
70 |
71 | for (int i = 0; i < 100; i++) {
72 | cycle();
73 | }
74 |
75 | succeed(__FILE__);
76 | }
77 |
--------------------------------------------------------------------------------
/test/zone.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | // Look for malloc zone "ObjC" iff OBJC_USE_INTERNAL_ZONE is set.
8 | // This fails if objc tries to allocate before checking its own
9 | // environment variables (rdar://6688423)
10 |
11 | int main()
12 | {
13 | if (is_guardmalloc()) {
14 | // guard malloc confuses this test
15 | succeed(__FILE__);
16 | }
17 |
18 | kern_return_t kr;
19 | vm_address_t *zones;
20 | unsigned int count, i;
21 | BOOL has_objc = NO, want_objc = NO;
22 |
23 | want_objc = (getenv("OBJC_USE_INTERNAL_ZONE") != NULL) ? YES : NO;
24 | testprintf("want objc %s\n", want_objc ? "YES" : "NO");
25 |
26 | kr = malloc_get_all_zones(mach_task_self(), NULL, &zones, &count);
27 | testassert(!kr);
28 | for (i = 0; i < count; i++) {
29 | const char *name = malloc_get_zone_name((malloc_zone_t *)zones[i]);
30 | if (name) {
31 | BOOL is_objc = (0 == strcmp(name, "ObjC_Internal")) ? YES : NO;
32 | if (is_objc) has_objc = YES;
33 | testprintf("zone %s\n", name);
34 | }
35 | }
36 |
37 | testassert(want_objc == has_objc);
38 |
39 | succeed(__FILE__);
40 | }
41 |
--------------------------------------------------------------------------------
/unexported_symbols:
--------------------------------------------------------------------------------
1 | .objc_class_name___IncompleteProtocol
2 | __Znam
3 | __ZnamRKSt9nothrow_t
4 | __Znwm
5 | __ZnwmRKSt9nothrow_t
6 | __ZdaPv
7 | __ZdaPvRKSt9nothrow_t
8 | __ZdlPv
9 | __ZdlPvRKSt9nothrow_t
10 | __ZTISt9bad_alloc
11 | __ZTISt9exception
12 | __ZTISt11logic_error
13 | __ZTISt12length_error
14 | __ZTSSt9bad_alloc
15 | __ZTSSt9exception
16 | __ZTSSt11logic_error
17 | __ZTSSt12length_error
18 |
--------------------------------------------------------------------------------
/version.bat:
--------------------------------------------------------------------------------
1 | :: version.bat
2 | :: Writes version numbers from B&I into version.h for use by version.rc.
3 |
4 | @ECHO OFF
5 |
6 | :: Set default values for environment variables if not set by B&I
7 | IF "%OBJROOT%"=="" SET OBJROOT=.
8 | IF "%RC_PROJECTSOURCEVERSION%"=="" SET RC_PROJECTSOURCEVERSION=0.0
9 | IF "%RC_PROJECTBUILDVERSION%"=="" SET RC_PROJECTBUILDVERSION=0
10 |
11 | :: Get version numbers from environment variables
12 | SET major=1
13 | SET patch=0
14 | FOR /F "tokens=1* eol= delims=." %%i IN ("%RC_PROJECTSOURCEVERSION%") DO (
15 | SET minor=%%i
16 | IF NOT "%%j"=="" SET patch=%%j
17 | )
18 | SET build=%RC_PROJECTBUILDVERSION%
19 |
20 | ECHO version %major% . %minor% . %patch% . %build%
21 |
22 | :: Write version.h
23 | ECHO // This file is automatically generated by version.bat. > "%OBJROOT%\version.h"
24 | ECHO // DO NOT EDIT >> "%OBJROOT%\version.h"
25 | ECHO #define major %major% >> "%OBJROOT%\version.h"
26 | ECHO #define minor %minor% >> "%OBJROOT%\version.h"
27 | ECHO #define patch %patch% >> "%OBJROOT%\version.h"
28 | ECHO #define build %build% >> "%OBJROOT%\version.h"
29 | ECHO #define string "%major%,%minor%,%patch%,%build%" >> "%OBJROOT%\version.h"
30 |
--------------------------------------------------------------------------------
/version.rc:
--------------------------------------------------------------------------------
1 | #include "Winver.h"
2 |
3 | // built by version.bat; sets variables major, minor, patch, build, string
4 | #include "version.h"
5 |
6 | VS_VERSION_INFO VERSIONINFO
7 | FILEVERSION major,minor,patch,build
8 | PRODUCTVERSION major,minor,patch,build
9 | FILEFLAGSMASK 0x17L
10 | #ifdef _DEBUG
11 | FILEFLAGS VS_FF_DEBUG
12 | #else
13 | FILEFLAGS 0x0L
14 | #endif
15 | FILEOS VOS_NT_WINDOWS32
16 | FILETYPE VFT_DLL
17 | FILESUBTYPE VFT2_UNKNOWN
18 | BEGIN
19 | BLOCK "StringFileInfo"
20 | BEGIN
21 | BLOCK "040904b0"
22 | BEGIN
23 | VALUE "CompanyName", "Apple Inc."
24 | VALUE "FileDescription", "Objective-C Runtime Library"
25 | VALUE "FileVersion", string
26 | VALUE "ProductVersion", string
27 | VALUE "ProductName", "objc4"
28 | VALUE "InternalName", "objc4"
29 | VALUE "LegalCopyright", "Copyright (C) 2007-2009, Apple Inc."
30 | VALUE "OriginalFilename", "objc.dll"
31 | END
32 | END
33 | BLOCK "VarFileInfo"
34 | BEGIN
35 | VALUE "Translation", 0x409, 1200
36 | END
37 | END
38 |
39 |
--------------------------------------------------------------------------------