mirror of
https://github.com/darlinghq/darling-corefoundation.git
synced 2024-10-06 16:53:28 +00:00
Adding more missing stuff etc.
This commit is contained in:
parent
e5e3f95c44
commit
5d8d13ea12
@ -671,3 +671,14 @@ void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences *self, CFPr
|
||||
updateDictRep(self);
|
||||
__CFUnlock(&__CFApplicationPreferencesLock);
|
||||
}
|
||||
|
||||
CFDictionaryRef _CFPrefsCopyAppDictionary(_CFApplicationPreferences *prefs) {
|
||||
CFDictionaryRef retVal = NULL;
|
||||
__CFLock(&__CFApplicationPreferencesLock);
|
||||
CFPreferencesDomainRef applicationDomain = _CFPreferencesStandardDomain(prefs->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
|
||||
if (applicationDomain) {
|
||||
retVal = _CFPreferencesDomainDeepCopyDictionary(applicationDomain);
|
||||
}
|
||||
__CFUnlock(&__CFApplicationPreferencesLock);
|
||||
return retVal;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <CoreFoundation/CFAttributedString.h>
|
||||
#include "CFRuntime.h"
|
||||
#include "CFInternal.h"
|
||||
#include "debug.h"
|
||||
#include "macros.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
3
CFBase.h
3
CFBase.h
@ -188,6 +188,9 @@ CF_EXTERN_C_BEGIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CF_ASSUME_NONNULL_BEGIN
|
||||
#define CF_ASSUME_NONNULL_END
|
||||
|
||||
// Marks functions which return a CF type that needs to be released by the caller but whose names are not consistent with CoreFoundation naming rules. The recommended fix to this is to rename the functions, but this macro can be used to let the clang static analyzer know of any exceptions that cannot be fixed.
|
||||
// This macro is ONLY to be used in exceptional circumstances, not to annotate functions which conform to the CoreFoundation naming rules.
|
||||
#ifndef CF_RETURNS_RETAINED
|
||||
|
251
CFForwardingPrep.S
Normal file
251
CFForwardingPrep.S
Normal file
@ -0,0 +1,251 @@
|
||||
/**************************************
|
||||
* The marg_list's layout is:
|
||||
* d0 <-- args
|
||||
* d1
|
||||
* d2 | increasing address
|
||||
* d3 v
|
||||
* d4
|
||||
* d5
|
||||
* d6
|
||||
* d7
|
||||
* a1
|
||||
* a2
|
||||
* a3
|
||||
* a4
|
||||
* stack args...
|
||||
*
|
||||
* typedef struct objc_sendv_margs {
|
||||
* int a[4];
|
||||
* int stackArgs[...];
|
||||
* };
|
||||
*
|
||||
**************************************/
|
||||
#if __arm__
|
||||
|
||||
#include <arm/arch.h>
|
||||
|
||||
#if defined(__DYNAMIC__)
|
||||
#define MI_EXTERN(var) \
|
||||
.non_lazy_symbol_pointer ;\
|
||||
L ## var ## __non_lazy_ptr: ;\
|
||||
.indirect_symbol var ;\
|
||||
.long 0
|
||||
#else
|
||||
#define MI_EXTERN(var) \
|
||||
.globl var
|
||||
#endif
|
||||
|
||||
MI_EXTERN(___forwarding___)
|
||||
|
||||
.globl __CF_forwarding_prep_0
|
||||
.align 2
|
||||
.fnstart
|
||||
|
||||
__CF_forwarding_prep_0: // top of stack is used as marg_list
|
||||
stmfd sp!, {r0-r3} // push args to marg_list
|
||||
stmfd sp!, {fp, lr} // setup stack frame: sp -= 8, marg_list @ sp+8
|
||||
.save {fp, lr}
|
||||
.setfp fp, sp, #4
|
||||
add fp, sp, #4
|
||||
.pad #8
|
||||
sub sp, sp, #8 // pad the stack: sp -= 8, marg_list @ sp+16
|
||||
add r1, sp, #16 // use marg_list as return strage pointer
|
||||
add r0, sp, #16 // load marg_list
|
||||
bl ____forwarding___ // call through
|
||||
sub sp, fp, #4 // restore stack
|
||||
ldmfd sp!, {fp, lr} // destroy stack frame
|
||||
cmp r0, #0 // check for forwarding completion
|
||||
bne LContinue // circle back around if we're not done or failed
|
||||
ldmfd sp!, {r0-r3} // load return value registers from marg_list
|
||||
bx lr // return
|
||||
|
||||
LContinue:
|
||||
str r0, [sp] // failed or redirect; save new target in marg_list
|
||||
ldmfd sp!, {r0-r3} // restore arg registers from marg_list
|
||||
b objc_msgSend // restart message send
|
||||
|
||||
.fnend
|
||||
|
||||
.globl __CF_forwarding_prep_1
|
||||
.align 2
|
||||
.fnstart
|
||||
|
||||
__CF_forwarding_prep_1: // top of stack is used as marg_list
|
||||
stmfd sp!, {r0-r3} // push stret pointer and args to marg_list
|
||||
stmfd sp!, {fp, lr} // setup stack frame
|
||||
.save {fp, lr}
|
||||
.setfp fp, sp, #4
|
||||
add fp, sp, #4
|
||||
.pad #8
|
||||
sub sp, sp, #8 // pad the stack
|
||||
add r1, r0, #0 // load stret pointer as return storage pointer
|
||||
add r0, sp, #20 // load marg_list, skipping the stret pointer
|
||||
bl ____forwarding___ // call through
|
||||
sub sp, fp, #4 // restore stack
|
||||
ldmfd sp!, {fp, lr} // destroy stack frame
|
||||
cmp r0, #0 // check for forwarding completion
|
||||
bne LStretContinue // circle back around if we're not done or failed
|
||||
ldmfd sp!, {r0-r3} // load return value registers and stret pointer from marg_list
|
||||
bx lr // return
|
||||
|
||||
LStretContinue:
|
||||
str r0, [sp, #4] // failed or redirect; save new target in marg_list
|
||||
ldmfd sp!, {r0-r3} // restore arg registers and stret pointer from marg_list
|
||||
b objc_msgSend_stret // restart message send
|
||||
|
||||
.fnend
|
||||
|
||||
#elif __i386__
|
||||
|
||||
.text
|
||||
.global __CF_forwarding_prep_0
|
||||
.align 2, 0x90
|
||||
|
||||
__CF_forwarding_prep_0:
|
||||
// All arguments are stack-based on i386
|
||||
// Using EAX as a scratch register
|
||||
push %ebp
|
||||
mov %esp, %ebp // create a stack frame
|
||||
|
||||
sub $0x10, %esp // reserve space for args pointer, return value pointer, and return values
|
||||
and $-16, %esp // align stack
|
||||
|
||||
lea 8(%ebp), %eax // load marg_list, skipping frame pointer and return address
|
||||
mov %eax, (%esp) // pass marg_list as first argument
|
||||
|
||||
lea 8(%esp), %eax // load pointer to return value space on stack
|
||||
mov %eax, 4(%esp) // pass pointer as second argument
|
||||
|
||||
movl $0x0, 8(%esp) // clear out return value space
|
||||
movl $0x0, 12(%esp)
|
||||
|
||||
call ____forwarding___ // call through
|
||||
mov 4(%esp), %edx // temporarily save return storage pointer
|
||||
|
||||
mov %ebp, %esp // restore stack
|
||||
pop %ebp // pop stack frame
|
||||
|
||||
cmp $0, %eax // check for forwarding completion
|
||||
je LSuccess // return to caller if done
|
||||
|
||||
// Overwriting the caller's stack frame like this is not great, but there's
|
||||
// no easy place to save off the old value; the next-best solution would
|
||||
// be to call through a VERY slow path of __invoking__, at which point
|
||||
// there's no use in having a fast path in the first place. This is not an
|
||||
// issue on ARM or 64-bit Intel, and this SHOULD be safe for all cases.
|
||||
// If this causes an issue, it will manifest as subsequent messages to an
|
||||
// object that implements -forwardingTargetForSelector: being sent to the
|
||||
// forwarding target directly instead of going to the original object. This
|
||||
// would have to be caused by the compiler not reloading the object pointer
|
||||
// onto the stack for subsequent message sends to the same target.
|
||||
mov %eax, 4(%esp) // overwrite original "self" value
|
||||
jmp _objc_msgSend // restart message send
|
||||
LSuccess:
|
||||
mov (%edx), %eax // load return value registers from return storage
|
||||
mov 4(%edx), %edx
|
||||
ret // return
|
||||
|
||||
.text
|
||||
.global __CF_forwarding_prep_1
|
||||
.align 2, 0x90
|
||||
|
||||
__CF_forwarding_prep_1:
|
||||
push %ebp
|
||||
mov %esp, %ebp // create a stack frame
|
||||
|
||||
sub $0x8, %esp // reserve space for args pointer and return value
|
||||
and $-16, %esp // align stack
|
||||
|
||||
lea 12(%ebp), %eax // load marg_list, skipping frame pointer, return address, and stret pointer
|
||||
mov %eax, (%esp) // pass marg_list as first argument
|
||||
|
||||
mov 8(%ebp), %eax // load stret pointer
|
||||
mov %eax, 4(%esp) // pass as second argument
|
||||
|
||||
call ____forwarding___ // call through
|
||||
|
||||
mov %ebp, %esp // restore stack
|
||||
pop %ebp // pop stack frame
|
||||
|
||||
cmp $0, %eax // check for forwarding completion
|
||||
je LStretSuccess // return to caller if done
|
||||
|
||||
mov %eax, 8(%esp) // overwrite original "self" value (see long comment above)
|
||||
jmp _objc_msgSend_stret // restart message send
|
||||
LStretSuccess:
|
||||
ret $4 // return value in stret pointer; return
|
||||
|
||||
#elif __x86_64__
|
||||
|
||||
.text
|
||||
.globl __CF_forwarding_prep_0
|
||||
.globl __CF_forwarding_prep_1
|
||||
.align 2, 0x90
|
||||
|
||||
__CF_forwarding_prep_0:
|
||||
__CF_forwarding_prep_1:
|
||||
push %rbp
|
||||
movq %rsp, %rbp
|
||||
|
||||
// Copy args from regs into a stack var
|
||||
subq $0xd0, %rsp
|
||||
movq %rax, 0xb0(%rsp)
|
||||
movapd %xmm7, 0xa0(%rsp)
|
||||
movapd %xmm6, 0x90(%rsp)
|
||||
movapd %xmm5, 0x80(%rsp)
|
||||
movapd %xmm4, 0x70(%rsp)
|
||||
movapd %xmm3, 0x60(%rsp)
|
||||
movapd %xmm2, 0x50(%rsp)
|
||||
movapd %xmm1, 0x40(%rsp)
|
||||
movapd %xmm0, 0x30(%rsp)
|
||||
movq %r9, 0x28(%rsp)
|
||||
movq %r8, 0x20(%rsp)
|
||||
movq %rcx, 0x18(%rsp)
|
||||
movq %rdx, 0x10(%rsp)
|
||||
movq %rsi, 8(%rsp)
|
||||
movq %rdi, (%rsp)
|
||||
|
||||
movq %rsp, %rdi
|
||||
xorl %esi, %esi
|
||||
call ____forwarding___ // call through
|
||||
|
||||
cmpq $0, %rax // check for forwarding completion
|
||||
jne Lfail // return to caller if done
|
||||
|
||||
// double return
|
||||
movapd 0x20(%rax), %xmm1
|
||||
movapd 0x10(%rax), %xmm0
|
||||
|
||||
movq 8(%rax), %rdx
|
||||
movq (%rax), %rax
|
||||
|
||||
movq %rbp, %rsp
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
Lfail:
|
||||
|
||||
movq %rax, %rdi
|
||||
movq 0x80(%rsp), %rax
|
||||
movapd 0xa0(%rsp), %xmm7
|
||||
movapd 0x90(%rsp), %xmm6
|
||||
movapd 0x80(%rsp), %xmm5
|
||||
movapd 0x70(%rsp), %xmm4
|
||||
movapd 0x60(%rsp), %xmm3
|
||||
movapd 0x50(%rsp), %xmm2
|
||||
movapd 0x40(%rsp), %xmm1
|
||||
movapd 0x30(%rsp), %xmm0
|
||||
movq 0x28(%rsp), %r9
|
||||
movq 0x20(%rsp), %r8
|
||||
movq 0x18(%rsp), %rcx
|
||||
movq 0x10(%rsp), %rdx
|
||||
movq 8(%rsp), %rsi
|
||||
// movq (%rsp), %rdi // self overwritten
|
||||
|
||||
movq %rbp, %rsp
|
||||
pop %rbp
|
||||
|
||||
jmp _objc_msgSend // restart message send
|
||||
#else
|
||||
#error Missing forwarding prep handlers for this arch https://code.google.com/p/apportable/issues/detail?id=619
|
||||
#endif
|
11
CFRunLoop.c
11
CFRunLoop.c
@ -1459,6 +1459,17 @@ CF_EXPORT CFTypeRef _CFRunLoopGet2b(CFRunLoopRef rl) {
|
||||
return rl->_counterpart;
|
||||
}
|
||||
|
||||
CF_EXPORT CFTypeRef _CFRunLoopSet2(CFRunLoopRef rl, CFTypeRef (*counterpartProvider)(CFRunLoopRef)) {
|
||||
CFTypeRef ret = NULL;
|
||||
__CFLock(&loopsLock);
|
||||
if (rl->_counterpart == NULL) {
|
||||
rl->_counterpart = counterpartProvider(rl);
|
||||
}
|
||||
ret = rl->_counterpart;
|
||||
__CFUnlock(&loopsLock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DEPLOYMENT_TARGET_MACOSX
|
||||
void _CFRunLoopSetCurrent(CFRunLoopRef rl) {
|
||||
if (pthread_main_np()) return;
|
||||
|
@ -903,6 +903,10 @@ void __CFInitialize(void) {
|
||||
if (!__CFInitialized && !__CFInitializing) {
|
||||
__CFInitializing = 1;
|
||||
|
||||
#ifdef __i386__
|
||||
__exceptionInit();
|
||||
#endif
|
||||
|
||||
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR
|
||||
if (!pthread_main_np()) HALT; // CoreFoundation must be initialized on the main thread
|
||||
#endif
|
||||
|
42
CFXPCBridge.c
Normal file
42
CFXPCBridge.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* CFXPCBridge.c
|
||||
|
||||
Copyright (C) 2016 Lubos Dolezel
|
||||
|
||||
This file is part of the GNUstep CoreBase Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <CoreFoundation/CFXPCBridge.h>
|
||||
|
||||
CFTypeRef _CFXPCCreateCFObjectFromXPCObject(xpc_object_t xpcattrs)
|
||||
{
|
||||
// TODO
|
||||
// This function converts XPC null, bool, string, data, int64,
|
||||
// double, date, uuid, array and dictionary types to their
|
||||
// CF counterparts.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xpc_object_t _CFXPCCreateXPCObjectFromCFObject(CFTypeRef attrs)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: _CFXPCCreateCFObjectFromXPCMessage
|
||||
// This function takes the "ECF19A18-7AA6-4141-B4DC-A2E5123B2B5C" data value
|
||||
// from the dictionary and parses it as a binary plist.
|
37
CFXPCBridge.h
Normal file
37
CFXPCBridge.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* CFXPCBridge.h
|
||||
|
||||
Copyright (C) 2016 Lubos Dolezel
|
||||
|
||||
This file is part of the GNUstep CoreBase Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CFCOREFOUNDATION_CFXPC_H__
|
||||
#define __CFCOREFOUNDATION_CFXPC_H__
|
||||
#include <CoreFoundation/CFBase.h>
|
||||
#include <xpc/xpc.h>
|
||||
|
||||
CF_EXTERN_C_BEGIN
|
||||
|
||||
extern CFTypeRef _CFXPCCreateCFObjectFromXPCObject(xpc_object_t xpcattrs);
|
||||
|
||||
extern xpc_object_t _CFXPCCreateXPCObjectFromCFObject(CFTypeRef attrs);
|
||||
|
||||
CF_EXTERN_C_END
|
||||
|
||||
#endif
|
@ -3,6 +3,7 @@ project(corefoundation)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc -fblocks -fconstant-cfstrings -fexceptions \
|
||||
-Wno-bridge-cast \
|
||||
-include ${CMAKE_CURRENT_SOURCE_DIR}/CoreFoundation_Prefix.h \
|
||||
-include ${CMAKE_CURRENT_SOURCE_DIR}/macros.h \
|
||||
-mmacosx-version-min=10.10")
|
||||
|
||||
include(darling_framework)
|
||||
@ -26,7 +27,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src/external/cfnetwork/include
|
||||
${CMAKE_SOURCE_DIR}/src/external/foundation/include
|
||||
${CMAKE_SOURCE_DIR}/src/external/foundation/src
|
||||
${CMAKE_SOURCE_DIR}/src/libmalloc/include)
|
||||
${CMAKE_SOURCE_DIR}/src/external/coregraphics/Headers
|
||||
${CMAKE_SOURCE_DIR}/src/libmalloc/include
|
||||
)
|
||||
|
||||
add_definitions(-DCF_BUILDING_CF
|
||||
-DDEPLOYMENT_TARGET_MACOSX=1
|
||||
@ -98,6 +101,7 @@ set(cf_sources
|
||||
CFStringEncodingDatabase.c
|
||||
CFStringEncodings.c
|
||||
CFStringScanner.c
|
||||
CFStringTokenizer.c
|
||||
CFStringUtilities.c
|
||||
CFSystemDirectories.c
|
||||
CFTimeZone.c
|
||||
@ -138,6 +142,7 @@ set(cf_sources
|
||||
NSCharacterSet.m
|
||||
NSInputStream.m
|
||||
NSInvocation.m
|
||||
NSInvoke-x86.S
|
||||
NSLocale.m
|
||||
NSMessageBuilder.m
|
||||
NSMethodSignature.m
|
||||
@ -157,9 +162,9 @@ set(cf_sources
|
||||
NSTimeZone.m
|
||||
NSURL.m
|
||||
NSZombie.m
|
||||
cifframe.m
|
||||
GSFFIInvocation.m
|
||||
GSObjCRuntime.m
|
||||
CFForwardingPrep.S
|
||||
FoundationExceptions.m
|
||||
CFXPCBridge.c
|
||||
)
|
||||
|
||||
add_framework(CoreFoundation
|
||||
@ -172,7 +177,6 @@ add_framework(CoreFoundation
|
||||
objc
|
||||
system
|
||||
icucore
|
||||
ffi
|
||||
LINK_FLAGS
|
||||
"-Wl,-init,___CFInitialize \
|
||||
-Wl,-compatibility_version,150 \
|
||||
@ -184,3 +188,7 @@ add_framework(CoreFoundation
|
||||
-Wl,-segprot,__UNICODE,r,r"
|
||||
)
|
||||
|
||||
add_darling_executable(plconvert plconvert.c)
|
||||
target_link_libraries(plconvert system CoreFoundation)
|
||||
install(TARGETS plconvert DESTINATION libexec/darling/usr/bin)
|
||||
|
||||
|
@ -85,6 +85,8 @@
|
||||
#include <CoreFoundation/CFURLAccess.h>
|
||||
#include <CoreFoundation/CFUUID.h>
|
||||
#include <CoreFoundation/CFUtilities.h>
|
||||
#include <CoreFoundation/CFMachPort.h>
|
||||
#include <CoreFoundation/CFXPCBridge.h>
|
||||
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || TARGET_OS_WIN32
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
|
39
FoundationExceptions.h
Normal file
39
FoundationExceptions.h
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Lubos Dolezel
|
||||
*
|
||||
* Darling is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Foobar is distributed in the hope that it will be useful,
|
||||
* Darling WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FOUNDATION_EXCEPTIONS_H
|
||||
#define _FOUNDATION_EXCEPTIONS_H
|
||||
|
||||
#if !__OBJC2__
|
||||
|
||||
enum {
|
||||
kCFDoExceptionOperationGetUncaughtHandler = 0,
|
||||
kCFDoExceptionOperationSetUncaughtHandler,
|
||||
kCFDoExceptionOperationRaiseError = 40,
|
||||
kCFDoExceptionOperationAddHandler = 50,
|
||||
kCFDoExceptionOperationRemoveHandler,
|
||||
kCFDoExceptionOperationExtractException
|
||||
};
|
||||
|
||||
void* _CFDoExceptionOperation(int op, void* arg);
|
||||
|
||||
__attribute__((visibility("hidden")))
|
||||
void __exceptionInit(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
192
FoundationExceptions.m
Normal file
192
FoundationExceptions.m
Normal file
@ -0,0 +1,192 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Lubos Dolezel
|
||||
*
|
||||
* Darling is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Foobar is distributed in the hope that it will be useful,
|
||||
* Darling WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !__OBJC2__
|
||||
|
||||
#include <objc/runtime.h>
|
||||
#include <objc/objc-exception.h>
|
||||
#include "CFLogUtilities.h"
|
||||
#include "CFInternal.h"
|
||||
#include "ForFoundationOnly.h"
|
||||
#include "FoundationExceptions.h"
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSException.h>
|
||||
|
||||
static void (*__uncaughtExceptionHandler)(id exc) = NULL;
|
||||
|
||||
typedef struct {
|
||||
jmp_buf buf;
|
||||
void* pointers[4];
|
||||
} LocalData_t;
|
||||
|
||||
typedef struct ThreadChainLink
|
||||
{
|
||||
void** localExceptionData;
|
||||
size_t localExceptionDataCount, localExceptionDataSize;
|
||||
} ThreadChainLink_t;
|
||||
|
||||
static int objectIsKindOfNSException(id exc);
|
||||
|
||||
// Throw handler with Foundation support
|
||||
static void __raiseError(id exc)
|
||||
{
|
||||
ThreadChainLink_t* chainLink = (ThreadChainLink_t*) _CFGetTSD(__CFTSDKeyExceptionData);
|
||||
if (chainLink != NULL)
|
||||
{
|
||||
LocalData_t* led = (LocalData_t*) chainLink->localExceptionData[chainLink->localExceptionDataCount - 1];
|
||||
|
||||
if (led != NULL)
|
||||
{
|
||||
chainLink->localExceptionDataCount--;
|
||||
led->pointers[0] = exc;
|
||||
_longjmp(led->buf, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (__uncaughtExceptionHandler != NULL && objectIsKindOfNSException(exc))
|
||||
{
|
||||
__uncaughtExceptionHandler(exc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!objectIsKindOfNSException(exc))
|
||||
{
|
||||
CFLog(kCFLogLevelError, CFSTR("*** Terminating app due to uncaught exception of class %s"), object_getClassName(exc));
|
||||
}
|
||||
else
|
||||
{
|
||||
CFLog(kCFLogLevelError, CFSTR("*** Terminating app due to uncaught exception of class %@, reason: \"%@\",\n"
|
||||
"*** Call stack:\n%@\n"),
|
||||
[exc name], [exc reason], [exc description]);
|
||||
}
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
static id __exceptionExtract(void* localExceptionData)
|
||||
{
|
||||
LocalData_t* led = (LocalData_t*)localExceptionData;
|
||||
return (id) led->pointers[0];
|
||||
}
|
||||
|
||||
static int objectIsKindOfNSException(id exc)
|
||||
{
|
||||
Class c = [NSException class];
|
||||
if (class_respondsToSelector(object_getClass(exc), @selector(isKindOfClass:)))
|
||||
{
|
||||
return [exc isKindOfClass: c];
|
||||
}
|
||||
else
|
||||
{
|
||||
// NSException implements isKindOfClass:, so this means it's not an NSException
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __exceptionFinalize(void* ptr)
|
||||
{
|
||||
ThreadChainLink_t* tsd = (ThreadChainLink_t*) ptr;
|
||||
free(tsd->localExceptionData);
|
||||
free(tsd);
|
||||
}
|
||||
|
||||
static int __exceptionMatch(Class matchClass, id exc)
|
||||
{
|
||||
Class excClass = object_getClass(exc);
|
||||
|
||||
if (class_respondsToSelector(excClass, @selector(isKindOfClass:)))
|
||||
{
|
||||
return [exc isKindOfClass: matchClass];
|
||||
}
|
||||
else
|
||||
{
|
||||
while (excClass != NULL)
|
||||
{
|
||||
if (excClass == matchClass)
|
||||
return 1;
|
||||
excClass = class_getSuperclass(excClass);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __addHandler2(void* localExceptionData)
|
||||
{
|
||||
ThreadChainLink_t* tsd = (ThreadChainLink_t*) _CFGetTSD(__CFTSDKeyExceptionData);
|
||||
|
||||
if (!tsd)
|
||||
{
|
||||
tsd = (ThreadChainLink_t*) malloc(sizeof(ThreadChainLink_t));
|
||||
memset(tsd, 0, sizeof(*tsd));
|
||||
_CFSetTSD(__CFTSDKeyExceptionData, tsd, __exceptionFinalize);
|
||||
}
|
||||
|
||||
if (tsd->localExceptionDataCount+1 > tsd->localExceptionDataSize)
|
||||
{
|
||||
tsd->localExceptionDataSize += 16;
|
||||
tsd->localExceptionData = (void**) realloc(tsd->localExceptionData, sizeof(void*) * tsd->localExceptionDataSize);
|
||||
}
|
||||
|
||||
// store pointer to localExceptionData in tsd
|
||||
tsd->localExceptionData[tsd->localExceptionDataCount] = localExceptionData;
|
||||
tsd->localExceptionDataCount++;
|
||||
}
|
||||
|
||||
static void __removeHandler2(void* localExceptionData)
|
||||
{
|
||||
ThreadChainLink_t* tsd = (ThreadChainLink_t*) _CFGetTSD(__CFTSDKeyExceptionData);
|
||||
tsd->localExceptionDataCount--;
|
||||
}
|
||||
|
||||
void* _CFDoExceptionOperation(int op, void* arg)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case kCFDoExceptionOperationGetUncaughtHandler:
|
||||
return __uncaughtExceptionHandler;
|
||||
case kCFDoExceptionOperationSetUncaughtHandler:
|
||||
__uncaughtExceptionHandler = arg;
|
||||
break;
|
||||
case kCFDoExceptionOperationRaiseError:
|
||||
__raiseError((id) arg);
|
||||
break;
|
||||
case kCFDoExceptionOperationAddHandler:
|
||||
__addHandler2(arg);
|
||||
break;
|
||||
case kCFDoExceptionOperationRemoveHandler:
|
||||
__removeHandler2(arg);
|
||||
break;
|
||||
case kCFDoExceptionOperationExtractException:
|
||||
return __exceptionExtract(arg);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static objc_exception_functions_t old_exc_funcs;
|
||||
|
||||
// Called from __CFInitialize
|
||||
void __exceptionInit(void)
|
||||
{
|
||||
objc_exception_functions_t funcs = { 0, __raiseError, __addHandler2, __removeHandler2, __exceptionExtract, __exceptionMatch };
|
||||
objc_exception_get_functions(&old_exc_funcs);
|
||||
objc_exception_set_functions(&funcs);
|
||||
}
|
||||
|
||||
#endif // !__OBJC2__
|
||||
|
@ -1,5 +1,4 @@
|
||||
#import <Foundation/NSException.h>
|
||||
#include "debug.h"
|
||||
|
||||
#define NUM_BUCKET_SIZES 64
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#import "NSBlock.h"
|
||||
#import <dispatch/dispatch.h>
|
||||
#import <objc/runtime.h>
|
||||
#include "debug.h"
|
||||
|
||||
extern Class objc_initializeClassPair(Class superclass_gen, const char *name, Class cls_gen, Class meta_gen);
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
#import <Foundation/NSLocale.h>
|
||||
#import "NSCalendarInternal.h"
|
||||
#import "NSObjectInternal.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern void CFCalendarSetGregorianStartDate(CFCalendarRef calendar, CFDateRef date);
|
||||
extern CFDateRef CFCalendarCopyGregorianStartDate(CFCalendarRef calendar);
|
||||
|
1299
NSInvocation.m
1299
NSInvocation.m
File diff suppressed because it is too large
Load Diff
10
NSInvocationInternal.h
Normal file
10
NSInvocationInternal.h
Normal file
@ -0,0 +1,10 @@
|
||||
#import <objc/message.h>
|
||||
|
||||
// By grabbing at least 4 words for retSize, we can blindly copy r0-r3
|
||||
// into retdata when returning from an invocation.
|
||||
#define RET_SIZE_ARGS (4 * sizeof(int))
|
||||
|
||||
void __invoke__(void *send, void *retdata, marg_list args, size_t len, const char *rettype);
|
||||
|
||||
extern void _CF_forwarding_prep_0();
|
||||
extern void _CF_forwarding_prep_1();
|
149
NSInvoke-x86.S
Normal file
149
NSInvoke-x86.S
Normal file
@ -0,0 +1,149 @@
|
||||
|
||||
.text
|
||||
.align 2, 0x90
|
||||
.globl ___invoke__
|
||||
___invoke__:
|
||||
|
||||
# void __invoke__(void (*msgSend)(...),
|
||||
# void *retdata,
|
||||
# marg_list args,
|
||||
# size_t frame_length,
|
||||
# const char *return_type)
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
# Save retdata, scratch register, and return address.
|
||||
push %ebp # Prologue
|
||||
mov %esp, %ebp
|
||||
push %edi
|
||||
push %esi
|
||||
push %edx
|
||||
push %ebx
|
||||
|
||||
mov 12+8(%ebp), %eax #$eax = frame_length
|
||||
mov 8+8(%ebp), %edx #$edx = args
|
||||
|
||||
mov %esp, %ebx
|
||||
subl %eax, %esp #push the stack down
|
||||
andl $-16, %esp #and align
|
||||
|
||||
Lpush:
|
||||
movl -4(%eax,%edx), %edi
|
||||
movl %edi, -4(%esp,%eax)
|
||||
sub $4, %eax
|
||||
test %eax, %eax
|
||||
jne Lpush
|
||||
|
||||
mov 0+8(%ebp), %edi #$edi = msgSend
|
||||
calll *%edi
|
||||
|
||||
mov 4+8(%ebp), %esi #$esi = retdata
|
||||
|
||||
mov %eax, (%esi) # copy the result (probably) into *retdata
|
||||
|
||||
#next, check to see if we need to put something else (ie something from
|
||||
#the x87 registers or a 64-bit value) into *retdata instead.
|
||||
|
||||
mov 8+16(%ebp), %eax #$eax == return_type
|
||||
mov (%eax), %al
|
||||
cmpb $0x71, %al # if (returnType[0] == 'q') // int64_t
|
||||
je Lsixtyfourret
|
||||
cmpb $0x51, %al # if (returnType[0] == 'Q') // uint64_t
|
||||
je Lsixtyfourret
|
||||
cmpb $0x44, %al # if (returnType[0] == 'D') // long double
|
||||
je Llongdoubleret
|
||||
cmpb $0x64, %al # if (returnType[0] == 'd') // double
|
||||
je Ldoubleret
|
||||
cmpb $0x66, %al # if (returnType[0] == 'f') // float
|
||||
jne Ldone
|
||||
fstps (%esi) # this is how to get things out of x87.
|
||||
# fstp pops and stores a certain length (determined by the suffix -
|
||||
# s for float, l for double, t for long double - just go with it)
|
||||
# in the location given (in this case *$esi)
|
||||
jmp Ldone #then jump to to cleanup and return
|
||||
Lsixtyfourret:
|
||||
# just store edx too
|
||||
mov %edx, 4(%esi)
|
||||
jmp Ldone
|
||||
Ldoubleret:
|
||||
fstpl (%esi)
|
||||
jmp Ldone
|
||||
Llongdoubleret:
|
||||
fstpt (%esi)
|
||||
|
||||
Ldone:
|
||||
mov %ebx, %esp # restore stack!
|
||||
pop %ebx
|
||||
pop %edx
|
||||
pop %esi
|
||||
pop %edi
|
||||
mov %ebp, %esp # Epilogue
|
||||
pop %ebp
|
||||
ret
|
||||
|
||||
#else // Now the x86-64 version
|
||||
|
||||
push %rbp # Prologue
|
||||
movq %rsp, %rbp
|
||||
push %rdi
|
||||
push %rsi
|
||||
push %r8
|
||||
movq %rdx, %rsi
|
||||
|
||||
subq %rcx, %rsp # Push the stack down
|
||||
andq $-16, %rsp #and align
|
||||
|
||||
# Shift stack contents (frame_length/8) times,
|
||||
# 8 bytes at a time
|
||||
# TODO: More efficient than the Lpush loop
|
||||
# in i386 assembly above
|
||||
movq %rsp, %rdi
|
||||
shrq $3, %rcx # frame_length /= 8
|
||||
cld
|
||||
rep movsq
|
||||
|
||||
# Copy args into registers
|
||||
movq 0xb0(%rsp), %rax
|
||||
movapd 0xa0(%rsp), %xmm7
|
||||
movapd 0x90(%rsp), %xmm6
|
||||
movapd 0x80(%rsp), %xmm5
|
||||
movapd 0x70(%rsp), %xmm4
|
||||
movapd 0x60(%rsp), %xmm3
|
||||
movapd 0x50(%rsp), %xmm2
|
||||
movapd 0x40(%rsp), %xmm1
|
||||
movapd 0x30(%rsp), %xmm0
|
||||
|
||||
movq 0x28(%rsp), %r9
|
||||
movq 0x20(%rsp), %r8
|
||||
movq 0x18(%rsp), %rcx
|
||||
movq 0x10(%rsp), %rdx
|
||||
movq 8(%rsp), %rsi
|
||||
movq (%rsp), %rdi
|
||||
|
||||
addq $224, %rsp
|
||||
movq -8(%rbp), %r10 # call objc_msgSend
|
||||
callq *%r10
|
||||
|
||||
movq -16(%rbp), %rsi # return value
|
||||
movq -24(%rbp), %rcx
|
||||
cmpb $0x44, %cl # if (returnType[0] == 'D') // long double
|
||||
je Llongdoubleret
|
||||
|
||||
# double
|
||||
movapd %xmm1, 32(%rsi)
|
||||
movapd %xmm0, 16(%rsi)
|
||||
|
||||
# int128
|
||||
movq %rdx, 8(%rsi)
|
||||
movq %rax, (%rsi)
|
||||
|
||||
jmp Ldone
|
||||
Llongdoubleret:
|
||||
fstpt (%rsi)
|
||||
Ldone:
|
||||
movq %rbp, %rsp # Epilogue
|
||||
pop %rbp
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#import "NSBasicHash.h"
|
||||
#import "NSFastEnumerationEnumerator.h"
|
||||
#import "NSObjectInternal.h"
|
||||
#include "debug.h"
|
||||
|
||||
@interface __NSPlaceholderOrderedSet : NSMutableOrderedSet
|
||||
+ (id)mutablePlaceholder;
|
||||
|
86
cifframe.h
86
cifframe.h
@ -1,86 +0,0 @@
|
||||
/* cifframe - Wrapper/Objective-C interface for ffi function interface
|
||||
|
||||
Copyright (C) 1999, Free Software Foundation, Inc.
|
||||
|
||||
Written by: Adam Fedor <fedor@gnu.org>
|
||||
Created: Feb 2000
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef cifframe_h_INCLUDE
|
||||
#define cifframe_h_INCLUDE
|
||||
|
||||
#include <ffi.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
* Avoid conflicts when other headers try to define UINT32 and UINT64
|
||||
*/
|
||||
#if defined(UINT32)
|
||||
#undef UINT32
|
||||
#endif
|
||||
#if defined(UINT64)
|
||||
#undef UINT64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#import "Foundation/NSMethodSignature.h"
|
||||
//#import "GNUstepBase/DistributedObjects.h"
|
||||
//#import "GSPrivate.h"
|
||||
|
||||
typedef struct _cifframe_t {
|
||||
ffi_cif cif;
|
||||
int nargs;
|
||||
ffi_type **arg_types;
|
||||
void **values;
|
||||
} cifframe_t;
|
||||
|
||||
/* Memory to use to put executable code in.
|
||||
*/
|
||||
@interface GSCodeBuffer : NSObject
|
||||
{
|
||||
unsigned size;
|
||||
void *buffer;
|
||||
void *executable;
|
||||
id frame;
|
||||
}
|
||||
+ (GSCodeBuffer*) memoryWithSize: (NSUInteger)_size;
|
||||
- (void*) buffer;
|
||||
- (void*) executable;
|
||||
- (id) initWithSize: (NSUInteger)_size;
|
||||
- (void) protect;
|
||||
- (void) setFrame: (id)aFrame;
|
||||
@end
|
||||
|
||||
|
||||
@class NSMutableData;
|
||||
|
||||
extern NSMutableData *cifframe_from_signature (NSMethodSignature *info);
|
||||
|
||||
extern GSCodeBuffer* cifframe_closure (NSMethodSignature *sig, void (*func)());
|
||||
|
||||
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
|
||||
int size);
|
||||
extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer,
|
||||
int size);
|
||||
extern void *cifframe_arg_addr(cifframe_t *cframe, int index);
|
||||
extern BOOL cifframe_decode_arg (const char *type, void* buffer);
|
||||
extern BOOL cifframe_encode_arg (const char *type, void* buffer);
|
||||
|
||||
#endif
|
747
cifframe.m
747
cifframe.m
@ -1,747 +0,0 @@
|
||||
/** cifframe.m - Wrapper/Objective-C interface for ffi function interface
|
||||
|
||||
Copyright (C) 1999-2015 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Adam Fedor <fedor@gnu.org>
|
||||
Date: Dec 1999, rewritten Apr 2002
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
//#import "common.h"
|
||||
|
||||
//#if !defined (__GNU_LIBOBJC__)
|
||||
# include <objc/objc-class.h>
|
||||
//#endif
|
||||
|
||||
#include <malloc.h>
|
||||
#include <alloca.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "cifframe.h"
|
||||
#import "Foundation/NSException.h"
|
||||
#import "Foundation/NSData.h"
|
||||
#import "Foundation/NSGeometry.h"
|
||||
#import "GSInvocation.h"
|
||||
#include "encoding.c"
|
||||
//#import "GSPrivate.h"
|
||||
|
||||
#define GS_SIZEOF_SHORT 2
|
||||
#define GS_SIZEOF_INT 4
|
||||
#define GS_SIZEOF_LONG_LONG 8
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define GS_SIZEOF_LONG 8
|
||||
#else
|
||||
# define GS_SIZEOF_LONG 4
|
||||
#endif
|
||||
|
||||
/* ffi defines types in a very odd way that doesn't map to the
|
||||
normal objective-c type (see ffi.h). Here we make up for that */
|
||||
#if GS_SIZEOF_SHORT == 2
|
||||
#define gsffi_type_ushort ffi_type_uint16
|
||||
#define gsffi_type_sshort ffi_type_sint16
|
||||
#elif GS_SIZEOF_SHORT == 4
|
||||
#define gsffi_type_ushort ffi_type_uint32
|
||||
#define gsffi_type_sshort ffi_type_sint32
|
||||
#else
|
||||
#error FFI Sizeof SHORT case not handled
|
||||
#endif
|
||||
|
||||
#if GS_SIZEOF_INT == 2
|
||||
#define gsffi_type_uint ffi_type_uint16
|
||||
#define gsffi_type_sint ffi_type_sint16
|
||||
#elif GS_SIZEOF_INT == 4
|
||||
#define gsffi_type_uint ffi_type_uint32
|
||||
#define gsffi_type_sint ffi_type_sint32
|
||||
#elif GS_SIZEOF_INT == 8
|
||||
#define gsffi_type_uint ffi_type_uint64
|
||||
#define gsffi_type_sint ffi_type_sint64
|
||||
#else
|
||||
#error FFI Sizeof INT case not handled
|
||||
#endif
|
||||
|
||||
#if GS_SIZEOF_LONG == 2
|
||||
#define gsffi_type_ulong ffi_type_uint16
|
||||
#define gsffi_type_slong ffi_type_sint16
|
||||
#elif GS_SIZEOF_LONG == 4
|
||||
#define gsffi_type_ulong ffi_type_uint32
|
||||
#define gsffi_type_slong ffi_type_sint32
|
||||
#elif GS_SIZEOF_LONG == 8
|
||||
#define gsffi_type_ulong ffi_type_uint64
|
||||
#define gsffi_type_slong ffi_type_sint64
|
||||
#else
|
||||
#error FFI Sizeof LONG case not handled
|
||||
#endif
|
||||
|
||||
#ifdef _C_LNG_LNG
|
||||
#if GS_SIZEOF_LONG_LONG == 8
|
||||
#define gsffi_type_ulong_long ffi_type_uint64
|
||||
#define gsffi_type_slong_long ffi_type_sint64
|
||||
#else
|
||||
#error FFI Sizeof LONG LONG case not handled
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ffi_type *cifframe_type(const char *typePtr, const char **advance);
|
||||
|
||||
static inline const char *
|
||||
gs_skip_type_qualifier_and_layout_info (const char *types)
|
||||
{
|
||||
while (*types == '+'
|
||||
|| *types == '-'
|
||||
|| *types == _C_CONST
|
||||
|| *types == _C_IN
|
||||
|| *types == _C_INOUT
|
||||
|| *types == _C_OUT
|
||||
|| *types == _C_BYCOPY
|
||||
|| *types == _C_BYREF
|
||||
|| *types == _C_ONEWAY
|
||||
|| *types == _C_GCINVISIBLE
|
||||
|| isdigit ((unsigned char) *types))
|
||||
{
|
||||
types++;
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
GSSelectorTypesMatch(const char *types1, const char *types2)
|
||||
{
|
||||
if (! types1 || ! types2)
|
||||
return NO;
|
||||
|
||||
while (*types1 && *types2)
|
||||
{
|
||||
types1 = gs_skip_type_qualifier_and_layout_info (types1);
|
||||
types2 = gs_skip_type_qualifier_and_layout_info (types2);
|
||||
|
||||
/* Reached the end of the selector. */
|
||||
if (! *types1 && ! *types2)
|
||||
return YES;
|
||||
|
||||
/* Ignore structure name yet compare layout. */
|
||||
if (*types1 == '{' && *types2 == '{')
|
||||
{
|
||||
while (*types1 != '=')
|
||||
types1++;
|
||||
|
||||
while (*types2 != '=')
|
||||
types2++;
|
||||
}
|
||||
|
||||
if (*types1 != *types2)
|
||||
return NO;
|
||||
|
||||
types1++;
|
||||
types2++;
|
||||
}
|
||||
|
||||
types1 = gs_skip_type_qualifier_and_layout_info (types1);
|
||||
types2 = gs_skip_type_qualifier_and_layout_info (types2);
|
||||
|
||||
return (! *types1 && ! *types2);
|
||||
}
|
||||
|
||||
/* Best guess at the space needed for a structure, since we don't know
|
||||
for sure until it's calculated in ffi_prep_cif, which is too late */
|
||||
int
|
||||
cifframe_guess_struct_size(ffi_type *stype)
|
||||
{
|
||||
int i, size;
|
||||
unsigned align = __alignof(double);
|
||||
|
||||
if (stype->elements == NULL)
|
||||
return stype->size;
|
||||
|
||||
size = 0;
|
||||
i = 0;
|
||||
while (stype->elements[i])
|
||||
{
|
||||
if (stype->elements[i]->elements)
|
||||
size += cifframe_guess_struct_size(stype->elements[i]);
|
||||
else
|
||||
size += stype->elements[i]->size;
|
||||
|
||||
if (size % align != 0)
|
||||
{
|
||||
size += (align - size % align);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
NSMutableData *
|
||||
cifframe_from_signature (NSMethodSignature *info)
|
||||
{
|
||||
unsigned size = sizeof(cifframe_t);
|
||||
unsigned align = __alignof(double);
|
||||
unsigned type_offset = 0;
|
||||
unsigned offset = 0;
|
||||
NSMutableData *result;
|
||||
void *buf;
|
||||
int i;
|
||||
int numargs = [info numberOfArguments];
|
||||
ffi_type *rtype;
|
||||
ffi_type *arg_types[numargs];
|
||||
cifframe_t *cframe;
|
||||
|
||||
/* FIXME: in cifframe_type, return values/arguments that are structures
|
||||
have custom ffi_types with are allocated separately. We should allocate
|
||||
them in our cifframe so we don't leak memory. Or maybe we could
|
||||
cache structure types? */
|
||||
rtype = cifframe_type([info methodReturnType], NULL);
|
||||
for (i = 0; i < numargs; i++)
|
||||
{
|
||||
arg_types[i] = cifframe_type([info getArgumentTypeAtIndex: i], NULL);
|
||||
}
|
||||
|
||||
if (numargs > 0)
|
||||
{
|
||||
if (size % align != 0)
|
||||
{
|
||||
size += align - (size % align);
|
||||
}
|
||||
type_offset = size;
|
||||
/* Make room to copy the arg_types */
|
||||
size += sizeof(ffi_type *) * numargs;
|
||||
if (size % align != 0)
|
||||
{
|
||||
size += align - (size % align);
|
||||
}
|
||||
offset = size;
|
||||
size += numargs * sizeof(void*);
|
||||
if (size % align != 0)
|
||||
{
|
||||
size += (align - (size % align));
|
||||
}
|
||||
for (i = 0; i < numargs; i++)
|
||||
{
|
||||
if (arg_types[i]->elements)
|
||||
size += cifframe_guess_struct_size(arg_types[i]);
|
||||
else
|
||||
size += arg_types[i]->size;
|
||||
|
||||
if (size % align != 0)
|
||||
{
|
||||
size += (align - size % align);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = [NSMutableData dataWithCapacity: size];
|
||||
[result setLength: size];
|
||||
cframe = buf = [result mutableBytes];
|
||||
|
||||
if (cframe)
|
||||
{
|
||||
cframe->nargs = numargs;
|
||||
cframe->arg_types = buf + type_offset;
|
||||
memcpy(cframe->arg_types, arg_types, sizeof(ffi_type *) * numargs);
|
||||
cframe->values = buf + offset;
|
||||
|
||||
if (ffi_prep_cif (&cframe->cif, FFI_DEFAULT_ABI, numargs,
|
||||
rtype, cframe->arg_types) != FFI_OK)
|
||||
{
|
||||
cframe = NULL;
|
||||
result = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set values locations. This must be done after ffi_prep_cif so
|
||||
that any structure sizes get calculated first. */
|
||||
offset += numargs * sizeof(void*);
|
||||
if (offset % align != 0)
|
||||
{
|
||||
offset += align - (offset % align);
|
||||
}
|
||||
for (i = 0; i < numargs; i++)
|
||||
{
|
||||
cframe->values[i] = buf + offset;
|
||||
|
||||
offset += arg_types[i]->size;
|
||||
|
||||
if (offset % align != 0)
|
||||
{
|
||||
offset += (align - offset % align);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size)
|
||||
{
|
||||
if (index < 0 || index >= cframe->nargs)
|
||||
return;
|
||||
memcpy(cframe->values[index], buffer, size);
|
||||
}
|
||||
|
||||
void
|
||||
cifframe_get_arg(cifframe_t *cframe, int index, void *buffer, int size)
|
||||
{
|
||||
if (index < 0 || index >= cframe->nargs)
|
||||
return;
|
||||
memcpy(buffer, cframe->values[index], size);
|
||||
}
|
||||
|
||||
void *
|
||||
cifframe_arg_addr(cifframe_t *cframe, int index)
|
||||
{
|
||||
if (index < 0 || index >= cframe->nargs)
|
||||
return NULL;
|
||||
return cframe->values[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the ffi_type for this type
|
||||
*/
|
||||
ffi_type *
|
||||
cifframe_type(const char *typePtr, const char **advance)
|
||||
{
|
||||
static ffi_type stypeNSPoint = { 0 };
|
||||
static ffi_type stypeNSRange = { 0 };
|
||||
static ffi_type stypeNSRect = { 0 };
|
||||
static ffi_type stypeNSSize = { 0 };
|
||||
const char *type;
|
||||
ffi_type *ftype = 0;
|
||||
|
||||
typePtr = objc_skip_type_qualifiers (typePtr);
|
||||
type = typePtr;
|
||||
|
||||
/*
|
||||
* Scan for size and alignment information.
|
||||
*/
|
||||
switch (*typePtr++)
|
||||
{
|
||||
case _C_ID: ftype = &ffi_type_pointer;
|
||||
break;
|
||||
case _C_CLASS: ftype = &ffi_type_pointer;
|
||||
break;
|
||||
case _C_SEL: ftype = &ffi_type_pointer;
|
||||
break;
|
||||
case _C_CHR: ftype = &ffi_type_schar;
|
||||
break;
|
||||
case _C_UCHR: ftype = &ffi_type_uchar;
|
||||
break;
|
||||
case _C_SHT: ftype = &gsffi_type_sshort;
|
||||
break;
|
||||
case _C_USHT: ftype = &gsffi_type_ushort;
|
||||
break;
|
||||
case _C_INT: ftype = &gsffi_type_sint;
|
||||
break;
|
||||
case _C_UINT: ftype = &gsffi_type_uint;
|
||||
break;
|
||||
case _C_LNG: ftype = &gsffi_type_slong;
|
||||
break;
|
||||
case _C_ULNG: ftype = &gsffi_type_ulong;
|
||||
break;
|
||||
#ifdef _C_LNG_LNG
|
||||
case _C_LNG_LNG: ftype = &gsffi_type_slong_long;
|
||||
break;
|
||||
case _C_ULNG_LNG: ftype = &gsffi_type_ulong_long;
|
||||
break;
|
||||
#endif
|
||||
case _C_FLT: ftype = &ffi_type_float;
|
||||
break;
|
||||
case _C_DBL: ftype = &ffi_type_double;
|
||||
break;
|
||||
case _C_PTR:
|
||||
ftype = &ffi_type_pointer;
|
||||
if (*typePtr == '?')
|
||||
{
|
||||
typePtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *adv;
|
||||
cifframe_type(typePtr, &adv);
|
||||
typePtr = adv;
|
||||
}
|
||||
break;
|
||||
|
||||
case _C_ATOM:
|
||||
case _C_CHARPTR:
|
||||
ftype = &ffi_type_pointer;
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
const char *adv;
|
||||
ftype = &ffi_type_pointer;
|
||||
|
||||
while (isdigit(*typePtr))
|
||||
{
|
||||
typePtr++;
|
||||
}
|
||||
cifframe_type(typePtr, &adv);
|
||||
typePtr = adv;
|
||||
typePtr++; /* Skip end-of-array */
|
||||
}
|
||||
break;
|
||||
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
int types, maxtypes, size;
|
||||
ffi_type *local;
|
||||
const char *adv;
|
||||
unsigned align = __alignof(double);
|
||||
|
||||
/* Standard structures can be handled using cached type information.
|
||||
Since the switch statement has already skipped the _C_STRUCT_B
|
||||
character, we must use typePtr-1 below to successfully match the
|
||||
type encoding with one of the standard type encodings. The same
|
||||
holds for skipping past the whole structure type's encoding with
|
||||
objc_skip_typespec.
|
||||
*/
|
||||
if (GSSelectorTypesMatch(typePtr - 1, @encode(NSRange)))
|
||||
{
|
||||
ftype = &stypeNSRange;
|
||||
if (ftype->type == 0)
|
||||
{
|
||||
static ffi_type *elems[3];
|
||||
|
||||
if (*@encode(NSUInteger) == _C_ULNG)
|
||||
{
|
||||
elems[0] = &gsffi_type_ulong;
|
||||
}
|
||||
#ifdef _C_LNG_LNG
|
||||
else if (*@encode(NSUInteger) == _C_ULNG_LNG)
|
||||
{
|
||||
elems[0] = &gsffi_type_ulong_long;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
elems[0] = &gsffi_type_uint;
|
||||
}
|
||||
elems[1] = elems[0];
|
||||
elems[2] = 0;
|
||||
ftype->elements = elems;
|
||||
ftype->type = FFI_TYPE_STRUCT;
|
||||
}
|
||||
typePtr = objc_skip_typespec (typePtr - 1);
|
||||
break;
|
||||
}
|
||||
else if (GSSelectorTypesMatch(typePtr - 1, @encode(NSPoint)))
|
||||
{
|
||||
ftype = &stypeNSPoint;
|
||||
if (ftype->type == 0)
|
||||
{
|
||||
static ffi_type *elems[3];
|
||||
|
||||
if (*@encode(CGFloat) == _C_DBL)
|
||||
{
|
||||
elems[0] = &ffi_type_double;
|
||||
}
|
||||
else
|
||||
{
|
||||
elems[0] = &ffi_type_float;
|
||||
}
|
||||
elems[1] = elems[0];
|
||||
elems[2] = 0;
|
||||
ftype->elements = elems;
|
||||
ftype->type = FFI_TYPE_STRUCT;
|
||||
}
|
||||
typePtr = objc_skip_typespec (typePtr - 1);
|
||||
break;
|
||||
}
|
||||
else if (GSSelectorTypesMatch(typePtr - 1, @encode(NSSize)))
|
||||
{
|
||||
ftype = &stypeNSSize;
|
||||
if (ftype->type == 0)
|
||||
{
|
||||
static ffi_type *elems[3];
|
||||
|
||||
if (*@encode(CGFloat) == _C_DBL)
|
||||
{
|
||||
elems[0] = &ffi_type_double;
|
||||
}
|
||||
else
|
||||
{
|
||||
elems[0] = &ffi_type_float;
|
||||
}
|
||||
elems[1] = elems[0];
|
||||
elems[2] = 0;
|
||||
ftype->elements = elems;
|
||||
ftype->type = FFI_TYPE_STRUCT;
|
||||
}
|
||||
typePtr = objc_skip_typespec (typePtr - 1);
|
||||
break;
|
||||
}
|
||||
else if (GSSelectorTypesMatch(typePtr - 1, @encode(NSRect)))
|
||||
{
|
||||
ftype = &stypeNSRect;
|
||||
if (ftype->type == 0)
|
||||
{
|
||||
static ffi_type *elems[3];
|
||||
|
||||
/* An NSRect is an NSPoint and an NSSize, but those
|
||||
* two structures are actually identical.
|
||||
*/
|
||||
elems[0] = cifframe_type(@encode(NSSize), NULL);
|
||||
elems[1] = cifframe_type(@encode(NSPoint), NULL);
|
||||
elems[2] = 0;
|
||||
ftype->elements = elems;
|
||||
ftype->type = FFI_TYPE_STRUCT;
|
||||
}
|
||||
typePtr = objc_skip_typespec (typePtr - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip "<name>=" stuff.
|
||||
*/
|
||||
while (*typePtr != _C_STRUCT_E)
|
||||
{
|
||||
if (*typePtr++ == '=')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
types = 0;
|
||||
maxtypes = 4;
|
||||
size = sizeof(ffi_type);
|
||||
if (size % align != 0)
|
||||
{
|
||||
size += (align - (size % align));
|
||||
}
|
||||
ftype = malloc(size + (maxtypes+1)*sizeof(ffi_type));
|
||||
ftype->size = 0;
|
||||
ftype->alignment = 0;
|
||||
ftype->type = FFI_TYPE_STRUCT;
|
||||
ftype->elements = (void*)ftype + size;
|
||||
/*
|
||||
* Continue accumulating structure size.
|
||||
*/
|
||||
while (*typePtr != _C_STRUCT_E)
|
||||
{
|
||||
local = cifframe_type(typePtr, &adv);
|
||||
typePtr = adv;
|
||||
// NSCAssert(typePtr, @"End of signature while parsing");
|
||||
ftype->elements[types++] = local;
|
||||
if (types >= maxtypes)
|
||||
{
|
||||
maxtypes *=2;
|
||||
ftype = realloc(ftype,
|
||||
size + (maxtypes+1)*sizeof(ffi_type));
|
||||
ftype->elements = (void*)ftype + size;
|
||||
}
|
||||
}
|
||||
ftype->elements[types] = NULL;
|
||||
typePtr++; /* Skip end-of-struct */
|
||||
}
|
||||
break;
|
||||
|
||||
case _C_UNION_B:
|
||||
{
|
||||
const char *adv;
|
||||
int max_align = 0;
|
||||
|
||||
/*
|
||||
* Skip "<name>=" stuff.
|
||||
*/
|
||||
while (*typePtr != _C_UNION_E)
|
||||
{
|
||||
if (*typePtr++ == '=')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
ftype = NULL;
|
||||
while (*typePtr != _C_UNION_E)
|
||||
{
|
||||
ffi_type *local;
|
||||
int align = objc_alignof_type(typePtr);
|
||||
local = cifframe_type(typePtr, &adv);
|
||||
typePtr = adv;
|
||||
// NSCAssert(typePtr, @"End of signature while parsing");
|
||||
if (align > max_align)
|
||||
{
|
||||
if (ftype && ftype->type == FFI_TYPE_STRUCT
|
||||
&& ftype != &stypeNSPoint
|
||||
&& ftype != &stypeNSRange
|
||||
&& ftype != &stypeNSRect
|
||||
&& ftype != &stypeNSSize)
|
||||
{
|
||||
free(ftype);
|
||||
}
|
||||
ftype = local;
|
||||
max_align = align;
|
||||
}
|
||||
}
|
||||
typePtr++; /* Skip end-of-union */
|
||||
}
|
||||
break;
|
||||
|
||||
case _C_VOID: ftype = &ffi_type_void;
|
||||
break;
|
||||
#if __GNUC__ > 2 && defined(_C_BOOL)
|
||||
case _C_BOOL: ftype = &ffi_type_uchar;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ftype = &ffi_type_void;
|
||||
// NSCAssert(0, @"Unknown type in sig");
|
||||
}
|
||||
|
||||
/* Skip past any offset information, if there is any */
|
||||
if (*type != _C_PTR || *type == '?')
|
||||
{
|
||||
if (*typePtr == '+')
|
||||
typePtr++;
|
||||
if (*typePtr == '-')
|
||||
typePtr++;
|
||||
while (isdigit(*typePtr))
|
||||
typePtr++;
|
||||
}
|
||||
if (advance)
|
||||
*advance = typePtr;
|
||||
|
||||
return ftype;
|
||||
}
|
||||
|
||||
GSCodeBuffer*
|
||||
cifframe_closure (NSMethodSignature *sig, void (*cb)())
|
||||
{
|
||||
NSMutableData *frame;
|
||||
cifframe_t *cframe;
|
||||
ffi_closure *cclosure;
|
||||
void *executable;
|
||||
GSCodeBuffer *memory;
|
||||
|
||||
/* Construct the frame (stored in an NSMutableDate object) and sety it
|
||||
* in a new closure.
|
||||
*/
|
||||
frame = cifframe_from_signature(sig);
|
||||
cframe = [frame mutableBytes];
|
||||
memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)];
|
||||
[memory setFrame: frame];
|
||||
cclosure = [memory buffer];
|
||||
executable = [memory executable];
|
||||
if (cframe == NULL || cclosure == NULL)
|
||||
{
|
||||
[NSException raise: NSMallocException format: @"Allocating closure"];
|
||||
}
|
||||
#if HAVE_FFI_PREP_CLOSURE_LOC
|
||||
if (ffi_prep_closure_loc(cclosure, &(cframe->cif),
|
||||
cb, frame, executable) != FFI_OK)
|
||||
{
|
||||
[NSException raise: NSGenericException format: @"Preping closure"];
|
||||
}
|
||||
#else
|
||||
executable = (void*)cclosure;
|
||||
if (ffi_prep_closure(cclosure, &(cframe->cif),
|
||||
cb, frame) != FFI_OK)
|
||||
{
|
||||
[NSException raise: NSGenericException format: @"Preping closure"];
|
||||
}
|
||||
#endif
|
||||
[memory protect];
|
||||
return memory;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* Functions for handling sending and receiving messages accross a
|
||||
connection
|
||||
*/
|
||||
|
||||
/* Some return types actually get coded differently. We need to convert
|
||||
back to the expected return type */
|
||||
BOOL
|
||||
cifframe_decode_arg (const char *type, void* buffer)
|
||||
{
|
||||
type = objc_skip_type_qualifiers (type);
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHR:
|
||||
*(signed char*)buffer = (signed char)(*((ffi_sarg *)buffer));
|
||||
break;
|
||||
case _C_UCHR:
|
||||
*(unsigned char*)buffer = (unsigned char)(*((ffi_arg *)buffer));
|
||||
break;
|
||||
case _C_SHT:
|
||||
*(signed short*)buffer = (signed short)(*((ffi_sarg *)buffer));
|
||||
break;
|
||||
case _C_USHT:
|
||||
*(unsigned short*)buffer = (unsigned short)(*((ffi_arg *)buffer));
|
||||
break;
|
||||
case _C_INT:
|
||||
*(signed int*)buffer = (signed int)(*((ffi_sarg *)buffer));
|
||||
break;
|
||||
case _C_UINT:
|
||||
*(unsigned int*)buffer = (unsigned int)(*((ffi_arg *)buffer));
|
||||
break;
|
||||
case _C_LNG:
|
||||
if (sizeof(signed long) < sizeof(ffi_sarg))
|
||||
*(signed long*)buffer = (signed long)(*((ffi_sarg *)buffer));
|
||||
break;
|
||||
case _C_ULNG:
|
||||
if (sizeof(unsigned long) < sizeof(ffi_arg))
|
||||
*(unsigned long*)buffer = (unsigned long)(*((ffi_arg *)buffer));
|
||||
break;
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
BOOL
|
||||
cifframe_encode_arg (const char *type, void* buffer)
|
||||
{
|
||||
type = objc_skip_type_qualifiers (type);
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHR:
|
||||
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed char *)buffer));
|
||||
break;
|
||||
case _C_UCHR:
|
||||
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned char *)buffer));
|
||||
break;
|
||||
case _C_SHT:
|
||||
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed short *)buffer));
|
||||
break;
|
||||
case _C_USHT:
|
||||
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned short *)buffer));
|
||||
break;
|
||||
case _C_INT:
|
||||
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed int *)buffer));
|
||||
break;
|
||||
case _C_UINT:
|
||||
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned int *)buffer));
|
||||
break;
|
||||
case _C_LNG:
|
||||
if (sizeof(signed long) < sizeof(ffi_sarg))
|
||||
*(ffi_sarg *)buffer = (ffi_sarg)(*((signed long *)buffer));
|
||||
break;
|
||||
case _C_ULNG:
|
||||
if (sizeof(unsigned long) < sizeof(ffi_arg))
|
||||
*(ffi_arg *)buffer = (ffi_arg)(*((unsigned int *)buffer));
|
||||
break;
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
8
debug.h
8
debug.h
@ -1,8 +0,0 @@
|
||||
#ifndef CF_DEBUG_H_
|
||||
#define CF_DEBUG_H_
|
||||
|
||||
#define DEBUG_BREAK() __asm__("int3")
|
||||
#define DEBUG_LOG(fmt, ...)
|
||||
|
||||
#endif
|
||||
|
1020
encoding.c
1020
encoding.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user