Skip to content

Commit

Permalink
objc runtime 756.2 & implement objc_opt_class for passing compile.
Browse files Browse the repository at this point in the history
  • Loading branch information
RetVal committed Jan 19, 2020
1 parent ba21fe7 commit 20d965f
Show file tree
Hide file tree
Showing 229 changed files with 7,307 additions and 4,432 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# objc-runtime
objc runtime 750
objc runtime 756.2
2 changes: 1 addition & 1 deletion debug-objc/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
NSLog(@"Hello, World! %@", [NSString class]);
}
return 0;
}
8 changes: 4 additions & 4 deletions include/System/pthread_machdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@
#define _PTHREAD_TSD_SLOT_DYLD_1 1
#define _PTHREAD_TSD_SLOT_DYLD_2 2
#define _PTHREAD_TSD_SLOT_DYLD_3 3
#define _PTHREAD_TSD_RESERVED_SLOT_COUNT 4
//#define _PTHREAD_TSD_RESERVED_SLOT_COUNT 4
/* To mirror the usage by dyld for Unwind_SjLj */
#define _PTHREAD_TSD_SLOT_DYLD_8 8

/* Keys 10 - 29 are for Libc/Libsystem internal ussage */
/* used as __pthread_tsd_first + Num */
#define __PTK_LIBC_LOCALE_KEY 10
#define __PTK_LIBC_TTYNAME_KEY 11
//#define __PTK_LIBC_TTYNAME_KEY 11
#define __PTK_LIBC_LOCALTIME_KEY 12
#define __PTK_LIBC_GMTIME_KEY 13
#define __PTK_LIBC_GDTOA_BIGINT_KEY 14
Expand Down Expand Up @@ -297,8 +297,8 @@ extern "C" {

#endif

#define LOCK_INIT(l) ((l) = 0)
#define LOCK_INITIALIZER 0
//#define LOCK_INIT(l) ((l) = 0)
//#define LOCK_INITIALIZER 0

#endif /* ! __ASSEMBLER__ */
#endif /* _POSIX_PTHREAD_MACHDEP_H */
887 changes: 490 additions & 397 deletions objc.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions runtime/Messengers.subproj/objc-msg-arm64.s
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,19 @@ LExit$0:
#define GETIMP 1
#define LOOKUP 2

// CacheHit: x17 = cached IMP, x12 = address of cached IMP
// CacheHit: x17 = cached IMP, x12 = address of cached IMP, x1 = SEL
.macro CacheHit
.if $0 == NORMAL
TailCallCachedImp x17, x12 // authenticate and call imp
TailCallCachedImp x17, x12, x1 // authenticate and call imp
.elseif $0 == GETIMP
mov p0, p17
AuthAndResignAsIMP x0, x12 // authenticate imp and re-sign as IMP
ret // return IMP
cbz p0, 9f // don't ptrauth a nil imp
AuthAndResignAsIMP x0, x12, x1 // authenticate imp and re-sign as IMP
9: ret // return IMP
.elseif $0 == LOOKUP
AuthAndResignAsIMP x17, x12 // authenticate imp and re-sign as IMP
// No nil check for ptrauth: the caller would crash anyway when they
// jump to a nil IMP. We don't care if that jump also fails ptrauth.
AuthAndResignAsIMP x17, x12, x1 // authenticate imp and re-sign as IMP
ret // return imp via x17
.else
.abort oops
Expand Down
17 changes: 14 additions & 3 deletions runtime/NSObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ BOOL objc_should_deallocate(id object) {
!((objc_class *)cls)->isInitialized())
{
SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
_class_initialize(_class_getNonMetaClass(cls, (id)newObj));
class_initialize(cls, (id)newObj);

// If this class is finished with +initialize then we're good.
// If this class is still running +initialize on this thread
Expand Down Expand Up @@ -506,7 +506,7 @@ BOOL objc_should_deallocate(id object) {
}
else {
table->unlock();
_class_initialize(cls);
class_initialize(cls, obj);
goto retry;
}
}
Expand Down Expand Up @@ -614,7 +614,12 @@ BOOL objc_should_deallocate(id object) {
}

~magic_t() {
m[0] = m[1] = m[2] = m[3] = 0;
// Clear magic before deallocation.
// This prevents some false positives in memory debugging tools.
// fixme semantically this should be memset_s(), but the
// compiler doesn't optimize that at all (rdar://44856676).
volatile uint64_t *p = (volatile uint64_t *)m;
p[0] = 0; p[1] = 0;
}

bool check() const {
Expand Down Expand Up @@ -1782,6 +1787,12 @@ void objc_overrelease_during_dealloc_error(void)
return callAlloc(cls, true/*checkNil*/, true/*allocWithZone*/);
}

// Calls [[cls alloc] init].
id
objc_alloc_init(Class cls)
{
return [callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/) init];
}

void
_objc_rootDealloc(id obj)
Expand Down
11 changes: 8 additions & 3 deletions runtime/arm64-asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@
.endmacro

.macro TailCallCachedImp
// $0 = cached imp, $1 = address of cached imp
// $0 = cached imp, $1 = address of cached imp, $2 = SEL
eor $1, $1, $2 // mix SEL into ptrauth modifier
brab $0, $1
.endmacro

Expand All @@ -123,8 +124,11 @@
.endmacro

.macro AuthAndResignAsIMP
// $0 = cached imp, $1 = address of cached imp
// $0 = cached imp, $1 = address of cached imp, $2 = SEL
// note: assumes the imp is not nil
eor $1, $1, $2 // mix SEL into ptrauth modifier
autib $0, $1 // authenticate cached imp
ldr xzr, [$0] // crash if authentication failed
paciza $0 // resign cached imp as IMP
.endmacro

Expand All @@ -138,7 +142,7 @@
.endmacro

.macro TailCallCachedImp
// $0 = cached imp, $1 = address of cached imp
// $0 = cached imp, $1 = address of cached imp, $2 = SEL
br $0
.endmacro

Expand All @@ -153,6 +157,7 @@
.endmacro

.macro AuthAndResignAsIMP
// $0 = cached imp, $1 = address of cached imp, $2 = SEL
// empty
.endmacro

Expand Down
3 changes: 3 additions & 0 deletions runtime/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,12 @@ objc_msgSend_fp2ret(void /* id self, SEL op, ... */ )
* you must use \c objc_msgSend_fpret for functions returning non-integral type. For \c float or
* \c long \c double return types, cast the function to an appropriate function pointer type first.
*/
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincompatible-library-redeclaration"
OBJC_EXPORT double
objc_msgSend_fpret(id _Nullable self, SEL _Nonnull op, ...)
OBJC_AVAILABLE(10.4, 2.0, 9.0, 1.0, 2.0);
#pragma clang diagnostic pop

/* Use objc_msgSendSuper() for fp-returning messages to super. */
/* See also objc_msgSendv_fpret() below. */
Expand Down
24 changes: 18 additions & 6 deletions runtime/objc-abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,36 @@ typedef struct objc_image_info {
#if __cplusplus >= 201103L
private:
enum : uint32_t {
// 1 byte assorted flags
IsReplacement = 1<<0, // used for Fix&Continue, now ignored
SupportsGC = 1<<1, // image supports GC
RequiresGC = 1<<2, // image requires GC
OptimizedByDyld = 1<<3, // image is from an optimized shared cache
CorrectedSynthesize = 1<<4, // used for an old workaround, now ignored
IsSimulated = 1<<5, // image compiled for a simulator platform
HasCategoryClassProperties = 1<<6, // class properties in category_t
// not yet used = 1<<7

SwiftVersionMaskShift = 8,
SwiftVersionMask = 0xff << SwiftVersionMaskShift // Swift ABI version
// 1 byte Swift unstable ABI version number
SwiftUnstableVersionMaskShift = 8,
SwiftUnstableVersionMask = 0xff << SwiftUnstableVersionMaskShift,

// 2 byte Swift stable ABI version number
SwiftStableVersionMaskShift = 16,
SwiftStableVersionMask = 0xffffUL << SwiftStableVersionMaskShift
};
public:
public:
enum : uint32_t {
// Values for SwiftUnstableVersion
// All stable ABIs store SwiftVersion5 here.
SwiftVersion1 = 1,
SwiftVersion1_2 = 2,
SwiftVersion2 = 3,
SwiftVersion3 = 4
SwiftVersion3 = 4,
SwiftVersion4 = 5,
SwiftVersion4_1 = 6,
SwiftVersion4_2 = 6, // [sic]
SwiftVersion5 = 7
};

public:
Expand All @@ -126,8 +138,8 @@ typedef struct objc_image_info {
bool requiresGC() const { return flags & RequiresGC; }
bool optimizedByDyld() const { return flags & OptimizedByDyld; }
bool hasCategoryClassProperties() const { return flags & HasCategoryClassProperties; }
bool containsSwift() const { return (flags & SwiftVersionMask) != 0; }
uint32_t swiftVersion() const { return (flags & SwiftVersionMask) >> SwiftVersionMaskShift; }
bool containsSwift() const { return (flags & SwiftUnstableVersionMask) != 0; }
uint32_t swiftUnstableVersion() const { return (flags & SwiftUnstableVersionMask) >> SwiftUnstableVersionMaskShift; }
#endif
} objc_image_info;

Expand Down
7 changes: 7 additions & 0 deletions runtime/objc-block-trampolines.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
* objc-block-trampolines.h: Symbols for IMP block trampolines
*/

// WARNING: remapped code and dtrace do not play well together. Dtrace
// will place trap instructions to instrument the code, which then get
// remapped along with everything else. The remapped traps are not
// recognized by dtrace and the process crashes. To avoid this, dtrace
// blacklists this library by name. Do not change the name of this
// library. rdar://problem/42627391

#include <objc/objc-api.h>

OBJC_EXPORT const char _objc_blockTrampolineImpl
Expand Down
34 changes: 24 additions & 10 deletions runtime/objc-block-trampolines.mm
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ void Initialize() {
void *dylib = dlopen("/usr/lib/libobjc-trampolines.dylib",
RTLD_NOW | RTLD_LOCAL | RTLD_FIRST);
if (!dylib) {
_objc_fatal("couldn't dlopen libobjc-trampolines.dylib");
_objc_fatal("couldn't dlopen libobjc-trampolines.dylib: %s",
dlerror());
}

auto t = new TrampolinePointers(dylib);
Expand All @@ -177,13 +178,18 @@ void Initialize() {
uintptr_t textSegment() { return get()->textSegment; }
uintptr_t textSegmentSize() { return get()->textSegmentSize; }

// See comments below about PAGE_SIZE and PAGE_MAX_SIZE.
uintptr_t dataSize() { return PAGE_MAX_SIZE; }

uintptr_t impl() { return get()->impl.address(); }
uintptr_t start() { return get()->start.address(); }
};

static TrampolinePointerWrapper Trampolines;

// argument mode identifier
// Some calculations assume that these modes are sequential starting from 0.
// This order must match the order of the trampoline's assembly code.
typedef enum {
ReturnValueInRegisterArgumentMode,
#if SUPPORT_STRET
Expand Down Expand Up @@ -211,8 +217,17 @@ void Initialize() {
{
TrampolineBlockPageGroup *nextPageGroup; // linked list of all pages
TrampolineBlockPageGroup *nextAvailablePage; // linked list of pages with available slots

uintptr_t nextAvailable; // index of next available slot, endIndex() if no more available

const void * TrampolinePtrauth const text; // text VM region; stored only for the benefit of the leaks tool

TrampolineBlockPageGroup()
: nextPageGroup(nil)
, nextAvailablePage(nil)
, nextAvailable(startIndex())
, text((const void *)((uintptr_t)this + Trampolines.dataSize()))
{ }

// Payload data: block pointers and free list.
// Bytes parallel with trampoline header code are the fields above or unused
Expand Down Expand Up @@ -249,7 +264,7 @@ static uintptr_t startIndex() {
}

static uintptr_t endIndex() {
return (uintptr_t)PAGE_MAX_SIZE / slotSize();
return (uintptr_t)Trampolines.dataSize() / slotSize();
}

static bool validIndex(uintptr_t index) {
Expand All @@ -262,8 +277,10 @@ static bool validIndex(uintptr_t index) {
}

uintptr_t trampolinesForMode(int aMode) {
// Skip over data page and Mach-O page.
return (uintptr_t)this + PAGE_MAX_SIZE * (2 + aMode);
// Skip over the data area, one page of Mach-O headers,
// and one text page for each mode before this one.
return (uintptr_t)this + Trampolines.dataSize() +
PAGE_MAX_SIZE * (1 + aMode);
}

IMP trampoline(int aMode, uintptr_t index) {
Expand Down Expand Up @@ -334,7 +351,7 @@ static void check() {

auto textSource = Trampolines.textSegment();
auto textSourceSize = Trampolines.textSegmentSize();
auto dataSize = PAGE_MAX_SIZE;
auto dataSize = Trampolines.dataSize();

// Allocate a single contiguous region big enough to hold data+text.
kern_return_t result;
Expand All @@ -358,10 +375,7 @@ static void check() {
_objc_fatal("vm_remap trampolines failed (%d)", result);
}

TrampolineBlockPageGroup *pageGroup = (TrampolineBlockPageGroup *) dataAddress;
pageGroup->nextAvailable = pageGroup->startIndex();
pageGroup->nextPageGroup = nil;
pageGroup->nextAvailablePage = nil;
auto *pageGroup = new ((void*)dataAddress) TrampolineBlockPageGroup;

if (HeadPageGroup) {
TrampolineBlockPageGroup *lastPageGroup = HeadPageGroup;
Expand Down
Loading

0 comments on commit 20d965f

Please sign in to comment.