├── .editorconfig
├── APPLE_LICENSE
├── ObjectiveC-swiftoverlay-Test-Dylib
└── Trees.swift
├── ObjectiveC.xctestplan
├── ObjectiveC
├── ObjectiveC.swift
├── ObjectiveC.xcconfig
├── ObjectiveCRPathInstallName.c
└── ObjectiveCRPathInstallName.h
├── ObjectiveCTests
├── Creatures.swift
├── ObjectiveC.swift
├── StdlibUnittest checkEquatable.swift
└── StdlibUnittest checkHashable.swift
├── ReleaseNotes.rtf
├── markgc.cpp
├── objc-vfs-overlay
└── write-vfs-overlay.sh
├── objc.sln
├── objc.xcconfig
├── objc.xcodeproj
├── project.pbxproj
└── xcshareddata
│ └── xcschemes
│ └── ObjectiveC.xcscheme
├── objc4.plist
├── objcdt
├── json.h
├── json.mm
├── objcdt-entitlements.plist
├── objcdt.1
└── objcdt.mm
├── objcrt
└── objcrt.vcproj
├── prebuild.bat
├── runtime
├── DenseMapExtras.h
├── InitWrappers.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
│ └── ObjectiveC.modulemap
├── ModulePrivate
│ ├── ObjectiveC_Private.apinotes
│ └── ObjectiveC_Private.modulemap
├── NSObjCRuntime.h
├── NSObject-internal.h
├── NSObject-private.h
├── NSObject.h
├── NSObject.mm
├── Object.h
├── Object.mm
├── OldClasses.subproj
│ └── List.h
├── PointerUnion.h
├── Protocol.h
├── Protocol.mm
├── Threading
│ ├── c11threads.h
│ ├── darwin.h
│ ├── lockdebug.h
│ ├── mixins.h
│ ├── nothreads.h
│ ├── pthreads.h
│ ├── threading.h
│ └── tls.h
├── 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.mm
├── objc-class.h
├── objc-class.mm
├── objc-config.h
├── objc-env.h
├── objc-errors.mm
├── objc-exception.h
├── objc-exception.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.mm
├── objc-locks.h
├── objc-magicsel.m
├── objc-malloc-instance.h
├── objc-object.h
├── objc-opt.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.h
├── objc-runtime.mm
├── objc-sel-table.s
├── objc-sel.mm
├── objc-sync.h
├── objc-sync.mm
├── objc-test-env.c
├── objc-test-env.h
├── objc-typeencoding.mm
├── objc-vm.h
├── objc-weak.h
├── objc-weak.mm
├── objc-zalloc.h
├── objc-zalloc.mm
├── objc.h
├── objcrt.h
├── retain-release-helpers-arm64.s
└── runtime.h
├── scripts
├── exclave-run
├── print-image-loading
└── time-startup
├── test
├── 00-defines.c
├── 01-headers.c
├── 02-concurrentcat.m
├── 03-load-parallel.m
├── 04-load-image-notification.m
├── 05-load-image-notification2.m
├── 06-ARCLayoutsWithoutWeak.m
├── ARCBase.h
├── ARCBase.m
├── ARCLayouts.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-error.m
├── arr-weak.m
├── asm-placeholder.s
├── association.m
├── associationForbidden.h
├── associationForbidden.m
├── associationForbidden2.m
├── associationForbidden3.m
├── associationForbidden4.m
├── atomicProperty.mm
├── badAltHandler.m
├── badCache.m
├── badPool.m
├── badPoolCompat-ios-simulator.m
├── badPoolCompat-ios.m
├── badPoolCompat-macos.m
├── badPoolCompat-tvos-simulator.m
├── badPoolCompat-tvos.m
├── badPoolCompat-watchos-simulator.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
├── class-structures.h
├── classgetclass.m
├── classname.m
├── classpair-stress.m
├── classpair.mm
├── classpairAddMethod.m
├── classversion.m
├── concurrentcat_category.m
├── consolidatePoolPointers.m
├── copyFixupHandler.mm
├── copyIvarList.m
├── copyMethodList.m
├── copyPropertyList.m
├── copyProtocolList.m
├── createInstance.m
├── customDeallocInitiation.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.expected
├── defines.sh
├── definitions.c
├── designatedinit.m
├── duplicateClass.m
├── duplicateProtocols.m
├── duplicatedClasses.m
├── duplicatedClasses0.m
├── duplicatedClasses2.m
├── duplicatedClasses3.m
├── enumClasses.h
├── enumClasses.m
├── enumClasses0.m
├── enumClasses1.m
├── evil-class-def.m
├── exc.m
├── exchangeImp.m
├── fakeRealizedClass.m
├── fakeRealizedClass2.m
├── faultLeaks.m
├── foreach.m
├── fork.m
├── forkInitialize.m
├── forkInitializeDisabled.m
├── forkInitializeSingleThreaded.m
├── forkSync.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.sh
├── imageAPIs.m
├── imageorder.h
├── imageorder.m
├── imageorder1.m
├── imageorder2.m
├── imageorder3.m
├── imports.c
├── include-warnings.c
├── includes-objc2.c
├── includes.c
├── initialize-autorelease.m
├── initialize.m
├── initializePriorityDonation.m
├── initializeVersusWeak.m
├── instanceSize.m
├── isaValidation.mm
├── ismeta.m
├── ivar.m
├── ivarSlide.h
├── ivarSlide.m
├── ivarSlide1.m
├── lazyClassName.m
├── lazyClassNameRace.swift
├── libraryPath.c
├── literals.m
├── load-image-notification-dylib.m
├── load-map-images.m
├── load-order.m
├── load-order1.m
├── load-order2.m
├── load-order3.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-macos.m
├── msgSend-performance.m
├── msgSend.m
├── nilAPIArgs.m
├── nonpointerisa.m
├── nopool.m
├── nscdtors.mm
├── nsexc.m
├── nsobject.m
├── nsprotocol.m
├── objectCopy.m
├── osVersion.m
├── partiallyRealizedClass.m
├── patch-class-root.m
├── preAttachedCategories.mm
├── preopt-caches.entitlements
├── preopt-caches.mm
├── property.m
├── propertyDesc.m
├── protocol.m
├── protocolSmall.m
├── protocol_copyMethodList.m
├── protocol_copyPropertyList.m
├── ptrauth.m
├── rawisa.m
├── readClassPair.m
├── readClassPairIvarFixup.m
├── realizedClassGenerationCount.m
├── release-race.m
├── release-workaround.m
├── resolve.m
├── restartableRangesSynchronizeStress.m
├── restartableRangesSynchronizeStress2.m
├── retain-release-helpers.m
├── rootMissingCategoryClass.m
├── rootMissingSuperclass.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
├── signedMethodSelectors.m
├── subscripting.m
├── super.m
├── supported-inline-refcnt.m
├── swift-allocateClassPair.swift
├── swift-class-def.m
├── swiftMetaMeta.swift
├── swiftMetadataInitializer.m
├── swiftMetadataInitializerRealloc-dylib1.m
├── swiftMetadataInitializerRealloc-dylib2.m
├── swiftMetadataInitializerRealloc.m
├── swiftStubClassList.m
├── swiftobject-no-custom-core.mm
├── sync-error-checking.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-simulator.sh
├── test-simulator
│ ├── Package.swift
│ └── Sources
│ │ └── test-simulator
│ │ └── test_simulator.swift
├── test.h
├── test.pl
├── testroot.i
├── timeout.pl
├── unexpectedBuildOutput.mm
├── uniquelyref.m
├── unload.h
├── unload.m
├── unload2.m
├── unload3.c
├── unload4.m
├── unload5.m
├── unrealizedClassSafety.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
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style=space
5 | indent_size=4
6 |
--------------------------------------------------------------------------------
/ObjectiveC-swiftoverlay-Test-Dylib/Trees.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Trees.swift
3 | // Trees
4 | //
5 | // Created by Alastair Houghton on 02/09/2021.
6 | // Copyright © 2021 Apple. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | @objc
12 | protocol Tree {
13 | func name() -> String
14 | func isEvergreen() -> Bool
15 | }
16 |
17 | @objc
18 | class Oak: NSObject, Tree {
19 | public func name() -> String { return "oak" }
20 | public func isEvergreen() -> Bool { return false }
21 | }
22 |
23 | @objc
24 | class Birch: NSObject, Tree {
25 | public func name() -> String { return "birch" }
26 | public func isEvergreen() -> Bool { return false }
27 | }
28 |
29 | @objc
30 | class Pine: NSObject, Tree {
31 | public func name() -> String { return "birch" }
32 | public func isEvergreen() -> Bool { return false }
33 | }
34 |
35 | @available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
36 | @_cdecl("testEnumerateClassesFromDylib")
37 | public func testEnumerateClassesFromDylib() -> Bool {
38 | // This should enumerate the classes *in the dylib*
39 | let trees = objc_enumerateClasses().map{ "\($0)" }
40 | if trees == [ "Oak", "Birch", "Pine" ] {
41 | return true
42 | } else {
43 | print("FAILED: trees was \(trees)!")
44 | return false
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/ObjectiveC.xctestplan:
--------------------------------------------------------------------------------
1 | {
2 | "configurations" : [
3 | {
4 | "id" : "A96CEB60-D6D0-40A5-9F09-DA83D83BA6D0",
5 | "name" : "Test Scheme Action",
6 | "options" : {
7 |
8 | }
9 | }
10 | ],
11 | "defaultOptions" : {
12 | "codeCoverage" : false
13 | },
14 | "testTargets" : [
15 | {
16 | "target" : {
17 | "containerPath" : "container:objc.xcodeproj",
18 | "identifier" : "8425816A2CEEB869007C1920",
19 | "name" : "ObjectiveCTests"
20 | }
21 | }
22 | ],
23 | "version" : 1
24 | }
25 |
--------------------------------------------------------------------------------
/ObjectiveC/ObjectiveCRPathInstallName.c:
--------------------------------------------------------------------------------
1 | //
2 | // ObjectiveCRPathInstallName.c
3 | // ObjectiveC
4 | //
5 | // Copyright © 2024 Apple Inc. All rights reserved.
6 | //
7 |
8 | #include "ObjectiveCRPathInstallName.h"
9 |
10 | const char ld_previous_objectivec_rpath = '\0';
11 |
--------------------------------------------------------------------------------
/objc-vfs-overlay/write-vfs-overlay.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Create a VFS overlay to virtually install the build products into the SDK.
4 | # The LLVM virtual filesystem is documented here.
5 | # http://llvm.org/doxygen/classllvm_1_1vfs_1_1RedirectingFileSystem.html#details
6 | if [ "$RC_XBS" = "YES" -a "$RC_BUILDIT" != "YES" ]
7 | then
8 | # The overlay is not needed in an XBS environment where installhdrs merges the
9 | # build products into the SDK before the other targets run installapi/install.
10 | roots=" []"
11 | else
12 | roots="
13 | -
14 | type: directory
15 | name: ${SDKROOT}/usr/include
16 | contents:
17 | -
18 | type: file
19 | name: ObjectiveC.apinotes
20 | external-contents: ${BASE_DIRECTORY}/usr/include/ObjectiveC.apinotes
21 | -
22 | type: file
23 | name: ObjectiveC.modulemap
24 | external-contents: ${BASE_DIRECTORY}/usr/include/ObjectiveC.modulemap
25 | -
26 | type: directory-remap
27 | name: objc
28 | external-contents: ${BASE_DIRECTORY}/usr/include/objc
29 | -
30 | type: directory
31 | name: ${SDKROOT}/usr/local/include
32 | contents:
33 | -
34 | type: file
35 | name: ObjectiveC_Private.apinotes
36 | external-contents: ${BASE_DIRECTORY}/usr/local/include/ObjectiveC_Private.apinotes
37 | -
38 | type: file
39 | name: ObjectiveC_Private.modulemap
40 | external-contents: ${BASE_DIRECTORY}/usr/local/include/ObjectiveC_Private.modulemap
41 | -
42 | type: directory-remap
43 | name: objc
44 | external-contents: ${BASE_DIRECTORY}/usr/local/include/objc"
45 | fi
46 |
47 | printf "\
48 | version: 0
49 | roots:%s" \
50 | "$roots" > "$SCRIPT_OUTPUT_FILE_0"
51 |
--------------------------------------------------------------------------------
/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.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS[sdk=exclavekit*] = $(inherited) DTRACE_PROBES_DISABLED=1
2 | INSTALL_FEATURE_FLAGS[sdk=exclavekit*] = NO
3 |
4 | INSTALLHDRS_SCRIPT_PHASE = YES
5 |
6 | SCRIPT_OUTPUT_DIR = $(SCRIPT_OUTPUT_DIR__$(DEPLOYMENT_LOCATION:default=NO))
7 | SCRIPT_OUTPUT_DIR__NO = $(TARGET_BUILD_DIR)
8 | SCRIPT_OUTPUT_DIR__YES = $(DSTROOT)
9 |
10 | MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH = $(SCRIPT_OUTPUT_DIR)/$(PRIVATE_HEADERS_FOLDER_PATH)
11 | MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH[sdk=macosx*] = $(SCRIPT_OUTPUT_DIR)/$(PUBLIC_HEADERS_FOLDER_PATH)
12 |
13 | MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS = $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/List.h $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/Object.h $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/Protocol.h $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/hashtable.h $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/hashtable2.h $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/objc-class.h $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/objc-load.h $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS_FOLDER_PATH)/objc-runtime.h
14 |
15 | TAPI_EXTRA_PUBLIC_HEADERS[sdk=macosx*] = $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS)
16 |
17 | TAPI_EXTRA_PRIVATE_HEADERS = $(MACOSPUBLIC_OTHERWISEPRIVATE_HEADERS)
18 | TAPI_EXTRA_PRIVATE_HEADERS[sdk=macosx*] =
19 |
--------------------------------------------------------------------------------
/objc4.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | autoreleaseFaultsMacOS
6 |
7 | Enabled
8 |
9 |
10 | preoptimizedCaches
11 |
12 | Enabled
13 |
14 |
15 | classRxSigning
16 |
17 | Enabled
18 |
19 |
20 | classRoSigningFaults
21 |
22 | Enabled
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/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/DenseMapExtras.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 DENSEMAPEXTRAS_H
25 | #define DENSEMAPEXTRAS_H
26 |
27 | #include "InitWrappers.h"
28 | #include "llvm-DenseMap.h"
29 | #include "llvm-DenseSet.h"
30 |
31 | namespace objc {
32 |
33 | // Convenience class for Dense Maps & Sets
34 | template
35 | class ExplicitInitDenseMap : public ExplicitInit> { };
36 |
37 | template
38 | class LazyInitDenseMap : public LazyInit> { };
39 |
40 | template
41 | class ExplicitInitDenseSet : public ExplicitInit> { };
42 |
43 | template
44 | class LazyInitDenseSet : public LazyInit> { };
45 |
46 | } // namespace objc
47 |
48 | #endif /* DENSEMAPEXTRAS_H */
49 |
--------------------------------------------------------------------------------
/runtime/Module/ObjectiveC.modulemap:
--------------------------------------------------------------------------------
1 | module ObjectiveC [system] {
2 | // These must all be set in the GCC_PREPROCESSOR_DEFINITIONS Xcode build
3 | // setting, or passed on the command line with -D in order to have an
4 | // effect. #define won't do anything for any of these.
5 | #if 0
6 | // config_macros communicates this, but it had to be temporarily disabled due to
7 | // rdar://95261458 (Swift is converting `-Xcc -DABC` to `#define ABC` when building bridging headers, triggers warnings from config_macros)
8 | #endif
9 | // config_macros
10 | // //
11 | // NS_BUILD_32_LIKE_64,
12 | //
13 | // // ,
14 | // OBJC_TYPES_DEFINED,
15 |
16 | umbrella "objc"
17 | export *
18 | module * {
19 | export *
20 | }
21 |
22 | module NSObject {
23 | requires objc
24 | header "objc/NSObject.h"
25 | export *
26 | }
27 | #if defined(BUILD_FOR_OSX)
28 |
29 | module Object {
30 | requires objc
31 | header "objc/Object.h"
32 | export *
33 | }
34 |
35 | module Protocol {
36 | requires objc
37 | header "objc/Protocol.h"
38 | export *
39 | }
40 | #endif
41 | }
42 |
--------------------------------------------------------------------------------
/runtime/ModulePrivate/ObjectiveC_Private.apinotes:
--------------------------------------------------------------------------------
1 | ---
2 | Name: ObjectiveC_Private
3 | Classes:
4 | - Name: List
5 | Methods:
6 | - Selector: init
7 | MethodKind: Instance
8 | NullabilityOfRet: N
9 | - Selector: 'isEqual:'
10 | MethodKind: Instance
11 | Nullability:
12 | - O
13 | NullabilityOfRet: S
14 | - Name: Object
15 | Methods:
16 | - Selector: init
17 | MethodKind: Instance
18 | NullabilityOfRet: N
19 | - Selector: 'isEqual:'
20 | MethodKind: Instance
21 | Nullability:
22 | - O
23 | NullabilityOfRet: S
24 |
--------------------------------------------------------------------------------
/runtime/ModulePrivate/ObjectiveC_Private.modulemap:
--------------------------------------------------------------------------------
1 | module ObjectiveC_Private [system] {
2 | umbrella "objc"
3 | explicit module * { export * }
4 | #ifndef BUILD_FOR_OSX
5 |
6 | explicit module Object {
7 | requires objc
8 | header "objc/Object.h"
9 | export *
10 | }
11 |
12 | explicit module Protocol {
13 | requires objc
14 | header "objc/Protocol.h"
15 | export *
16 | }
17 | #endif
18 | }
19 |
--------------------------------------------------------------------------------
/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 | #include
11 |
12 | #if __LP64__ || NS_BUILD_32_LIKE_64
13 | typedef long NSInteger;
14 | typedef unsigned long NSUInteger;
15 | #else
16 | typedef int NSInteger;
17 | typedef unsigned int NSUInteger;
18 | #endif
19 |
20 | #define NSIntegerMax LONG_MAX
21 | #define NSIntegerMin LONG_MIN
22 | #define NSUIntegerMax ULONG_MAX
23 |
24 | #define NSINTEGER_DEFINED 1
25 |
26 | #ifndef NS_DESIGNATED_INITIALIZER
27 | #if __has_attribute(objc_designated_initializer)
28 | #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
29 | #else
30 | #define NS_DESIGNATED_INITIALIZER
31 | #endif
32 | #endif
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/runtime/Object.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2003, 2005-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 | Object.h
25 | Copyright 1988-1996 NeXT Software, Inc.
26 |
27 | DEFINED AS: A common class
28 | HEADER FILES:
29 |
30 | */
31 |
32 | #ifndef _OBJC_OBJECT_H_
33 | #define _OBJC_OBJECT_H_
34 |
35 | #include
36 | #include
37 |
38 | #endif /* _OBJC_OBJECT_H_ */
39 |
--------------------------------------------------------------------------------
/runtime/Object.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-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 | Object.m
25 | Copyright 1988-1996 NeXT Software, Inc.
26 | */
27 |
28 | #include "objc-private.h"
29 |
30 | #undef id
31 | #undef Class
32 |
33 | typedef struct objc_class *Class;
34 | typedef struct objc_object *id;
35 |
36 | @implementation Object
37 |
38 | + (id)initialize
39 | {
40 | return self;
41 | }
42 |
43 | + (id)class
44 | {
45 | return self;
46 | }
47 |
48 | -(id) retain
49 | {
50 | return _objc_rootRetain(self);
51 | }
52 |
53 | -(void) release
54 | {
55 | _objc_rootRelease(self);
56 | }
57 |
58 | -(id) autorelease
59 | {
60 | return _objc_rootAutorelease(self);
61 | }
62 |
63 | +(id) retain
64 | {
65 | return self;
66 | }
67 |
68 | +(void) release
69 | {
70 | }
71 |
72 | +(id) autorelease
73 | {
74 | return self;
75 | }
76 |
77 | @end
78 |
--------------------------------------------------------------------------------
/runtime/OldClasses.subproj/List.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2002, 2005-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 | List.h
25 | Copyright 1988-1996 NeXT Software, Inc.
26 |
27 | DEFINED AS: A common class
28 | HEADER FILES: objc/List.h
29 |
30 | */
31 |
32 | #ifndef _OBJC_LIST_H_
33 | #define _OBJC_LIST_H_
34 |
35 | // This file intentionally left blank
36 |
37 | #endif /* _OBJC_LIST_H_ */
38 |
--------------------------------------------------------------------------------
/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 | #else
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/Threading/threading.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2022 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 | * threading.h
26 | * Threading support
27 | **********************************************************************/
28 |
29 | #ifndef _OBJC_THREADING_H
30 | #define _OBJC_THREADING_H
31 |
32 | // TLS key identifiers
33 | enum class tls_key {
34 | main = 0,
35 | sync_data = 1,
36 | sync_count = 2,
37 | autorelease_pool = 3,
38 | #if SUPPORT_RETURN_AUTORELEASE
39 | return_autorelease_object = 4,
40 | return_autorelease_address = 5
41 | #endif
42 | };
43 |
44 | #if OBJC_THREADING_PACKAGE == OBJC_THREADING_NONE
45 | #include "nothreads.h"
46 | #elif OBJC_THREADING_PACKAGE == OBJC_THREADING_DARWIN
47 | #include "darwin.h"
48 | #elif OBJC_THREADING_PACKAGE == OBJC_THREADING_PTHREADS
49 | #include "pthreads.h"
50 | #elif OBJC_THREADING_PACKAGE == OBJC_THREADING_C11THREADS
51 | #include "c11threads.h"
52 | #else
53 | #error No threading package selected in objc-config.h
54 | #endif
55 |
56 | #include "mixins.h"
57 | #include "lockdebug.h"
58 | #include "tls.h"
59 |
60 | using objc_lock_t = locker_mixin>;
61 | using objc_recursive_lock_t =
62 | locker_mixin>;
63 | using objc_nodebug_lock_t = locker_mixin;
64 |
65 | #endif // _OBJC_THREADING_H
66 |
--------------------------------------------------------------------------------
/runtime/hashtable.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
--------------------------------------------------------------------------------
/runtime/objc-class.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
--------------------------------------------------------------------------------
/runtime/objc-file.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-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 | #include "objc-private.h"
25 | #include "objc-file.h"
26 |
--------------------------------------------------------------------------------
/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 | extern void classInitializeAtforkPrepare();
40 | extern void classInitializeAtforkParent();
41 | extern void classInitializeAtforkChild();
42 |
43 | __END_DECLS
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/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-load.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2001, 2004-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 | /*
25 | * objc-load.m
26 | * Copyright 1988-1996, NeXT Software, Inc.
27 | * Author: s. naroff
28 | *
29 | */
30 |
31 | #include "objc-private.h"
32 | #include "objc-load.h"
33 |
34 |
--------------------------------------------------------------------------------
/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-magicsel.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 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 | #include
25 |
26 | // All shared cache relative method lists names are offsets from this selector.
27 | // C++ doesn't like emoji identifiers, and this causes ObjC++ to reject this
28 | // @selector expression (rdar://84895077). This probably needs a different long
29 | // term fix, but for now work around the problem by putting this into an ObjC
30 | // file.
31 | uintptr_t sharedCacheRelativeMethodBase() {
32 | SEL sel = @selector(🤯);
33 | return (uintptr_t)sel;
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/runtime/objc-malloc-instance.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 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_MALLOC_INSTANCE_H
25 | #define _OBJC_MALLOC_INSTANCE_H
26 |
27 | #include
28 | #if _MALLOC_TYPE_ENABLED
29 | # include
30 | #endif
31 |
32 | namespace objc {
33 |
34 | static inline id
35 | malloc_instance(size_t size, Class cls __unused)
36 | {
37 | #if _MALLOC_TYPE_ENABLED
38 | malloc_type_descriptor_t desc = {};
39 | desc.summary.type_kind = MALLOC_TYPE_KIND_OBJC;
40 | return (id)malloc_type_calloc(1, size, desc.type_id);
41 | #else
42 | return (id)calloc(1, size);
43 | #endif
44 | }
45 |
46 | } // namespace objc
47 |
48 | #endif // _OBJC_MALLOC_INSTANCE_H
49 |
--------------------------------------------------------------------------------
/runtime/objc-opt.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 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-opt.h
26 | Management of optimizations in the dyld shared cache
27 | */
28 |
29 | #ifndef _OBJC_OPT_H
30 | #define _OBJC_OPT_H
31 |
32 | #include
33 |
34 | typedef struct header_info_rw {
35 |
36 | bool getLoaded() const {
37 | return isLoaded;
38 | }
39 |
40 | void setLoaded(bool v) {
41 | isLoaded = v ? 1: 0;
42 | }
43 |
44 | struct header_info *getNext() const {
45 | return (struct header_info *)(next << 2);
46 | }
47 |
48 | void setNext(struct header_info *v) {
49 | next = ((uintptr_t)v) >> 2;
50 | }
51 |
52 | private:
53 | #ifdef __LP64__
54 | uintptr_t isLoaded : 1;
55 | [[maybe_unused]] uintptr_t unused : 1;
56 | uintptr_t next : 62;
57 | #else
58 | uintptr_t isLoaded : 1;
59 | [[maybe_unused]] uintptr_t unused : 1;
60 | uintptr_t next : 30;
61 | #endif
62 | } header_info_rw;
63 |
64 | struct objc_headeropt_rw_t {
65 | uint32_t count;
66 | uint32_t entsize;
67 | header_info_rw headers[0]; // sorted by mhdr address
68 | };
69 |
70 | #endif // _OBJC_OPT_H
71 |
--------------------------------------------------------------------------------
/runtime/objc-probes.d:
--------------------------------------------------------------------------------
1 | typedef void *Class;
2 | typedef const char *SEL;
3 | typedef void *IMP;
4 |
5 | provider objc_runtime
6 | {
7 | // Exception handling
8 | probe objc_exception_throw(void *id);
9 | probe objc_exception_rethrow();
10 |
11 | // Initialization time things; you may need to use
12 | //
13 | // dtrace -x evaltime=preinit -Z
14 | //
15 | // in order to catch everything
16 | probe load_image(const char *name, int bundle, int hasClassProperties, int preoptimized);
17 |
18 | // Different phases of initialization
19 | probe first_time__start();
20 | probe first_time__end();
21 |
22 | probe fixup_selectors__start();
23 | probe fixup_selectors__end();
24 |
25 | probe discover_classes__start();
26 | probe discover_classes__end();
27 |
28 | probe remap_classes__start();
29 | probe remap_classes__end();
30 |
31 | probe fixup_vtables__start();
32 | probe fixup_vtables__end();
33 |
34 | probe discover_protocols__start();
35 | probe discover_protocols__end();
36 |
37 | probe fixup_protocols__start();
38 | probe fixup_protocols__end();
39 |
40 | probe discover_categories__start();
41 | probe discover_categories__end();
42 |
43 | probe realize_non_lazy_classes__start();
44 | probe realize_non_lazy_classes__end();
45 |
46 | probe realize_future_classes__start();
47 | probe realize_future_classes__end();
48 |
49 | // Method cache
50 | probe cache_miss(void *id, SEL sel, Class cls);
51 | probe cache_flush(Class cls);
52 |
53 | // Autorelease
54 | probe autorelease_pool__push(void *token);
55 | probe autorelease_pool__pop(void *token);
56 |
57 | // Fires when we add a new page to an autorelease pool
58 | probe autorelease_pool__grow(int depth);
59 | };
60 |
--------------------------------------------------------------------------------
/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_associations(id object, bool deallocating);
39 |
40 | __END_DECLS
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/runtime/objc-runtime.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
--------------------------------------------------------------------------------
/runtime/objc-sel-table.s:
--------------------------------------------------------------------------------
1 | #include
2 | #include "objc-vm.h"
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 | lobjc_opt_ptrs:
43 | PTR(.objc_class_name_Protocol)
44 | #else
45 | // new ABI
46 | .globl _OBJC_CLASS_$_Protocol
47 | lobjc_opt_ptrs:
48 | PTR(_OBJC_CLASS_$_Protocol)
49 | #endif
50 |
51 | .no_dead_strip lobjc_opt_ptrs
52 |
--------------------------------------------------------------------------------
/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/objc-test-env.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2022 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-test-env.h"
25 |
26 | #include
27 | #include
28 |
29 | // This is a dummy placeholder, so we can link
30 | char **_objc_test_get_environ(void) {
31 | return NULL;
32 | }
33 |
--------------------------------------------------------------------------------
/runtime/objc-test-env.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2022 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_TEST_ENV_
25 | #define _OBJC_TEST_ENV_
26 |
27 | #ifdef __cplusplus
28 | extern "C" {
29 | #endif
30 |
31 | // Retrieve the environment when using a compiled environment library
32 | char **_objc_test_get_environ(void) __attribute__((weak_import, visibility("default")));
33 |
34 | #ifdef __cplusplus
35 | }
36 | #endif
37 |
38 | #endif // _OBJC_TEST_ENV_
39 |
--------------------------------------------------------------------------------
/runtime/objc-vm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2022 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_VM_H
25 | #define _OBJC_VM_H
26 |
27 | /*
28 | * WARNING DANGER HAZARD BEWARE EEK
29 | *
30 | * Everything in this file is for Apple Internal use only.
31 | * These will change in arbitrary OS updates and in unpredictable ways.
32 | * When your program breaks, you get to keep both pieces.
33 | */
34 |
35 | /*
36 | * objc-vm.h: defines PAGE_SIZE, PAGE_MIN/MAX_SIZE and PAGE_MAX_SHIFT
37 | */
38 |
39 | // N.B. This file must be usable FROM ASSEMBLY SOURCE FILES
40 |
41 | #include
42 |
43 | #if __has_include()
44 | # include
45 |
46 | # define OBJC_VM_MAX_ADDRESS MACH_VM_MAX_ADDRESS
47 | #elif __arm64__
48 | # define PAGE_SIZE 16384
49 | # define PAGE_MIN_SIZE 16384
50 | # define PAGE_MAX_SIZE 16384
51 | # define PAGE_MAX_SHIFT 14
52 | #if TARGET_OS_EXCLAVEKIT
53 | # define OBJC_VM_MAX_ADDRESS 0x0000000ffffffff8ULL
54 | #else
55 | # define OBJC_VM_MAX_ADDRESS 0x00007ffffffffff8ULL
56 | #endif
57 | #else
58 | # error Unknown platform - please define PAGE_SIZE et al.
59 | #endif
60 |
61 | #endif // _OBJC_VM_H
62 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/scripts/time-startup:
--------------------------------------------------------------------------------
1 | #!/usr/sbin/dtrace -qs
2 |
3 | //
4 | // Measure start-up time
5 | //
6 |
7 | dtrace:::BEGIN {
8 | self->start = timestamp;
9 | self->vstart = vtimestamp;
10 | }
11 |
12 | objc$target:NSApplication:-finishLaunching:return {
13 | this->elapsed = timestamp - self->start;
14 | this->on_cpu = vtimestamp - self->vstart;
15 |
16 | printf("\n** STARTUP TIME **\n");
17 | printf("Elapsed time: %d ns\n", this->elapsed);
18 | printf("On CPU: %d ns\n", this->on_cpu);
19 | printf("\n");
20 | }
21 |
--------------------------------------------------------------------------------
/test/00-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/00-defines.c -o 00-defines.exe
7 | END
8 | */
9 |
10 |
11 | #include "test.h"
12 |
13 | int main()
14 | {
15 | succeed(__FILE__);
16 | }
17 |
--------------------------------------------------------------------------------
/test/01-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/01-headers.c -o 01-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/06-ARCLayoutsWithoutWeak.m:
--------------------------------------------------------------------------------
1 | // Same as test ARCLayouts but with MRC __weak support disabled.
2 | /*
3 | TEST_CONFIG MEM=arc OS=!exclavekit
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=\"06-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 06-ARCLayoutsWithoutWeak.exe
11 | END
12 | */
13 |
--------------------------------------------------------------------------------
/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/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/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/arr-weak-error.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 | // TEST_ENV OBJC_DEBUG_WEAK_ERRORS=fatal
3 | // TEST_CRASHES
4 | /*
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: __weak variable at 0x[0-9a-f]+ holds 0x[0-9a-f]+ instead of 0x[0-9a-f]+. This is probably incorrect use of objc_storeWeak\(\) and objc_loadWeak\(\).
7 | objc\[\d+\]: HALTED
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 |
15 | int main()
16 | {
17 | id weakVar = nil;
18 | @autoreleasepool {
19 | id obj = [NSObject new];
20 | objc_storeWeak(&weakVar, obj);
21 | weakVar = [NSObject new];
22 | [obj release];
23 | }
24 |
25 | fail("should have crashed");
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/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 |
42 | #if __x86_64__
43 | // Only request 4kB alignment on Intel. It doesn't support any greater
44 | // alignment anyway, and the linker complains if we ask. rdar://119847439
45 | .align 12
46 | #else
47 | .align 14
48 | #endif
49 |
50 | _main:
51 | // at least 1024 instruction bytes on all architectures
52 | NOP256
53 | NOP256
54 | NOP256
55 | NOP256
56 |
--------------------------------------------------------------------------------
/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 * __ptrauth_objc_isa_pointer isa;
15 | void * __ptrauth_objc_super_pointer superclass;
16 | void *cachePtr;
17 | uintptr_t maskAndOccupied;
18 | struct minimal_class_ro * __ptrauth_objc_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 | ptrauth_strip(localForbidden->ro, ptrauth_key_process_independent_data)->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/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]+\. Set a breakpoint .*
9 | objc\[\d+\]: Invalid autorelease pools are a fatal error
10 | objc\[\d+\]: HALTED
11 | END
12 | */
13 |
14 | #include "test.h"
15 |
16 | int main()
17 | {
18 | void *outer = objc_autoreleasePoolPush();
19 | void *inner = objc_autoreleasePoolPush();
20 | objc_autoreleasePoolPop(outer);
21 | objc_autoreleasePoolPop(inner);
22 |
23 | #if !OLD
24 | fail("should have crashed already with new SDK");
25 | #else
26 | // should only warn once
27 | outer = objc_autoreleasePoolPush();
28 | inner = objc_autoreleasePoolPush();
29 | objc_autoreleasePoolPop(outer);
30 | objc_autoreleasePoolPop(inner);
31 |
32 | succeed(__FILE__);
33 | #endif
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/test/badPoolCompat-ios-simulator.m:
--------------------------------------------------------------------------------
1 | // Run test badPool as if it were built with an old SDK.
2 |
3 | // TEST_CONFIG MEM=mrc OS=iphonesimulator ARCH=x86_64
4 | // TEST_CRASHES
5 | // TEST_CFLAGS -DOLD=1 -Xlinker -platform_version -Xlinker ios-simulator -Xlinker 9.0 -Xlinker 9.0 -mios-simulator-version-min=9.0
6 |
7 | /*
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .*
10 | objc\[\d+\]: Proceeding anyway.*
11 | OK: badPool.m
12 | END
13 | */
14 |
15 | #include "badPool.m"
16 |
--------------------------------------------------------------------------------
/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 ARCH=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_RUN_OUTPUT
9 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .*
10 | objc\[\d+\]: Proceeding anyway.*
11 | OK: badPool.m
12 | END
13 | */
14 |
15 | #include "badPool.m"
16 |
--------------------------------------------------------------------------------
/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_RUN_OUTPUT
9 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .*
10 | objc\[\d+\]: Proceeding anyway.*
11 | OK: badPool.m
12 | END
13 | */
14 |
15 | #include "badPool.m"
16 |
--------------------------------------------------------------------------------
/test/badPoolCompat-tvos-simulator.m:
--------------------------------------------------------------------------------
1 | // Run test badPool as if it were built with an old SDK.
2 |
3 | // TEST_CONFIG MEM=mrc OS=appletvsimulator ARCH=x86_64
4 | // TEST_CRASHES
5 | // TEST_CFLAGS -DOLD=1 -Xlinker -platform_version -Xlinker tvos-simulator -Xlinker 9.0 -Xlinker 9.0 -mtvos-simulator-version-min=9.0
6 |
7 | /*
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .*
10 | objc\[\d+\]: Proceeding anyway.*
11 | OK: badPool.m
12 | END
13 | */
14 |
15 | #include "badPool.m"
16 |
--------------------------------------------------------------------------------
/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 ARCH=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_RUN_OUTPUT
9 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .*
10 | objc\[\d+\]: Proceeding anyway.*
11 | OK: badPool.m
12 | END
13 | */
14 |
15 | #include "badPool.m"
16 |
--------------------------------------------------------------------------------
/test/badPoolCompat-watchos-simulator.m:
--------------------------------------------------------------------------------
1 | // Run test badPool as if it were built with an old SDK.
2 |
3 | // TEST_CONFIG MEM=mrc OS=watchsimulator ARCH=x86_64
4 | // TEST_CRASHES
5 | // TEST_CFLAGS -DOLD=1 -Xlinker -platform_version -Xlinker watchos-simulator -Xlinker 2.0 -Xlinker 2.0 -mwatchos-simulator-version-min=2.0
6 |
7 | /*
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .*
10 | objc\[\d+\]: Proceeding anyway.*
11 | OK: badPool.m
12 | END
13 | */
14 |
15 | #include "badPool.m"
16 |
--------------------------------------------------------------------------------
/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 ARCH=armv7k,arm64_32
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_RUN_OUTPUT
9 | objc\[\d+\]: Invalid or prematurely-freed autorelease pool 0x[0-9a-fA-f]+\. Set a breakpoint .*
10 | objc\[\d+\]: Proceeding anyway.*
11 | OK: badPool.m
12 | END
13 | */
14 |
15 | #include "badPool.m"
16 |
--------------------------------------------------------------------------------
/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_CFLAGS -Wno-nonnull
3 | TEST_CRASHES
4 | TEST_RUN_OUTPUT
5 | objc\[\d+\]: tag index 1 used for two different classes \(was 0x[0-9a-fA-F]+ NSObject, now 0x[0-9a-fA-F]+ TestRoot\)
6 | objc\[\d+\]: HALTED
7 | OR
8 | no tagged pointers
9 | OK: badTagClass.m
10 | END
11 | */
12 |
13 | #include "test.h"
14 | #include "testroot.i"
15 |
16 | #include
17 | #include
18 |
19 | #if OBJC_HAVE_TAGGED_POINTERS
20 |
21 | int main()
22 | {
23 | // re-registration and nil registration allowed
24 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [NSObject class]);
25 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [NSObject class]);
26 | _objc_registerTaggedPointerClass(OBJC_TAG_1, nil);
27 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [NSObject class]);
28 |
29 | // colliding registration disallowed
30 | _objc_registerTaggedPointerClass(OBJC_TAG_1, [TestRoot class]);
31 |
32 | fail(__FILE__);
33 | }
34 |
35 | #else
36 |
37 | int main()
38 | {
39 | // provoke the same nullability warning as the real test
40 | objc_getClass(nil);
41 |
42 | fprintf(stderr, "no tagged pointers\n");
43 | succeed(__FILE__);
44 | }
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/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/bool.c:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -funsigned-char
2 | // TEST_CONFIG LANGUAGE=c,c++,objc,objc++
3 | // (verify -funsigned-char doesn't change the definition of BOOL)
4 |
5 | #include "test.h"
6 | #include
7 |
8 | #if TARGET_OS_OSX
9 | # if __x86_64__
10 | # define RealBool 0
11 | # else
12 | # define RealBool 1
13 | # endif
14 | #elif TARGET_OS_IOS || TARGET_OS_BRIDGE
15 | # if (__arm__ && !__armv7k__) || __i386__
16 | # define RealBool 0
17 | # else
18 | # define RealBool 1
19 | # endif
20 | #else
21 | # define RealBool 1
22 | #endif
23 |
24 | #if __OBJC__ && !defined(__OBJC_BOOL_IS_BOOL)
25 | # error no __OBJC_BOOL_IS_BOOL
26 | #endif
27 |
28 | #if RealBool != OBJC_BOOL_IS_BOOL
29 | # error wrong OBJC_BOOL_IS_BOOL
30 | #endif
31 |
32 | #if RealBool == OBJC_BOOL_IS_CHAR
33 | # error wrong OBJC_BOOL_IS_CHAR
34 | #endif
35 |
36 | int main()
37 | {
38 | const char *expected __unused =
39 | #if RealBool
40 | "B"
41 | #else
42 | "c"
43 | #endif
44 | ;
45 | #if __OBJC__
46 | const char *enc = @encode(BOOL);
47 | testassert(0 == strcmp(enc, expected));
48 | #endif
49 | succeed(__FILE__);
50 | }
51 |
--------------------------------------------------------------------------------
/test/cacheflush-constant.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=!exclavekit
2 | // TEST_CFLAGS -framework Foundation
3 | /*
4 | TEST_RUN_OUTPUT
5 | foo
6 | bar
7 | bar
8 | foo
9 | END
10 | */
11 |
12 | // NOTE: This test won't catch problems when running against a root, so it's of
13 | // limited utility, but it would at least catch things when testing against the
14 | // shared cache.
15 |
16 | #include
17 | #include
18 |
19 | @interface NSBlock: NSObject @end
20 |
21 | // NSBlock is a conveniently accessible superclass that (currently) has a constant cache.
22 | @interface MyBlock: NSBlock
23 | +(void)foo;
24 | +(void)bar;
25 | @end
26 | @implementation MyBlock
27 | +(void)foo {
28 | printf("foo\n");
29 | }
30 | +(void)bar {
31 | printf("bar\n");
32 | }
33 | @end
34 |
35 | int main() {
36 | [MyBlock foo];
37 | [MyBlock bar];
38 |
39 | Method m1 = class_getClassMethod([MyBlock class], @selector(foo));
40 | Method m2 = class_getClassMethod([MyBlock class], @selector(bar));
41 | method_exchangeImplementations(m1, m2);
42 |
43 | [MyBlock foo];
44 | [MyBlock bar];
45 | }
46 |
--------------------------------------------------------------------------------
/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 -install_name $T{DYLIBDIR}/cacheflush0.dylib -o cacheflush0.dylib -dynamiclib
4 | $C{COMPILE} $DIR/cacheflush2.m -x none cacheflush0.dylib -install_name $T{DYLIBDIR}/cacheflush2.dylib -o cacheflush2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/cacheflush3.m -x none cacheflush0.dylib -install_name $T{DYLIBDIR}/cacheflush3.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 | #if !TARGET_OS_EXCLAVEKIT
37 | // Dynamically load a category
38 | dlopen("cacheflush2.dylib", 0);
39 |
40 | // Make sure old cache results are gone
41 | testassert(2 == [TestRoot classMethod]);
42 | testassert(2 == [sup instanceMethod]);
43 |
44 | testassert(2 == [Sub classMethod]);
45 | testassert(2 == [sub instanceMethod]);
46 |
47 | // Dynamically load another category
48 | dlopen("cacheflush3.dylib", 0);
49 |
50 | // Make sure old cache results are gone
51 | testassert(3 == [TestRoot classMethod]);
52 | testassert(3 == [sup instanceMethod]);
53 |
54 | testassert(3 == [Sub classMethod]);
55 | testassert(3 == [sub instanceMethod]);
56 | #endif // !TARGET_OS_EXCLAVEKIT
57 |
58 | // fixme test subclasses
59 |
60 | // fixme test objc_flush_caches(), class_addMethod(), class_addMethods()
61 |
62 | succeed(__FILE__);
63 | }
64 |
--------------------------------------------------------------------------------
/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 | #define __APPLE_API_PRIVATE 1
4 | #include "test.h"
5 | #include
6 | #include
7 | #import
8 |
9 | @interface Foo:NSObject
10 | @end
11 | @implementation Foo
12 | @end
13 |
14 | int main()
15 | {
16 | testassert(gdb_class_getClass([Foo class]) == [Foo class]);
17 | succeed(__FILE__);
18 | }
19 |
--------------------------------------------------------------------------------
/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 | memset(buf, 0, 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/classpair-stress.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | int main()
8 | {
9 | // Allocate a large number of classes and make sure their instances work.
10 | // This is mostly to ensure that the indexed class system on 32-bit works
11 | // correctly for the full range of values, and when we run off the end.
12 |
13 | // The indexed class array is currently 32,768 entries. Each iteration will
14 | // use two (class and metaclass).
15 | int count = 20000;
16 | for (int i = 0; i < count; i++) {
17 | testprintf("Testing iteration %d\n", i);
18 |
19 | char *name;
20 | asprintf(&name, "TestClass-%d", i);
21 |
22 | Class c = objc_allocateClassPair([NSObject class], name, 0);
23 | objc_registerClassPair(c);
24 |
25 | testprintf("%s is at %p\n", name, c);
26 |
27 | free(name);
28 |
29 | RELEASE_VALUE([[c alloc] init]);
30 | }
31 |
32 | succeed(__FILE__);
33 | }
34 |
--------------------------------------------------------------------------------
/test/classpairAddMethod.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #include "testroot.i"
6 | #include
7 |
8 | void fakeIMP() {}
9 | IMP testIMP = (IMP)fakeIMP;
10 |
11 | int main()
12 | {
13 | // Make sure that method_getDescription doesn't return a stale cached
14 | // description when creating and destroying dynamic subclasses
15 | // (rdar://91521212). This is a UaF so it's not completely reliable, but
16 | // empirically it happens reliably after five iterations. Run 100 just to be
17 | // safe.
18 | for (int i = 0; i < 100; i++) {
19 | char *name;
20 | asprintf(&name, "test-%d", i);
21 | SEL sel = sel_getUid(name);
22 | Class c = objc_allocateClassPair([TestRoot class], name, 0);
23 | class_addMethod(c, sel, testIMP, name);
24 | objc_registerClassPair(c);
25 |
26 | Method m = class_getInstanceMethod(c, sel);
27 | struct objc_method_description *desc = method_getDescription(m);
28 | testassert(strcmp(desc->types, name) == 0);
29 | testassertequal(desc->name, sel);
30 |
31 | free(name);
32 | objc_disposeClassPair(c);
33 | }
34 |
35 | succeed(__FILE__);
36 | }
--------------------------------------------------------------------------------
/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 | (void)keyPath;
47 | (void)object;
48 | (void)change;
49 | (void)context;
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_FILTER .*( OS_|inherited).*
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: CUSTOM AWZ: NSObject \(meta\)
14 | OK: customrr-nsobject-awz.exe
15 | END
16 |
17 | */
18 |
19 |
--------------------------------------------------------------------------------
/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_FILTER .*( OS_|inherited).*
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: CUSTOM Core: NSObject \(meta\)
14 | objc\[\d+\]: CUSTOM Core: NSObject
15 | OK: customrr-nsobject-core.exe
16 | OR
17 | objc\[\d+\]: CUSTOM Core: NSObject
18 | objc\[\d+\]: CUSTOM Core: NSObject \(meta\)
19 | OK: customrr-nsobject-core.exe
20 | END
21 |
22 | */
23 |
24 |
--------------------------------------------------------------------------------
/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_RUN_OUTPUT_FILTER .*( OS_|inherited).*
7 |
8 | TEST_BUILD
9 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-none.exe -fno-objc-convert-messages-to-runtime-calls
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | OK: customrr-nsobject-none.exe
14 | END
15 |
16 | */
17 |
18 |
--------------------------------------------------------------------------------
/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_FILTER .*( OS_|inherited).*
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: CUSTOM RR: NSObject
14 | OK: customrr-nsobject-rr.exe
15 | END
16 |
17 | */
18 |
19 |
--------------------------------------------------------------------------------
/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_FILTER .*( OS_|inherited).*
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: CUSTOM AWZ: NSObject \(meta\)
14 | objc\[\d+\]: CUSTOM RR: NSObject
15 | OK: customrr-nsobject-rrawz.exe
16 | OR
17 | objc\[\d+\]: CUSTOM RR: NSObject
18 | objc\[\d+\]: CUSTOM AWZ: NSObject \(meta\)
19 | OK: customrr-nsobject-rrawz.exe
20 | END
21 |
22 | */
23 |
24 |
--------------------------------------------------------------------------------
/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.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
28 |
29 | ERROR=
30 |
31 | extract_defines() {
32 | echo "$INCLUDES" | $1 - -dM -E \
33 | | sed 's/\(#define [_A-Za-z][_A-Za-z0-9]*\).*/\1/g' \
34 | | sort | uniq
35 | }
36 |
37 | get_new_lines() {
38 | diff -u -U 0 $1 $2 | grep -v "^+++" | grep "^+" | cut -c2- || true
39 | }
40 |
41 | run_test() {
42 | extract_defines "$1 $CFLAGS" > base-defines
43 | extract_defines "$1 $CFLAGS $FILES" > objc-defines
44 | get_new_lines base-defines objc-defines > objc-defines-only
45 | if [[ ! -s objc-defines-only ]]; then
46 | echo "ERROR: objc-defines-only is somehow empty."
47 | exit 1
48 | fi
49 | get_new_lines defines.expected objc-defines-only > objc-defines-unexpected
50 | if [[ -s objc-defines-unexpected ]]; then
51 | echo "ERROR: unknown #defines found in headers. If these are expected, add them to test/defines.expected."
52 | echo "$1"
53 | cat objc-defines-unexpected
54 | ERROR=1
55 | fi
56 | rm base-defines objc-defines objc-defines-only objc-defines-unexpected
57 | }
58 |
59 | run_test "$COMPILE_C $CFLAGS"
60 | run_test "$COMPILE_CXX $CFLAGS"
61 | run_test "$COMPILE_M $CFLAGS"
62 | run_test "$COMPILE_MM $CFLAGS"
63 | for STDC in '99' '11' ; do
64 | run_test "$COMPILE_C $CFLAGS -std=c$STDC"
65 | run_test "$COMPILE_M $CFLAGS -std=c$STDC"
66 | done
67 | for STDCXX in '98' '03' '11' '14' '17' ; do
68 | run_test "$COMPILE_CXX $CFLAGS -std=c++$STDCXX"
69 | run_test "$COMPILE_MM $CFLAGS -std=c++$STDCXX"
70 | done
71 |
72 | if [[ $ERROR == 1 ]]; then
73 | echo "Unknown #defines found in headers."
74 | exit 1
75 | fi
76 |
--------------------------------------------------------------------------------
/test/definitions.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc,arc LANGUAGE=c,c++,objc,objc++
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/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_CONFIG OS=!exclavekit
5 | // TEST_ENV OBJC_DEBUG_DUPLICATE_CLASSES=FATAL OBJC_DISABLE_PREOPTIMIZATION=YES
6 | // TEST_CRASHES
7 | /*
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: Class [^\s]+ is implemented in both .+ \(0x[0-9a-f]+\) and .+ \(0x[0-9a-f]+\)\. This may cause spurious casting failures and mysterious crashes\. One of the duplicates must be removed or renamed\.
10 | objc\[\d+\]: HALTED
11 | OR
12 | OK: duplicatedClasses.m
13 | END
14 | */
15 |
16 | #include "test.h"
17 | #include "testroot.i"
18 |
19 | @interface WKWebView : TestRoot @end
20 | @implementation WKWebView @end
21 |
22 | int main()
23 | {
24 | void *dl = dlopen("/System/Library/Frameworks/WebKit.framework/WebKit", RTLD_LAZY);
25 | if (!dl) fail("couldn't open WebKit");
26 | fail("should have crashed already");
27 | }
28 |
--------------------------------------------------------------------------------
/test/duplicatedClasses0.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "testroot.i"
3 |
4 | @interface DuplicatedClass : TestRoot @end
5 | @implementation DuplicatedClass @end
6 |
--------------------------------------------------------------------------------
/test/duplicatedClasses2.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG OS=!exclavekit
3 | TEST_BUILD
4 | $C{COMPILE} $DIR/duplicatedClasses0.m -fvisibility=hidden -DTestRoot=TestRoot2 -install_name $T{DYLIBDIR}/duplicatedClasses0.dylib -o duplicatedClasses0.dylib -dynamiclib
5 | $C{COMPILE} $DIR/duplicatedClasses2.m -o duplicatedClasses2.exe
6 | END
7 | */
8 |
9 | // TEST_ENV OBJC_DEBUG_DUPLICATE_CLASSES=FATAL
10 | // TEST_CRASHES
11 | /*
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: Class DuplicatedClass is implemented in both .+ \(0x[0-9a-f]+\) and .+ \(0x[0-9a-f]+\)\. This may cause spurious casting failures and mysterious crashes\. One of the duplicates must be removed or renamed\.
14 | objc\[\d+\]: HALTED
15 | END
16 | */
17 |
18 | #include "duplicatedClasses0.m"
19 |
20 | int main()
21 | {
22 | void *dl = dlopen("duplicatedClasses0.dylib", RTLD_LAZY);
23 | if (!dl) fail("couldn't open dylib");
24 | fail("should have crashed already");
25 | }
26 |
--------------------------------------------------------------------------------
/test/duplicatedClasses3.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/duplicatedClasses0.m -fvisibility=hidden -DTestRoot=TestRoot2 -install_name $T{DYLIBDIR}/duplicatedClasses0.dylib -o duplicatedClasses0.dylib -dynamiclib
4 | $C{COMPILE} $DIR/duplicatedClasses3.m -x none duplicatedClasses0.dylib -o duplicatedClasses3.exe
5 | END
6 | */
7 |
8 | // TEST_ENV OBJC_DEBUG_DUPLICATE_CLASSES=FATAL
9 | // TEST_CRASHES
10 | /*
11 | TEST_RUN_OUTPUT
12 | objc\[\d+\]: Class DuplicatedClass is implemented in both .+ \(0x[0-9a-f]+\) and .+ \(0x[0-9a-f]+\)\. This may cause spurious casting failures and mysterious crashes\. One of the duplicates must be removed or renamed\.
13 | objc\[\d+\]: HALTED
14 | END
15 | */
16 |
17 | #include "duplicatedClasses0.m"
18 |
19 | int main()
20 | {
21 | fail("should have crashed already");
22 | }
23 |
--------------------------------------------------------------------------------
/test/enumClasses.h:
--------------------------------------------------------------------------------
1 | /* Emacs, this is -*-objc-*- */
2 |
3 | #ifndef ENUMCLASSES_H_
4 | #define ENUMCLASSES_H_
5 |
6 | #include "test.h"
7 |
8 | typedef enum {
9 | UnknownSize = -1,
10 | MinasculeSize,
11 | SmallSize,
12 | MediumSize,
13 | BigSize,
14 | HugeSize,
15 | } creature_size_t;
16 |
17 | typedef enum {
18 | BlackAndOrange,
19 | GrayAndBlack,
20 | Plaid,
21 | } stripe_color_t;
22 |
23 | @protocol Creature
24 | - (const char *)name;
25 | - (creature_size_t)size;
26 | @end
27 |
28 | @protocol Claws
29 | - (void)retract;
30 | - (void)extend;
31 | @end
32 |
33 | @protocol Stripes
34 | - (stripe_color_t)stripeColor;
35 | @end
36 |
37 | // Animal
38 | @interface Animal : TestRoot
39 |
40 | - (const char *)name;
41 | - (creature_size_t)size;
42 |
43 | @end
44 |
45 | @interface Dog : Animal
46 |
47 | - (const char *)name;
48 |
49 | @end
50 |
51 | @interface Cat : Animal
52 |
53 | - (const char *)name;
54 |
55 | @end
56 |
57 | @interface Elephant : Animal
58 |
59 | - (const char *)name;
60 | - (creature_size_t)size;
61 |
62 | @end
63 |
64 | #endif /* ENUMCLASSES_H_ */
65 |
--------------------------------------------------------------------------------
/test/enumClasses0.m:
--------------------------------------------------------------------------------
1 | #include "enumClasses.h"
2 | #include "testroot.i"
3 |
4 | // Animal
5 | @implementation Animal
6 |
7 | - (const char *)name { return "animal"; }
8 | - (creature_size_t)size { return UnknownSize; }
9 |
10 | @end
11 |
12 | // Cat
13 | @implementation Cat
14 |
15 | - (const char *)name { return "cat"; }
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/test/enumClasses1.m:
--------------------------------------------------------------------------------
1 | #include "enumClasses.h"
2 |
3 | // Cats have retractable claws (using a category)
4 | @interface Cat (Category)
5 |
6 | - (void)retract;
7 | - (void)extend;
8 |
9 | @end
10 |
11 | @implementation Cat (Category)
12 |
13 | - (void)retract {
14 | }
15 | - (void)extend {
16 | }
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/test/fakeRealizedClass.m:
--------------------------------------------------------------------------------
1 | /*
2 | Make sure we detect classes with the RW_REALIZED bit set in the binary. rdar://problem/67692760
3 |
4 | (Note that on arm64e, this problem will cause a pointer auth failure.)
5 |
6 | TEST_CONFIG OS=macosx ARCH=!arm64e
7 | TEST_CRASHES
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: realized class 0x[0-9a-fA-F]+ has corrupt data pointer: malloc_size\(0x[0-9a-fA-F]+\) = 0
10 | objc\[\d+\]: HALTED
11 | END
12 | */
13 |
14 | #include "test.h"
15 | #include "class-structures.h"
16 |
17 | #include
18 |
19 | #define RW_REALIZED (1U<<31)
20 |
21 | // This test only runs on macOS, so we won't bother with the conditionals around
22 | // this value. Just use the one value macOS always has.
23 | #define FAST_IS_RW_POINTER 0x8000000000000000UL
24 |
25 | __attribute__((section("__DATA,__objc_const")))
26 | struct ObjCClass_ro FakeSuperclassRO = {
27 | .flags = RW_REALIZED
28 | };
29 |
30 | struct ObjCClass FakeSuperclass = {
31 | &OBJC_METACLASS_$_NSObject,
32 | &OBJC_METACLASS_$_NSObject,
33 | NULL,
34 | 0,
35 | (struct ObjCClass_ro *)((uintptr_t)&FakeSuperclassRO + FAST_IS_RW_POINTER)
36 | };
37 |
38 | __attribute__((section("__DATA,__objc_const")))
39 | struct ObjCClass_ro FakeSubclassRO;
40 |
41 | struct ObjCClass FakeSubclass = {
42 | &FakeSuperclass,
43 | &FakeSuperclass,
44 | NULL,
45 | 0,
46 | &FakeSubclassRO
47 | };
48 |
49 | static struct ObjCClass *class_ptr __attribute__((used)) __attribute((section("__DATA,__objc_nlclslist"))) = &FakeSubclass;
50 |
51 | int main() {}
52 |
--------------------------------------------------------------------------------
/test/fakeRealizedClass2.m:
--------------------------------------------------------------------------------
1 | /*
2 | Variant on fakeRealizedClass which tests a fake class with no superclass rdar://problem/67692760
3 |
4 | (On arm64e, this will cause a pointer auth failure.)
5 |
6 | TEST_CONFIG OS=macosx ARCH=!arm64e
7 | TEST_CRASHES
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: realized class 0x[0-9a-fA-F]+ has corrupt data pointer: malloc_size\(0x[0-9a-fA-F]+\) = 0
10 | objc\[\d+\]: HALTED
11 | END
12 | */
13 |
14 | #include "test.h"
15 |
16 | #include
17 |
18 | #define RW_REALIZED (1U<<31)
19 |
20 | // This test only runs on macOS, so we won't bother with the conditionals around
21 | // this value. Just use the one value macOS always has.
22 | #define FAST_IS_RW_POINTER 0x8000000000000000UL
23 |
24 | struct ObjCClass {
25 | struct ObjCClass * __ptrauth_objc_isa_pointer isa;
26 | struct ObjCClass * __ptrauth_objc_super_pointer superclass;
27 | void *cachePtr;
28 | uintptr_t zero;
29 | uintptr_t data;
30 | };
31 |
32 | struct ObjCClass_ro {
33 | uint32_t flags;
34 | uint32_t instanceStart;
35 | uint32_t instanceSize;
36 | #ifdef __LP64__
37 | uint32_t reserved;
38 | #endif
39 |
40 | union {
41 | const uint8_t * ivarLayout;
42 | struct ObjCClass * nonMetaClass;
43 | };
44 |
45 | const char * name;
46 | struct ObjCMethodList * __ptrauth_objc_method_list_pointer baseMethodList;
47 | struct protocol_list_t * baseProtocols;
48 | const struct ivar_list_t * ivars;
49 |
50 | const uint8_t * weakIvarLayout;
51 | struct property_list_t *baseProperties;
52 | };
53 |
54 | extern struct ObjCClass OBJC_METACLASS_$_NSObject;
55 | extern struct ObjCClass OBJC_CLASS_$_NSObject;
56 |
57 | __attribute__((section("__DATA,__objc_const")))
58 | struct ObjCClass_ro FakeSuperclassRO = {
59 | .flags = RW_REALIZED
60 | };
61 |
62 | struct ObjCClass FakeSuperclass = {
63 | &OBJC_METACLASS_$_NSObject,
64 | NULL,
65 | NULL,
66 | 0,
67 | (uintptr_t)&FakeSuperclassRO + FAST_IS_RW_POINTER
68 | };
69 |
70 | __attribute__((section("__DATA,__objc_const")))
71 | struct ObjCClass_ro FakeSubclassRO;
72 |
73 | struct ObjCClass FakeSubclass = {
74 | &FakeSuperclass,
75 | &FakeSuperclass,
76 | NULL,
77 | 0,
78 | (uintptr_t)&FakeSubclassRO
79 | };
80 |
81 | static struct ObjCClass *class_ptr __attribute__((used)) __attribute((section("__DATA,__objc_nlclslist"))) = &FakeSubclass;
82 |
83 | int main() {}
84 |
--------------------------------------------------------------------------------
/test/faultLeaks.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc, LANGUAGE=objective-c
2 | // TEST_ENV OBJC_DEBUG_SYNC_ERRORS=Fault
3 | /* TEST_RUN_OUTPUT
4 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
5 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
6 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
7 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
8 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
9 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
10 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
11 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
12 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
13 | objc\[\d+\]: objc_sync_exit\(0x[a-fA-F0-9]+\) returned error -1
14 | [\S\s]*0 leaks for 0 total leaked bytes[\S\s]*
15 | OK: faultLeaks.m
16 | END
17 | */
18 |
19 | #include
20 |
21 | #include
22 | #include
23 |
24 | #include "test.h"
25 | #include "testroot.i"
26 |
27 | int main() {
28 | id obj = [TestRoot alloc];
29 |
30 | // objc_sync_exit on an object that isn't locked will provoke a fault from
31 | // OBJC_DEBUG_SYNC_ERRORS=Fault. Do this several times to ensure any leak is
32 | // detected.
33 | objc_sync_exit(obj);
34 | objc_sync_exit(obj);
35 | objc_sync_exit(obj);
36 | objc_sync_exit(obj);
37 | objc_sync_exit(obj);
38 | objc_sync_exit(obj);
39 | objc_sync_exit(obj);
40 | objc_sync_exit(obj);
41 | objc_sync_exit(obj);
42 | objc_sync_exit(obj);
43 |
44 | char *pidstr;
45 | int result = asprintf(&pidstr, "%u", getpid());
46 | testassert(result);
47 |
48 | extern char **environ;
49 | char *argv[] = { "/usr/bin/leaks", pidstr, NULL };
50 | pid_t pid;
51 | result = posix_spawn(&pid, "/usr/bin/leaks", NULL, NULL, argv, environ);
52 | if (result) {
53 | perror("posix_spawn");
54 | exit(1);
55 | }
56 | wait4(pid, NULL, 0, NULL);
57 |
58 | free(pidstr);
59 | [obj release];
60 |
61 | succeed(__FILE__);
62 | }
63 |
--------------------------------------------------------------------------------
/test/fork.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=!exclavekit
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_FILTER .*INITIALIZE: thread.*
9 | TEST_RUN_OUTPUT
10 | objc\[\d+\]: INITIALIZE: disabling \+initialize fork safety enforcement because the app has a __DATA,__objc_fork_ok section
11 | OK: forkInitializeDisabled\.m
12 | END
13 | */
14 |
15 | #include "test.h"
16 |
17 | asm(".section __DATA, __objc_fork_ok\n.long 0\n");
18 |
19 | int main()
20 | {
21 | succeed(__FILE__);
22 | }
23 |
--------------------------------------------------------------------------------
/test/forkInitializeSingleThreaded.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG OS=!exclavekit
3 |
4 | TEST_RUN_OUTPUT
5 | OK: forkInitialize\.m
6 | OK: forkInitialize\.m
7 | END
8 | */
9 | #define SINGLETHREADED 1
10 | #include "forkInitialize.m"
11 |
--------------------------------------------------------------------------------
/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/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/get_task_allow_entitlement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | get-task-allow
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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 |
5 | #include "test.h"
6 | #include "testroot.i"
7 |
8 | @interface Foo: TestRoot @end
9 | @implementation Foo @end
10 | @interface Bar: Foo @end
11 | @implementation Bar @end
12 |
13 | int main(int argc __unused, const char **argv)
14 | {
15 | // Make sure we show up in the list of image names.
16 | unsigned int count;
17 | const char **imageNames = objc_copyImageNames(&count);
18 | testassert(imageNames);
19 | testassertequal(imageNames[count], NULL);
20 |
21 | char myBaseName[MAXPATHLEN];
22 | basename_r(argv[0], myBaseName);
23 | const char *myImageName = NULL;
24 | for (unsigned int i = 0; i < count; i++) {
25 | char imageBaseName[MAXPATHLEN];
26 | basename_r(imageNames[i], imageBaseName);
27 | if (strcmp(imageBaseName, myBaseName) == 0)
28 | myImageName = imageNames[i];
29 | }
30 | testassert(myImageName);
31 | free(imageNames);
32 |
33 | // Make sure our classes show up in the class names.
34 | const char **classNames = objc_copyClassNamesForImage(myImageName, &count);
35 | testassert(classNames);
36 | testassertequal(classNames[count], NULL);
37 |
38 | int sawFoo = 0;
39 | int sawBar = 0;
40 | for (unsigned int i = 0; i < count; i++) {
41 | if (strcmp(classNames[i], "Foo") == 0)
42 | sawFoo++;
43 | if (strcmp(classNames[i], "Bar") == 0)
44 | sawBar++;
45 | }
46 | testassertequal(sawFoo, 1);
47 | testassertequal(sawBar, 1);
48 | free(classNames);
49 |
50 | // Make sure our classes show up in the classes list.
51 | sawFoo = 0;
52 | sawBar = 0;
53 | Class *classes = objc_copyClassesForImage(myImageName, &count);
54 | testassert(classes);
55 | testassertequal(classes[count], NULL);
56 | for (unsigned int i = 0; i < count; i++) {
57 | if (strcmp(class_getName(classes[i]), "Foo") == 0)
58 | sawFoo++;
59 | if (strcmp(class_getName(classes[i]), "Bar") == 0)
60 | sawBar++;
61 | }
62 | testassertequal(sawFoo, 1);
63 | testassertequal(sawBar, 1);
64 | free(classes);
65 |
66 | // Make sure bad names return NULL.
67 | testassertequal(objc_copyClassNamesForImage("aaaaaaaaaaaaaaaaaaa", NULL), NULL);
68 | testassertequal(objc_copyClassesForImage("aaaaaaaaaaaaaaaaaaa", NULL), NULL);
69 |
70 | succeed(__FILE__);
71 | }
72 |
--------------------------------------------------------------------------------
/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 -install_name $T{DYLIBDIR}/imageorder1.dylib -o imageorder1.dylib -dynamiclib
4 | $C{COMPILE} $DIR/imageorder2.m -x none imageorder1.dylib -install_name $T{DYLIBDIR}/imageorder2.dylib -o imageorder2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/imageorder3.m -x none imageorder2.dylib -install_name $T{DYLIBDIR}/imageorder3.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 | test -e $C{TESTLIB} && $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\)' | grep -v 'weak external __objc_test_get_environ \(from libobjc-env\)' | egrep '(weak external| external (___cxa_atexit|___cxa_guard_acquire|___cxa_guard_release))' || true
28 | test -e $C{TESTLIB} && $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_CONFIG MEM=mrc,arc LANGUAGE=c,c++,objc,objc++
3 | TEST_BUILD
4 | $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 -Wno-declaration-after-statement 2>&1 | grep -v 'In file' | grep objc || true
5 | END
6 |
7 | TEST_RUN_OUTPUT
8 | OK: includes.c
9 | END
10 | */
11 |
12 | // Detect warnings inside any header.
13 | // The build command above filters out warnings inside non-objc headers
14 | // (which are noisy with -Weverything).
15 | // -Wno-undef suppresses warnings about `#if __cplusplus` and the like.
16 | // -Wno-old-style-cast is tough to avoid in mixed C/C++ code.
17 | // -Wno-nullability-extension disables a warning about non-portable
18 | // _Nullable etc which we already handle correctly in objc-abi.h.
19 | // -Wno-c++98-compat disables warnings about things that already
20 | // have guards against C++98.
21 | // -Wno-declaration-after-statement disables a warning about mixing declarations
22 | // and code while building for a standard earlier than C99
23 |
24 | #include "includes.c"
25 |
--------------------------------------------------------------------------------
/test/includes-objc2.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc,arc LANGUAGE=c,c++,objc,objc++
2 | // TEST_CFLAGS -D__OBJC2__
3 |
4 | // Verify that all headers can be included in any language, even if
5 | // the client is C code that defined __OBJC2__.
6 |
7 | // This is the definition that Instruments uses in its build.
8 | #if defined(__OBJC2__)
9 | #undef __OBJC2__
10 | #endif
11 | #define __OBJC2__ 1
12 |
13 | #define NAME "includes-objc2.c"
14 | #include "includes.c"
15 |
--------------------------------------------------------------------------------
/test/includes.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc,arc LANGUAGE=c,c++,objc,objc++
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(int argc __unused, char **argv __unused)
45 | {
46 | succeed(NAME);
47 | }
48 |
--------------------------------------------------------------------------------
/test/initialize-autorelease.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 |
5 | #include
6 | #include
7 |
8 | bool didDealloc;
9 |
10 | @interface TestClass: NSObject @end
11 |
12 | @implementation TestClass
13 |
14 | + (void)initialize {
15 | // Verify that autoreleasing an object in +initialize doesn't leak.
16 | id instance = [[TestClass alloc] init];
17 | [instance autorelease];
18 | }
19 |
20 | - (void)dealloc {
21 | didDealloc = true;
22 | [super dealloc];
23 | }
24 |
25 | @end
26 |
27 | int main()
28 | {
29 | @autoreleasepool {
30 | // We need to get to objc_retainAutoreleaseReturnValue without
31 | // triggering initialization, but we do want it to be realized. Looking
32 | // up the class by name avoids initialization.
33 | Class c = objc_getClass("TestClass");
34 |
35 | // Getting the instance size triggers realization if needed.
36 | class_getInstanceSize(c);
37 |
38 | // Make the call.
39 | objc_retainAutoreleaseReturnValue(c);
40 | }
41 | testassert(didDealloc);
42 |
43 | succeed(__FILE__);
44 | }
45 |
--------------------------------------------------------------------------------
/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/lazyClassNameRace.swift:
--------------------------------------------------------------------------------
1 | // TEST_ENV MallocProbGuard=1 MallocProbGuardMemoryBudgetInKB=10000 MallocProbGuardSampleRate=1
2 |
3 | import ObjectiveC
4 | import Dispatch
5 |
6 | // Race to be the first to get the name of a bunch of different generic classes.
7 | // This tests the thread safety of lazy name installation. The MallocProbGuard
8 | // variables help to more deterministically catch use-after-frees from this
9 | // race. rdar://130280263
10 | class C {
11 | func doit(depth: Int, names: inout [String]) {
12 | if depth <= 0 { return }
13 |
14 | DispatchQueue.concurrentPerform(iterations: 2, execute: { _ in
15 | class_getName(object_getClass(self))
16 | })
17 |
18 | names.append(String(cString: class_getName(object_getClass(self))))
19 |
20 | C>().doit(depth: depth - 1, names: &names)
21 | C, U>().doit(depth: depth - 1, names: &names)
22 | }
23 | }
24 |
25 | var names: [String] = []
26 | C().doit(depth: 10, names: &names)
27 |
28 | for name in names {
29 | _ = objc_getClass(name)
30 | }
31 |
32 | print("OK:", #file.split(separator: "/").last!)
33 |
--------------------------------------------------------------------------------
/test/libraryPath.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=!exclavekit
2 | // TEST_CFLAGS -lobjc
3 |
4 | #include "test.h"
5 | #include
6 |
7 | // We use DYLD_LIBRARY_PATH to run the tests against a particular copy of
8 | // libobjc. If this fails somehow (path is wrong, codesigning prevents loading,
9 | // etc.) then the typical result is a silent failure and we end up testing
10 | // /usr/lib/libobjc.A.dylib instead. This test detects when DYLD_LIBRARY_PATH is
11 | // set but libobjc isn't loaded from it.
12 | int main(int argc __unused, char **argv) {
13 | char *containingDirectory = realpath(dirname(argv[0]), NULL);
14 | testprintf("containingDirectory is %s\n", containingDirectory);
15 |
16 | char *dyldLibraryPath = getenv("DYLD_LIBRARY_PATH");
17 | testprintf("DYLD_LIBRARY_PATH is %s\n", dyldLibraryPath);
18 |
19 | if (dyldLibraryPath != NULL && strlen(dyldLibraryPath) > 0) {
20 | int foundMatch = 0;
21 | int foundNonMatch = 0;
22 |
23 | dyldLibraryPath = strdup(dyldLibraryPath);
24 |
25 | Dl_info info;
26 | int success = dladdr((void *)objc_msgSend, &info);
27 | testassert(success);
28 |
29 | testprintf("libobjc is located at %s\n", info.dli_fname);
30 |
31 | char *cursor = dyldLibraryPath;
32 | char *path;
33 | while ((path = strsep(&cursor, ":"))) {
34 | char *resolved = realpath(path, NULL);
35 | testprintf("Resolved %s to %s\n", path, resolved);
36 | if (strcmp(resolved, containingDirectory) == 0) {
37 | testprintf("This is equal to our containing directory, ignoring.\n");
38 | continue;
39 | }
40 | testprintf("Comparing %s and %s\n", resolved, info.dli_fname);
41 | int comparison = strncmp(resolved, info.dli_fname, strlen(resolved));
42 | free(resolved);
43 | if (comparison == 0) {
44 | testprintf("Found a match!\n");
45 | foundMatch = 1;
46 | break;
47 | } else {
48 | foundNonMatch = 1;
49 | }
50 | }
51 |
52 | testprintf("Finished searching, foundMatch=%d foundNonMatch=%d\n", foundMatch, foundNonMatch);
53 | testassert(foundMatch || !foundNonMatch);
54 | }
55 | succeed(__FILE__);
56 | }
57 |
--------------------------------------------------------------------------------
/test/literals.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=!exclavekit LANGUAGE=objc,objc++
2 | // TEST_CFLAGS -framework Foundation
3 |
4 | #import
5 | #import
6 | #import
7 | #import
8 | #import
9 | #include "test.h"
10 |
11 | int main() {
12 | PUSH_POOL {
13 |
14 | #if __has_feature(objc_bool) // placeholder until we get a more precise macro.
15 | NSArray *array = @[ @1, @2, @YES, @NO, @"Hello", @"World" ];
16 | testassert([array count] == 6);
17 | NSDictionary *dict = @{ @"Name" : @"John Q. Public", @"Age" : @42 };
18 | testassert([dict count] == 2);
19 | NSDictionary *numbers = @{ @"π" : @M_PI, @"e" : @M_E };
20 | testassert([[numbers objectForKey:@"π"] doubleValue] == M_PI);
21 | testassert([[numbers objectForKey:@"e"] doubleValue] == M_E);
22 |
23 | BOOL yesBool = YES;
24 | BOOL noBool = NO;
25 | array = @[
26 | @(true),
27 | @(YES),
28 | [NSNumber numberWithBool:YES],
29 | @YES,
30 | @(yesBool),
31 | @((BOOL)YES),
32 |
33 | @(false),
34 | @(NO),
35 | [NSNumber numberWithBool:NO],
36 | @NO,
37 | @(noBool),
38 | @((BOOL)NO),
39 | ];
40 | NSData * jsonData = [NSJSONSerialization dataWithJSONObject:array options:0 error:nil];
41 | NSString * string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
42 | #if __cplusplus
43 | testassert([string isEqualToString:@"[true,true,true,true,true,true,false,false,false,false,false,false]"]);
44 | #else
45 | // C99 @(true) and @(false) evaluate to @(1) and @(0).
46 | testassert([string isEqualToString:@"[1,true,true,true,true,true,0,false,false,false,false,false]"]);
47 | #endif
48 |
49 | #endif
50 |
51 | } POP_POOL;
52 |
53 | succeed(__FILE__);
54 |
55 | return 0;
56 | }
57 |
--------------------------------------------------------------------------------
/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 -install_name $T{DYLIBDIR}/load-order3.dylib -o load-order3.dylib -dynamiclib
4 | $C{COMPILE} $DIR/load-order2.m -install_name $T{DYLIBDIR}/load-order2.dylib -o load-order2.dylib -x none load-order3.dylib -dynamiclib
5 | $C{COMPILE} $DIR/load-order1.m -install_name $T{DYLIBDIR}/load-order1.dylib -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-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_CONFIG OS=!exclavekit
3 | TEST_BUILD
4 | $C{COMPILE} $DIR/load-reentrant.m -o load-reentrant.exe
5 | $C{COMPILE} $DIR/load-reentrant2.m -o libload-reentrant2.dylib -bundle -bundle_loader load-reentrant.exe
6 | END
7 | */
8 |
9 | #include "test.h"
10 | #include
11 |
12 | int state1 = 0;
13 | int *state2_p;
14 |
15 | OBJC_ROOT_CLASS
16 | @interface One @end
17 | @implementation One
18 | +(void)load
19 | {
20 | state1 = 111;
21 |
22 | // Re-entrant +load doesn't get to complete until we do
23 | void *dlh = dlopen("libload-reentrant2.dylib", RTLD_LAZY);
24 | testassert(dlh);
25 | state2_p = (int *)dlsym(dlh, "state2");
26 | testassert(state2_p);
27 | testassert(*state2_p == 0);
28 |
29 | state1 = 1;
30 | }
31 | @end
32 |
33 | int main()
34 | {
35 | testassert(state1 == 1 && state2_p && *state2_p == 2);
36 | succeed(__FILE__);
37 | }
38 |
--------------------------------------------------------------------------------
/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/methodCacheLeaks.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc LANGUAGE=objective-c ARCH=!arm64e,!arm64
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 OS=!exclavekit
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/msgSend-performance-macos.m:
--------------------------------------------------------------------------------
1 | // macOS builds of this test require -loah, which is not valid for other OSes.
2 | // This test provides separate cflags for msgSend-performance.m when
3 | // targeting macOS.
4 | // TEST_CONFIG OS=macosx
5 | // TEST_CFLAGS -loah
6 |
7 | const char *FileName = __FILE__;
8 | #define TEST_NAME FileName
9 | #include "msgSend-performance.m"
--------------------------------------------------------------------------------
/test/nilAPIArgs.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CFLAGS -Wno-nonnull
3 | */
4 |
5 | #include "test.h"
6 |
7 | #import
8 |
9 | int main() {
10 | // ensure various bits of API don't crash when tossed nil parameters
11 | class_conformsToProtocol(nil, nil);
12 | method_setImplementation(nil, NULL);
13 |
14 | succeed(__FILE__);
15 | }
16 |
--------------------------------------------------------------------------------
/test/nopool.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc OS=!exclavekit
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 |
6 | @implementation TestRoot (Loader)
7 | +(void)load
8 | {
9 | [[TestRoot new] autorelease];
10 | testassertequal((int)TestRootAutorelease, 1);
11 | testassertequal((int)TestRootDealloc, 0);
12 | }
13 | @end
14 |
15 | int main()
16 | {
17 | // +load's autoreleased object should have deallocated
18 | testassertequal((int)TestRootDealloc, 1);
19 |
20 | [[TestRoot new] autorelease];
21 | testassertequal((int)TestRootAutorelease, 2);
22 |
23 |
24 | objc_autoreleasePoolPop(objc_autoreleasePoolPush());
25 | [[TestRoot new] autorelease];
26 | testassertequal((int)TestRootAutorelease, 3);
27 |
28 |
29 | testonthread(^{
30 | [[TestRoot new] autorelease];
31 | testassertequal((int)TestRootAutorelease, 4);
32 | testassertequal((int)TestRootDealloc, 1);
33 | });
34 | // thread's autoreleased object should have deallocated
35 | testassertequal((int)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 | testassertequal((int)TestRootAutorelease, 5);
44 | testassertequal((int)TestRootDealloc, 2);
45 | });
46 | testassert(TestRootDealloc == 3
47 | );
48 | succeed(__FILE__);
49 | }
50 |
--------------------------------------------------------------------------------
/test/nscdtors.mm:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=!exclavekit
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_CONFIG OS=!exclavekit MEM=mrc,arc LANGUAGE=objc,objc++
4 | TEST_CFLAGS -fobjc-arc-exceptions -framework Foundation
5 | */
6 |
7 | #define USE_FOUNDATION 1
8 | #include "exc.m"
9 |
--------------------------------------------------------------------------------
/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 | @interface TestSELs : NSObject {
15 | SEL sel1, sel2, sel3;
16 | }
17 | @end
18 | @implementation TestSELs
19 |
20 | - (id)init {
21 | sel1 = @selector(sel1);
22 | sel2 = @selector(sel2);
23 | sel3 = @selector(sel3);
24 | return self;
25 | }
26 |
27 | - (void)compareWith: (TestSELs *)other {
28 | testassert(sel1 == other->sel1);
29 | testassert(sel2 == other->sel2);
30 | testassert(sel3 == other->sel3);
31 | }
32 |
33 | @end
34 |
35 | int main()
36 | {
37 | Test *o0 = [Test new];
38 | [o0 retain];
39 | Test *o1 = class_createInstance([Test class], 32);
40 | [o1 retain];
41 | id o2 = object_copy(o0, 0);
42 | id o3 = object_copy(o1, 0);
43 | id o4 = object_copy(o1, 32);
44 |
45 | testassert(malloc_size(o0) == 32);
46 | testassert(malloc_size(o1) == 64);
47 | testassert(malloc_size(o2) == 32);
48 | testassert(malloc_size(o3) == 32);
49 | testassert(malloc_size(o4) == 64);
50 |
51 | testassert([o0 retainCount] == 2);
52 | testassert([o1 retainCount] == 2);
53 | testassert([o2 retainCount] == 1);
54 | testassert([o3 retainCount] == 1);
55 | testassert([o4 retainCount] == 1);
56 |
57 | TestSELs *sels = [TestSELs new];
58 | TestSELs *selsCopy = object_copy(sels, 0);
59 | [sels compareWith: selsCopy];
60 |
61 | succeed(__FILE__);
62 | }
63 |
--------------------------------------------------------------------------------
/test/osVersion.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=!exclavekit
2 | // TEST_CFLAGS -framework Foundation
3 |
4 | #include "test.h"
5 | #include "mach-o/dyld_priv.h"
6 | #include
7 |
8 | extern uintptr_t objc_debug_realized_class_generation_count;
9 |
10 | // Make sure we're testing on the same OS version that libobjc was built for.
11 | int main(int argc __unused, char **argv __unused) {
12 | const struct mach_header *libobjcHeader = dyld_image_header_containing_address(&objc_debug_realized_class_generation_count);
13 | // dyld_get_min_os_version tries to normalize to iOS-aligned numbers, which
14 | // is not what we want. dyld_get_image_versions gives us the raw info we
15 | // want.
16 | __block unsigned libobjcVersion = -1;
17 | dyld_get_image_versions(libobjcHeader, ^(dyld_platform_t platform, uint32_t sdk_version __unused, uint32_t min_version) {
18 | if (platform == dyld_get_active_platform()) {
19 | libobjcVersion = min_version;
20 | }
21 | });
22 | unsigned libobjcMajor = libobjcVersion >> 16;
23 | unsigned libobjcMinor = (libobjcVersion >> 8) & 0xFF;
24 | testprintf("libobjc minos is %u.%u\n", libobjcMajor, libobjcMinor);
25 |
26 | NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
27 | testprintf("OS version is %u.%u\n", (unsigned)osVersion.majorVersion, (unsigned)osVersion.minorVersion);
28 | testassertequal(libobjcMajor, osVersion.majorVersion);
29 | testassertequal(libobjcMinor, osVersion.minorVersion);
30 |
31 | succeed(__FILE__);
32 | }
33 |
--------------------------------------------------------------------------------
/test/partiallyRealizedClass.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | #include
3 | #include "test.h"
4 |
5 | @interface AccessStatic: NSObject @end
6 | @implementation AccessStatic @end
7 |
8 | // EXTERN_C id objc_retainAutoreleaseReturnValue(id);
9 | // EXTERN_C id objc_alloc(id);
10 |
11 | // Verify that objc_retainAutoreleaseReturnValue on an unrealized class doesn't
12 | // put the class into a half-baked state where the metaclass is realized but the
13 | // class is not. rdar://101151980
14 | int main() {
15 | extern char OBJC_CLASS_$_AccessStatic;
16 | id st = (__bridge id)(void *)&OBJC_CLASS_$_AccessStatic;
17 |
18 | objc_retainAutoreleaseReturnValue(st);
19 | objc_alloc(st);
20 |
21 | succeed(__FILE__);
22 | }
23 |
--------------------------------------------------------------------------------
/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/ptrauth.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG ARCH=arm64e
3 | TEST_BUILD
4 | $C{COMPILE} $DIR/ptrauth.m -Wno-deprecated-objc-isa-usage -Wno-deprecated-declarations -framework Foundation -o ptrauth.exe
5 | END
6 | TEST_RUN_OUTPUT
7 | doSomething
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 | #include
15 |
16 | #include
17 |
18 | int count = 0;
19 |
20 | @interface ParentClass : NSObject
21 |
22 | - (void)doSomething;
23 |
24 | @end
25 |
26 | @implementation ParentClass
27 |
28 | - (void)doSomething
29 | {
30 | if (++count == 1) {
31 | printf("doSomething\n");
32 | fflush(stdout);
33 | }
34 | }
35 |
36 | @end
37 |
38 | int main()
39 | {
40 | for (int n = 0; n < 128; ++n) {
41 | char name[32];
42 | snprintf(name, sizeof(name), "PtrAuthTest%d", n);
43 |
44 | Class testClass = objc_allocateClassPair([ParentClass class], name, 0);
45 |
46 | // This should work, because the isa pointer will be signed
47 | id obj = [[testClass alloc] init];
48 | [obj doSomething];
49 |
50 | // Hacking the isa pointer to an unsigned value should cause a crash
51 | ((__bridge struct objc_object *)obj)->isa = testClass;
52 | [obj doSomething];
53 | }
54 |
55 | fail("should have crashed when attempting to invoke -doSomething");
56 | }
57 |
--------------------------------------------------------------------------------
/test/rawisa.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG
3 | TEST_CFLAGS -Xlinker -sectcreate -Xlinker __DATA -Xlinker __objc_rawisa -Xlinker /dev/null
4 | TEST_ENV OBJC_PRINT_RAW_ISA=YES
5 |
6 | TEST_RUN_OUTPUT
7 | objc\[\d+\]: RAW ISA: disabling non-pointer isa because the app has a __DATA,__objc_rawisa section
8 | (.* RAW ISA: .*\n)*
9 | OK: rawisa.m(\n.* RAW ISA: .*)*
10 | OR
11 | (.* RAW ISA: .*\n)*
12 | no __DATA,__rawisa support
13 | OK: rawisa.m(\n.* RAW ISA: .*)*
14 | END
15 |
16 | "RAW ISA" is allowed after "OK" because of static destructors
17 | that provoke class realization.
18 | */
19 |
20 | #include "test.h"
21 |
22 | int main()
23 | {
24 | fprintf(stderr, "\n");
25 | #if ! (SUPPORT_NONPOINTER_ISA && TARGET_OS_OSX)
26 | // only 64-bit Mac supports this
27 | fprintf(stderr, "no __DATA,__rawisa support\n");
28 | #endif
29 | succeed(__FILE__);
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/test/readClassPairIvarFixup.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 | /*
3 | TEST_RUN_OUTPUT
4 | objc\[\d+\]: Class Sub1 is implemented in both.*
5 | objc\[\d+\]: Class SubSub is implemented in both.*
6 | OK: readClassPairIvarFixup.m
7 | END
8 | */
9 |
10 | #include "test.h"
11 | #include
12 |
13 | @interface Bigger: NSObject {
14 | id a, b, c, d;
15 | }
16 | @end
17 | @implementation Bigger
18 | @end
19 |
20 | @interface Sub1: NSObject {
21 | id x;
22 | }
23 | @end
24 | @implementation Sub1 @end
25 |
26 | @interface Sub2: NSObject {
27 | id x;
28 | }
29 | @end
30 | @implementation Sub2 @end
31 |
32 | @interface SubSub: Sub2 {
33 | id y;
34 | }
35 | @end
36 | @implementation SubSub @end
37 |
38 | int main() {
39 | objc_image_info info = {};
40 |
41 | extern char OBJC_CLASS_$_Sub1;
42 | Class sub1Ptr = (Class)&OBJC_CLASS_$_Sub1;
43 |
44 | // Make sure objc_readClassPair slides our ivars when needed.
45 | // Reading a class that's statically known to the runtime will emit a
46 | // duplicate class warning, but that's OK for our testing.
47 | class_setSuperclass(sub1Ptr, [Bigger class]);
48 | objc_readClassPair(sub1Ptr, &info);
49 |
50 | unsigned count1;
51 | Ivar *ivars1 = class_copyIvarList(sub1Ptr, &count1);
52 | testassertequal(count1, 1);
53 | testassert(ivars1);
54 | testassertequal(ivar_getOffset(ivars1[0]), 5 * sizeof(id));
55 |
56 |
57 | // And make sure it slides our ivars even when there's another unrealized
58 | // class in between.
59 | extern char OBJC_CLASS_$_Sub2;
60 | Class sub2Ptr = (Class)&OBJC_CLASS_$_Sub2;
61 |
62 | extern char OBJC_CLASS_$_SubSub;
63 | Class subSubPtr = (Class)&OBJC_CLASS_$_SubSub;
64 |
65 | class_setSuperclass(sub2Ptr, [Bigger class]);
66 | objc_readClassPair(subSubPtr, &info);
67 |
68 | unsigned count2;
69 | Ivar *ivars2 = class_copyIvarList(subSubPtr, &count2);
70 | testassertequal(count2, 1);
71 | testassert(ivars2);
72 | testassertequal(ivar_getOffset(ivars2[0]), 6 * sizeof(id));
73 |
74 | succeed(__FILE__);
75 | }
76 |
--------------------------------------------------------------------------------
/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 | Class c;
16 |
17 | #if !TARGET_OS_EXCLAVEKIT
18 | void *handle = dlopen("/System/Library/Frameworks/Foundation.framework/Foundation", RTLD_LAZY);
19 | testassert(handle);
20 | c = objc_getClass("NSFileManager");
21 | testassert(c);
22 | testassert(objc_debug_realized_class_generation_count > prev);
23 | #endif
24 |
25 | prev = objc_debug_realized_class_generation_count;
26 | c = objc_allocateClassPair([TestRoot class], "Dynamic", 0);
27 | testassert(objc_debug_realized_class_generation_count > prev);
28 | prev = objc_debug_realized_class_generation_count;
29 | objc_registerClassPair(c);
30 | testassert(objc_debug_realized_class_generation_count == prev);
31 |
32 | succeed(__FILE__);
33 | }
34 |
--------------------------------------------------------------------------------
/test/release-race.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc LANGUAGE=objective-c
2 |
3 | #import
4 | #import
5 | #import "test.h"
6 |
7 | @interface MyEncoder : NSObject
8 | {
9 | int x;
10 | }
11 | @end
12 |
13 | @implementation MyEncoder
14 |
15 | - (id)init
16 | {
17 | x = 1;
18 | return self;
19 | }
20 |
21 | - (void)close
22 | {
23 | x = 2;
24 | [self release];
25 | }
26 |
27 | - (void)dealloc
28 | {
29 | // Make sure that release has the appropriate barriers so that we're
30 | // guaranteed to see the x=2 above.
31 | testassertequal(x, 2);
32 | [super dealloc];
33 | }
34 | @end
35 |
36 | int main() {
37 | // The 1 thread worker pool on simulators makes this slow and pointless.
38 | #if !TARGET_OS_SIMULATOR
39 | for (unsigned long long i = 0; i < 100000000ULL; i++) {
40 | if (i % 100000 == 0)
41 | testprintf("%llu\n", i);
42 |
43 | MyEncoder *enc = [MyEncoder new];
44 | [enc retain]; // For the first dispatch
45 | [enc retain]; // For the second one
46 | MyEncoder __unsafe_unretained *enc_weak = enc;
47 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
48 | [enc_weak close];
49 | });
50 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
51 | [enc_weak release];
52 | });
53 | [enc release]; // Drop top level reference
54 | }
55 | #endif
56 | succeed(__FILE__);
57 | }
58 |
--------------------------------------------------------------------------------
/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/restartableRangesSynchronizeStress2.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=arc LANGUAGE=objective-c OS=!exclavekit
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/rootMissingCategoryClass.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_RUN_OUTPUT
3 | objc\[[0-9]+\]: Class of category TestCategory at 0x[a-fA-f0-9]+ in .*rootMissingCategoryClass.exe is set to 0xbad4007, indicating it is missing from an installed root
4 | END
5 | */
6 |
7 | #include "class-structures.h"
8 | #include "test.h"
9 |
10 | #include
11 |
12 | #define BAD_ROOT_ADDRESS 0xbad4007
13 |
14 | static struct ObjCCategory testCategory = {
15 | "TestCategory",
16 | (struct ObjCClass *)BAD_ROOT_ADDRESS
17 | };
18 |
19 | static struct ObjCCategory *testCategoryListEntry __attribute__((used)) __attribute__((section("__DATA, __objc_catlist"))) = &testCategory;
20 |
21 |
22 | int main() {
23 | fail("This test is supposed to crash before main()");
24 | }
25 |
--------------------------------------------------------------------------------
/test/rootMissingSuperclass.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_RUN_OUTPUT
3 | objc\[[0-9]+\]: Superclass of TestClass at 0x[a-fA-f0-9]+ in .*rootMissingSuperclass.exe is set to 0x[0-9a-fA-F]*bad4007, indicating it is missing from an installed root
4 | END
5 | */
6 |
7 | #include "class-structures.h"
8 | #include "test.h"
9 |
10 | #include
11 |
12 | #if __arm64e__
13 | // dyld signs the 0xbad4007 sentinel. It's hard to get it to sign it for us
14 | // in a test, but the runtime should just strip the signature anyway, so we'll
15 | // fake it by manually setting a signature bit.
16 | #define BAD_ROOT_ADDRESS 0x004000000bad4007
17 | #else
18 | #define BAD_ROOT_ADDRESS 0xbad4007
19 | #endif
20 |
21 | extern struct ObjCClass OBJC_METACLASS_$_NSObject;
22 | extern struct ObjCClass OBJC_CLASS_$_NSObject;
23 |
24 | static struct ObjCClass_ro TestClassMeta_ro __attribute__((section("__DATA,__objc_const"))) = {
25 | .flags = RO_META,
26 | .instanceStart = 40,
27 | .instanceSize = 40,
28 | };
29 |
30 | static struct ObjCClass TestClassMeta __attribute__((section("__DATA, __objc_data"))) = {
31 | .isa = &OBJC_METACLASS_$_NSObject,
32 | .superclass = &OBJC_METACLASS_$_NSObject,
33 | .cachePtr = &_objc_empty_cache,
34 | .data = &TestClassMeta_ro,
35 | };
36 |
37 | static struct ObjCClass_ro TestClass_ro __attribute__((section("__DATA,__objc_const"))) = {
38 | .instanceStart = sizeof(void *),
39 | .instanceSize = sizeof(void *),
40 | .name = "TestClass",
41 | };
42 |
43 | static struct ObjCClass TestClass __attribute__((section("__DATA, __objc_data"))) = {
44 | .isa = &TestClassMeta,
45 | .superclass = (struct ObjCClass *)BAD_ROOT_ADDRESS,
46 | .cachePtr = &_objc_empty_cache,
47 | .data = &TestClass_ro,
48 | };
49 |
50 | static struct ObjCClass *testClassListEntry __attribute__((used)) __attribute__((section("__DATA, __objc_classlist"))) = &TestClass;
51 |
52 | int main() {
53 | fail("This test is supposed to crash before main()");
54 | }
55 |
--------------------------------------------------------------------------------
/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 OBJC_DEBUG_POOL_DEPTH=-1
4 | // TEST_CFLAGS -framework Foundation
5 | // TEST_CONFIG MEM=mrc OS=!exclavekit
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 OS=!exclavekit
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 OS=!exclavekit
3 |
4 | #define FOUNDATION 1
5 | #define NAME "rr-nsautorelease"
6 |
7 | #include "rr-autorelease2.m"
8 |
--------------------------------------------------------------------------------
/test/rr-sidetable.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=!exclavekit MEM=mrc ARCH=x86_64
2 | // TEST_CFLAGS -framework Foundation
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_CFLAGS -Wno-nonnull
3 | */
4 |
5 | #include "test.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | int main()
12 | {
13 | // Make sure @selector values are correctly fixed up
14 | testassert(@selector(foo) == sel_registerName("foo"));
15 |
16 | // sel_getName recognizes the zero SEL
17 | testassert(0 == strcmp("", sel_getName(0)));
18 |
19 | // sel_lookUpByName returns NULL for NULL string
20 | testassert(NULL == sel_lookUpByName(NULL));
21 |
22 | // sel_lookUpByName returns NULL for unregistered and matches later registered selector
23 | {
24 | SEL sel;
25 | testassert(NULL == sel_lookUpByName("__testSelectorLookUp:"));
26 | testassert(NULL != (sel = sel_registerName("__testSelectorLookUp:")));
27 | testassert(sel == sel_lookUpByName("__testSelectorLookUp:"));
28 | }
29 |
30 | // sel_lookUpByName matches @selector value
31 | testassert(@selector(foo2) == sel_lookUpByName("foo2"));
32 |
33 | succeed(__FILE__);
34 | }
35 |
--------------------------------------------------------------------------------
/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 | // Intel simulator doesn't support this method.
28 | #if !TARGET_OS_SIMULATOR || !__x86_64__
29 | id obj = [TestRoot new];
30 | id value = [TestRoot new];
31 | const void *key = "key";
32 | objc_setAssociatedObject(obj, key, value, OBJC_ASSOCIATION_RETAIN);
33 | testassert(hasAssociations == true);
34 |
35 | id out = objc_getAssociatedObject(obj, key);
36 | testassert(out == value);
37 |
38 | hasAssociations = false;
39 | key = "key2";
40 | objc_setAssociatedObject(obj, key, value, OBJC_ASSOCIATION_RETAIN);
41 | testassert(hasAssociations == false); //only called once
42 |
43 |
44 | out = objc_getAssociatedObject(obj, key);
45 | testassert(out == value);
46 | #endif
47 |
48 | succeed(__FILE__);
49 | }
50 |
--------------------------------------------------------------------------------
/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/swift-allocateClassPair.swift:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | import Darwin
4 | import ObjectiveC
5 |
6 | var didFail = false
7 |
8 | func fail(_ msg: String) {
9 | print("BAD: \(msg)")
10 | didFail = true
11 | }
12 |
13 | func basePointer(class cls: AnyClass) -> UnsafeRawPointer {
14 | let ptr = unsafeBitCast(cls, to: UnsafeRawPointer.self)
15 |
16 | // The classAddressOffset comes after the ObjC class structure (5 pointers),
17 | // then after 4 uint32_t's and 2 uint16_t's.
18 | let classAddressOffsetOffset =
19 | MemoryLayout.size * 5
20 | + MemoryLayout.size * 4
21 | + MemoryLayout.size * 2;
22 | let classAddressOffset = ptr.load(fromByteOffset: classAddressOffsetOffset, as: UInt32.self)
23 | return ptr - Int(classAddressOffset)
24 | }
25 |
26 | class SwiftClass {}
27 |
28 | // Track how many times malloc_zone_from_ptr returned something for a disposed
29 | // class. This could happen if something else allocated something new in that
30 | // location, but that should not happen 100 times in a row, so we'll tolerate
31 | // false positives but not 100% false positives.
32 | var disposedZoneCount = 0
33 | let iterations = 100
34 | for _ in 0.. {}
13 |
14 | // Ensure that a Swift generic metaclass has properly signed isa/superclass
15 | // pointers. Work with raw pointers to avoid retain/release on the class
16 | // objects, which Swift ARC likes to do.
17 | let genericRaw = unsafeBitCast(Generic.self, to: UnsafeRawPointer.self)
18 |
19 | let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
20 | typealias classToClassFn = @convention(c) (UnsafeRawPointer?) -> UnsafeRawPointer?
21 |
22 | let object_getClassRaw = dlsym(RTLD_DEFAULT, "object_getClass")
23 | let object_getClass = unsafeBitCast(object_getClassRaw, to: classToClassFn.self)
24 |
25 | let class_getSuperClassRaw = dlsym(RTLD_DEFAULT, "class_getSuperclass")
26 | let class_getSuperClass = unsafeBitCast(class_getSuperClassRaw, to: classToClassFn.self)
27 |
28 | // Check for nil, but we're really checking for ptrauth failures in the call.
29 |
30 | if object_getClass(object_getClass(genericRaw)) == nil {
31 | fail("metaclass of metaclass is nil")
32 | }
33 |
34 | if class_getSuperClass(object_getClass(genericRaw)) == nil {
35 | fail("superclass of metaclass is nil")
36 | }
37 |
38 | if !didFail {
39 | print("OK:", #file.split(separator: "/").last!)
40 | }
41 |
--------------------------------------------------------------------------------
/test/swiftMetadataInitializer.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include "swift-class-def.m"
5 | #include
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 | static int SubInits = 0;
21 | Class initSub(Class cls, void *arg)
22 | {
23 | testprintf("initSub callback\n");
24 |
25 | testassert(SubInits == 0);
26 | SubInits++;
27 | testassert(arg == nil);
28 | testassert(0 == strcmp(class_getName(cls), "SwiftSub"));
29 | testassert(cls == RawSwiftSub);
30 | testassert(!isRealized(RawSwiftSuper));
31 | testassert(!isRealized(RawSwiftSub));
32 |
33 | testprintf("initSub beginning _objc_realizeClassFromSwift\n");
34 | _objc_realizeClassFromSwift(cls, cls);
35 | testprintf("initSub finished _objc_realizeClassFromSwift\n");
36 |
37 | testassert(isRealized(RawSwiftSuper));
38 | testassert(isRealized(RawSwiftSub));
39 |
40 | return cls;
41 | }
42 |
43 |
44 | int main()
45 | {
46 | testassert(SubInits == 0);
47 | testprintf("calling [SwiftSub class]\n");
48 | [SwiftSub class];
49 | testprintf("finished [SwiftSub class]\n");
50 | testassert(SubInits == 1);
51 | [SwiftSuper class];
52 | succeed(__FILE__);
53 | }
54 |
--------------------------------------------------------------------------------
/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/swiftobject-no-custom-core.mm:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 |
3 | #include "test.h"
4 | #include
5 |
6 | int CalledHackClass = 0;
7 |
8 | id HackClass(id self, SEL _cmd __unused)
9 | {
10 | CalledHackClass++;
11 | return self;
12 | }
13 |
14 | int main(int argc __unused, char **argv __unused)
15 | {
16 | // Since Foundation now includes the Swift overlay, we can count on
17 | // SwiftObject being loaded when Foundation is loaded.
18 | Class SwiftObject = objc_getClass("_TtCs12_SwiftObject");
19 | testassert(SwiftObject);
20 |
21 | // Replace +class using the RawUnsafe call so we don't look like an
22 | // override.
23 | Method m = class_getClassMethod(SwiftObject, @selector(class));
24 | _method_setImplementationRawUnsafe(m, (IMP)HackClass);
25 |
26 | _objc_flush_caches(SwiftObject);
27 |
28 | // Verify the hack worked.
29 | IMP imp = class_getMethodImplementation(object_getClass(SwiftObject), @selector(class));
30 | testassertequal(imp, (IMP)HackClass);
31 |
32 | // Call +class using the optimized entrypoint. This should not call our
33 | // override.
34 | Class result = objc_opt_class(SwiftObject);
35 | testassert(result == SwiftObject);
36 | testassertequal(CalledHackClass, 0);
37 |
38 | succeed(__FILE__);
39 | }
--------------------------------------------------------------------------------
/test/sync-error-checking.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG MEM=mrc
3 | TEST_ENV OBJC_DEBUG_SYNC_ERRORS=1
4 |
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: objc_sync_exit\(0x1\) returned error -1
7 | OK: sync-error-checking.m
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 |
15 | int main()
16 | {
17 | // It's currently impossible for objc_sync_enter to return an error, so we
18 | // only test objc_sync_exit.
19 | objc_sync_exit((id)1);
20 | succeed(__FILE__);
21 | }
22 |
--------------------------------------------------------------------------------
/test/taggedPointersDisabled.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CFLAGS -Wno-nonnull
3 | TEST_ENV OBJC_DISABLE_TAGGED_POINTERS=YES
4 | TEST_CRASHES
5 |
6 | TEST_RUN_OUTPUT
7 | objc\[\d+\]: tagged pointers are disabled
8 | objc\[\d+\]: HALTED
9 | OR
10 | OK: taggedPointersDisabled.m
11 | END
12 | */
13 |
14 | #include "test.h"
15 | #include
16 |
17 | #if !OBJC_HAVE_TAGGED_POINTERS
18 |
19 | int main()
20 | {
21 | // provoke the same nullability warning as the real test
22 | objc_getClass(nil);
23 |
24 | succeed(__FILE__);
25 | }
26 |
27 | #else
28 |
29 | int main()
30 | {
31 | testassert(!_objc_taggedPointersEnabled());
32 | _objc_registerTaggedPointerClass((objc_tag_index_t)0, nil);
33 | fail("should have crashed in _objc_registerTaggedPointerClass()");
34 | }
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/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/test-simulator.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -euxo pipefail
4 |
5 | pushd "$(dirname $0)/test-simulator"
6 | swift build -c release
7 | BIN_PATH="$(swift build -c release --show-bin-path)"
8 |
9 | popd
10 | exec "$BIN_PATH/test-simulator" "$@"
11 |
--------------------------------------------------------------------------------
/test/test-simulator/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.7
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "test-simulator",
8 | dependencies: [
9 | .package(
10 | url: "https://github.com/apple/swift-argument-parser",
11 | from: "1.1.4"
12 | ),
13 | ],
14 | targets: [
15 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
16 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
17 | .executableTarget(
18 | name: "test-simulator",
19 | dependencies: [
20 | .product(name: "ArgumentParser", package: "swift-argument-parser"),
21 | ]),
22 | ]
23 | )
24 |
--------------------------------------------------------------------------------
/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/unexpectedBuildOutput.mm:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=arc
2 | // TEST_CFLAGS -framework Foundation
3 |
4 | #include "test.h"
5 | #include
6 |
7 | int main()
8 | {
9 | NSString *unexpectedBuildOutputFile = @"../../unexpected-build-output";
10 | if ([[NSFileManager defaultManager] fileExistsAtPath: unexpectedBuildOutputFile]) {
11 | NSData *data = [NSData dataWithContentsOfFile: unexpectedBuildOutputFile];
12 | if (!data)
13 | data = [@"" dataUsingEncoding: NSUTF8StringEncoding];
14 |
15 | [[NSFileHandle fileHandleWithStandardOutput] writeData: data];
16 |
17 | fail(__FILE__);
18 | } else {
19 | succeed(__FILE__);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/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 | __attribute__((weak_import))
29 | @interface ClassThatIsWeakImportAndMissing : TestRoot @end
30 |
31 | @interface SubclassOfMissingWeakImport : ClassThatIsWeakImportAndMissing @end
32 | @implementation SubclassOfMissingWeakImport
33 | -(void)unload2_category_method { }
34 | @end
35 |
36 | @interface ClassThatIsWeakImportAndMissing (Category) @end
37 | @implementation ClassThatIsWeakImportAndMissing (Category)
38 | -(void)unload2_category_method { }
39 | @end
40 |
--------------------------------------------------------------------------------
/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/unload5.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | __attribute__((weak_import))
4 | @interface ClassThatIsWeakImportAndMissing : NSObject @end
5 | @implementation ClassThatIsWeakImportAndMissing @end
6 |
--------------------------------------------------------------------------------
/test/unwind.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | // TEST_ENV OBJC_DEBUG_POOL_DEPTH=-1
3 |
4 | #include "test.h"
5 | #include
6 | #include
7 |
8 | static int state;
9 |
10 | @interface Foo : NSObject @end
11 | @interface Bar : NSObject @end
12 |
13 | @interface Foo (Unimplemented)
14 | +(void)method;
15 | @end
16 |
17 | @implementation Bar @end
18 |
19 | @implementation Foo
20 |
21 | -(void)check { state++; }
22 | +(void)check { testassert(!"caught class object, not instance"); }
23 |
24 | static id exc;
25 |
26 | static void handler(id unused, void *ctx) __attribute__((used));
27 | static void handler(id unused __unused, void *ctx __unused)
28 | {
29 | testassert(state == 3); state++;
30 | }
31 |
32 | +(BOOL) resolveClassMethod:(SEL)__unused name
33 | {
34 | testassertequal(state, 1); state++;
35 | #if TARGET_OS_EXCLAVEKIT
36 | state++; // handler would have done this
37 | #elif TARGET_OS_OSX
38 | objc_addExceptionHandler(&handler, 0);
39 | testassertequal(state, 2);
40 | #else
41 | state++; // handler would have done this
42 | #endif
43 | state++;
44 | exc = [Foo new];
45 | @throw exc;
46 | }
47 |
48 |
49 | @end
50 |
51 | int main()
52 | {
53 | // unwind exception and alt handler through objc_msgSend()
54 |
55 | PUSH_POOL {
56 |
57 | #if TARGET_OS_EXCLAVEKIT
58 | const int count = 256;
59 | #else
60 | const int count = is_guardmalloc() ? 1000 : 100000;
61 | #endif
62 | state = 0;
63 | for (int i = 0; i < count; i++) {
64 | @try {
65 | testassertequal(state, 0); state++;
66 | [Foo method];
67 | testunreachable();
68 | } @catch (Bar *e) {
69 | testunreachable();
70 | } @catch (Foo *e) {
71 | testassertequal(e, exc);
72 | testassertequal(state, 4); state++;
73 | testassertequal(state, 5); [e check]; // state++
74 | RELEASE_VAR(exc);
75 | } @catch (id e) {
76 | testunreachable();
77 | } @catch (...) {
78 | testunreachable();
79 | } @finally {
80 | testassertequal(state, 6); state++;
81 | }
82 | testassertequal(state, 7); state = 0;
83 | }
84 |
85 | } POP_POOL;
86 |
87 | succeed(__FILE__);
88 | }
89 |
--------------------------------------------------------------------------------
/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 -install_name $T{DYLIBDIR}/libweakframework.dylib -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 -install_name $T{DYLIBDIR}/libweakframework.dylib -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 -install_name $T{DYLIBDIR}/libweakframework.dylib -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 -install_name $T{DYLIBDIR}/libweakimport.dylib -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 -install_name $T{DYLIBDIR}/libweakimport.dylib -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 -install_name $T{DYLIBDIR}/libweakimport.dylib -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 OS=!exclavekit
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 OS=!exclavekit
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 |
--------------------------------------------------------------------------------