LIPO = /usr/bin/lipo
ifeq "$(PLATFORM)" "Darwin"
-WARNING_FLAGS = -Wmost -Wno-precomp -Wno-four-char-constants
+WARNING_FLAGS = -Wmost -Wno-four-char-constants
endif
ARCH_LIST=
ifeq "$(ORDERFILE)" ""
-ORDERFILE = $(wildcard /usr/local/lib/OrderFiles/libobjc.order)
+ORDERFILE = $(SRCROOT)/libobjc.order
endif
ifneq "$(ORDERFILE)" ""
ORDER = -sectorder __TEXT __text $(ORDERFILE)
USER = unknown
endif
-CFLAGS = -g -fno-common -fobjc-exceptions -pipe $(PLATFORM_CFLAGS) $(WARNING_FLAGS) -I$(SYMROOT) -I. -I$(SYMROOT)/ProjectHeaders
+CFLAGS = -g -fno-common -fobjc-exceptions -fdollars-in-identifiers -pipe $(PLATFORM_CFLAGS) $(WARNING_FLAGS) -I$(SYMROOT) -I. -I$(SYMROOT)/ProjectHeaders
LDFLAGS =
LIBRARY_EXT = .dylib
OTHER_SOURCES += runtime/Messengers.subproj/objc-msg-stub-ppc.s runtime/Messengers.subproj/objc-msg-stub-i386.s
# project root
-OTHER_SOURCES += Makefile APPLE_LICENSE objc-exports-i386 objc-exports-ppc
+OTHER_SOURCES += Makefile APPLE_LICENSE objc-exports libobjc.order
OBJECTS = $(addprefix $(OBJROOT)/, $(addsuffix .o, $(basename $(SOURCES) ) ) )
OBJECTS_OPTIMIZED = $(OBJECTS:.o=.opt.o)
$3 ; \
$(SILENT) $(CC) $2 \
-arch $A \
- -Wl,-exported_symbols_list,$(SRCROOT)/objc-exports-$(A) \
+ -Wl,-exported_symbols_list,$(SRCROOT)/objc-exports \
$(ORDER) \
-sectcreate __DATA __commpage $(OBJROOT)/runtime/objc-rtp-sym.$A.o \
-install_name /$(INSTALLDIR)/libobjc$1.$(VERSION_NAME)$(LIBRARY_EXT) \
--- /dev/null
+__objc_notify_images
+___i686.get_pc_thunk.bx
+_map_images
+_getsegbynamefromheader
+___i686.get_pc_thunk.cx
+_verify_gc_readiness
+_objc_msgSend
+__class_lookupMethodAndLoadCache
+_class_initialize
+_objc_getClass
+_look_up_class
+_NXHashGet
+_classHash
+_classIsEqual
+__class_changeInfo
+__fetchInitializingClassList
+__cache_getMethod
+_fixupSelectorsInMethodList
+__malloc_internal
+__objc_internal_zone
+_sel_lock
+_sel_registerNameNoLock
+___sel_registerName
+__objc_search_builtins
+___objc_sel_set_get
+___objc_sel_set_findBuckets
+___objc_sel_set_add
+_sel_unlock
+__cache_fill
+__cache_getImp
+__cache_create
+__cache_malloc
+__calloc_internal
+_objc_assign_global
+_objc_collecting_enabled
+__internal_class_createInstanceFromZone
+_object_cxxConstructFromClass
+_object_getClassName
+_objc_msgSendSuper
+_objc_assign_ivar
+dyld_stub_binding_helper
+__cache_collect_free
+_sel_registerName
+__internal_object_dispose
+_object_cxxDestruct
+_object_cxxDestructFromClass
+__objc_getFreedObjectClass
+_objc_exception_try_enter
+_objc_exception_try_exit
+__strdup_internal
+_class_respondsToMethod
+__cache_addForwardEntry
+_objc_assign_strongCast
+_objc_msgSend_stret
+_objc_msgSend_fpret
+_class_getInstanceMethod
+_objc_memmove_collectable
+-[Protocol descriptionForInstanceMethod:]
+_class_nextMethodList
+_objc_getOrigClass
+_NXMapGet
+__mapStrHash
+__free_internal
+_NXUniqueString
+_NXCreateHashTable
+_NXCreateHashTableFromZone
+_hashPrototype
+_isEqualPrototype
+_NXHashInsert
+__NXHashRehashToCapacity
+_freeBuckets
+_NXNoEffectFree
+_NXStrHash
+_NXStrIsEqual
+_class_poseAs
+__objc_addOrigClass
+__mapStrIsEqual
+_NXMapInsert
+_objc_getClasses
+_NXHashRemove
+__mapPtrHash
+_NXInitHashState
+_NXNextHashState
+__objc_headerStart
+__getObjcClassRefs
+_sel_getName
+_object_setInstanceVariable
+_class_getInstanceVariable
+_objc_setMultithreaded
+-[Object self]
+__objc_defaultClassHandler
+_class_lookupMethod
+__internal_object_copyFromZone
+__objc_msgForward
+_objc_msgSendv
+_objc_loadModule
+__getObjcModules
+__getObjcImageInfo
+__getImageSlide
+__NXHashCapacity
+_lookupNamedMethodInMethodList
+_log2
+_resolve_categories_for_class
+_connect_class
+_class_is_connected
+_NXHashMember
+_really_connect_class
+_NXCountHashTable
+_NXFreeHashTable
+__objc_fixup_selector_refs
+__getObjcMessageRefs
+__getObjcProtocols
++[Protocol _fixup:numElements:]
+-[Protocol conformsTo:]
+__objc_insertMethods
+__objc_flush_caches
+_flush_caches
+_objc_getClassList
+__realloc_internal
+__cache_flush
+__class_setInfo
+__class_clearInfo
+_map_method_descs
+_objc_msgSendSuper_stret
+_cache_region_calloc
+_objc_msgSendv_stret
+_objc_sync_enter
+_id2data
+_objc_sync_exit
+__mapPtrIsEqual
+__objc_pthread_destroyspecific
+__destroyInitializingClassList
+__objcInit
+_objc_exception_extract
+_objc_exception_match
--- /dev/null
+# Functions and variables explicitly exported from ObjC.
+# GrP 2002-2-4
+# Note that some commonly used functions are *not* listed in the
+# ObjC headers (e.g. objc_flush_caches())
+# List.h
+.objc_class_name_List
+# objc-class.h
+_object_setInstanceVariable
+_object_getInstanceVariable
+_class_createInstance
+_class_createInstanceFromZone
+_class_setVersion
+_class_getVersion
+_class_getInstanceVariable
+_class_getInstanceMethod
+_class_getClassMethod
+_class_addMethods
+_class_removeMethods
+_class_poseAs
+_method_getNumberOfArguments
+_method_getSizeOfArguments
+_method_getArgumentInfo
+_class_nextMethodList
+# objc-auto.h - actually, everything possible for now
+_objc_collect
+_objc_collect_generation
+_objc_numberAllocated
+_objc_isAuto
+_objc_collecting_enabled
+_objc_allocate_object
+_objc_assign_strongCast
+_objc_assign_global
+_objc_assign_ivar
+_objc_assign_strongCast_generic
+_objc_assign_global_generic
+_objc_assign_ivar_generic
+_objc_assign_strongCast_CF
+_objc_assign_ivar_address_CF
+_objc_collect_init
+_objc_is_finalized
+_objc_memmove_collectable
+_objc_collect_if_needed
+# objc-exception.h
+_objc_exception_throw
+_objc_exception_try_enter
+_objc_exception_try_exit
+_objc_exception_extract
+_objc_exception_match
+_objc_exception_get_functions
+_objc_exception_set_functions
+# objc-sync.h
+_objc_sync_enter
+_objc_sync_exit
+_objc_sync_wait
+_objc_sync_notify
+_objc_sync_notifyAll
+# objc-load.h
+_objc_loadModules
+_objc_loadModule
+_objc_unloadModules
+# objc-runtime.h
+_objc_getClass
+_objc_getMetaClass
+_objc_msgSend
+# non-nil entry points disabled for now
+# _objc_msgSendNonNil
+_objc_msgSend_fpret
+_objc_msgSend_stret
+# _objc_msgSendNonNil_stret
+_objc_msgSendSuper
+_objc_msgSendSuper_stret
+_objc_msgSendv
+_objc_msgSendv_fpret
+_objc_msgSendv_stret
+_objc_getClassList
+_objc_getClasses
+_objc_lookUpClass
+_objc_getRequiredClass
+_objc_addClass
+_objc_setClassHandler
+_objc_setMultithreaded
+__alloc
+__copy
+__realloc
+__dealloc
+__zoneAlloc
+__zoneRealloc
+__zoneCopy
+__error
+# objc.h
+_sel_isMapped
+_sel_getName
+_sel_getUid
+_sel_registerName
+_object_getClassName
+_object_getIndexedIvars
+# Object.h
+.objc_class_name_Object
+_object_dispose
+_object_copy
+_object_copyFromZone
+_object_realloc
+_object_reallocFromZone
+# Protocol.h
+.objc_class_name_Protocol
+# error.h
+# everything inside is declared but no longer defined?!
+# hashtable2.h
+_NXCreateHashTableFromZone
+_NXCreateHashTable
+_NXFreeHashTable
+_NXEmptyHashTable
+_NXResetHashTable
+_NXCompareHashTables
+_NXCopyHashTable
+_NXCountHashTable
+_NXHashMember
+_NXHashGet
+_NXHashInsert
+_NXHashInsertIfAbsent
+_NXHashRemove
+_NXInitHashState
+_NXNextHashState
+_NXPtrHash
+_NXStrHash
+_NXPtrIsEqual
+_NXStrIsEqual
+_NXNoEffectFree
+_NXReallyFree
+_NXPtrPrototype
+_NXStrPrototype
+_NXPtrStructKeyPrototype
+_NXStrStructKeyPrototype
+_NXUniqueString
+_NXUniqueStringWithLength
+_NXUniqueStringNoCopy
+_NXCopyStringBuffer
+_NXCopyStringBufferFromZone
+# maptable.h
+_NXCreateMapTableFromZone
+_NXCreateMapTable
+_NXFreeMapTable
+_NXResetMapTable
+_NXCompareMapTables
+_NXCountMapTable
+_NXMapMember
+_NXMapGet
+_NXMapInsert
+_NXMapRemove
+_NXInitMapState
+_NXNextMapState
+_NXPtrValueMapPrototype
+_NXStrValueMapPrototype
+_NXObjectMapPrototype
+#
+# Functions that aren't in the headers but are used or are useful.
+#
+# sudo find / -xdev -type f -perm -0111 \! -name "libobjc*dylib" -print -exec nm -u {} \; > /tmp/all-used-symbols
+# (repeat with any other disks you want checked, appending to the same file)
+# nm /usr/lib/libobjc.dylib | awk '$2 ~ /^[ADST]$/' | colrm 1 11 | sort -u > /tmp/objc-exports
+# (note that you need an unstripped, un-nmedited libobjc.dylib)
+# grep -f /tmp/objc-exports /tmp/all-used-symbols | sort -u > /tmp/used-objc-symbols
+# grep -v -f /tmp/used-objc-symbols /tmp/objc-exports | sort -u > /tmp/unused-objc-symbols
+#
+__class_printDuplicateCacheEntries
+__class_printMethodCaches
+__class_printMethodCacheStatistics
+__objc_create_zone
+__objc_error
+__objc_flush_caches
+__objc_msgForward
+__objc_resolve_categories_for_class
+__objc_setClassLoader
+__objc_setNilReceiver
+__objc_getNilReceiver
+__objcInit
+_class_lookupMethod
+_class_respondsToMethod
+_instrumentObjcMessageSends
+_objc_getOrigClass
+# magic, or garbage?
+__dummy
+_do_not_remove_this_dummy_function
+# used by debugging tools like heap
+__objc_debug_class_hash
+# used by Foundation's NSAutoreleaseFreedObjectCheckEnabled
+__objc_getFreedObjectClass
+++ /dev/null
-# Functions and variables explicitly exported from ObjC.
-# GrP 2002-2-4
-# Note that some commonly used functions are *not* listed in the
-# ObjC headers (e.g. objc_flush_caches())
-# List.h
-.objc_class_name_List
-# objc-class.h
-_object_setInstanceVariable
-_object_getInstanceVariable
-_class_createInstance
-_class_createInstanceFromZone
-_class_setVersion
-_class_getVersion
-_class_getInstanceVariable
-_class_getInstanceMethod
-_class_getClassMethod
-_class_addMethods
-_class_removeMethods
-_class_poseAs
-_method_getNumberOfArguments
-_method_getSizeOfArguments
-_method_getArgumentInfo
-_class_nextMethodList
-# objc-auto.h - actually, everything possible for now
-_objc_collect
-_objc_collect_generation
-_objc_numberAllocated
-_objc_isAuto
-_objc_collecting_enabled
-_objc_allocate_object
-_objc_assign_strongCast
-_objc_assign_global
-_objc_assign_ivar
-_objc_assign_strongCast_generic
-_objc_assign_global_generic
-_objc_assign_ivar_generic
-_objc_assign_strongCast_CF
-_objc_assign_ivar_address_CF
-_objc_collect_init
-_objc_is_finalized
-_objc_memmove_collectable
-_objc_collect_if_needed
-# objc-exception.h
-_objc_exception_throw
-_objc_exception_try_enter
-_objc_exception_try_exit
-_objc_exception_extract
-_objc_exception_match
-_objc_exception_get_functions
-_objc_exception_set_functions
-# objc-sync.h
-_objc_sync_enter
-_objc_sync_exit
-_objc_sync_wait
-_objc_sync_notify
-_objc_sync_notifyAll
-# objc-load.h
-_objc_loadModules
-_objc_loadModule
-_objc_unloadModules
-# objc-runtime.h
-_objc_getClass
-_objc_getMetaClass
-_objc_msgSend
-# non-nil entry points disabled for now
-# _objc_msgSendNonNil
-_objc_msgSend_fpret
-_objc_msgSend_stret
-# _objc_msgSendNonNil_stret
-_objc_msgSendSuper
-_objc_msgSendSuper_stret
-_objc_msgSendv
-_objc_msgSendv_fpret
-_objc_msgSendv_stret
-_objc_getClassList
-_objc_getClasses
-_objc_lookUpClass
-_objc_getRequiredClass
-_objc_addClass
-_objc_setClassHandler
-_objc_setMultithreaded
-__alloc
-__copy
-__realloc
-__dealloc
-__zoneAlloc
-__zoneRealloc
-__zoneCopy
-__error
-# objc.h
-_sel_isMapped
-_sel_getName
-_sel_getUid
-_sel_registerName
-_object_getClassName
-_object_getIndexedIvars
-# Object.h
-.objc_class_name_Object
-_object_dispose
-_object_copy
-_object_copyFromZone
-_object_realloc
-_object_reallocFromZone
-# Protocol.h
-.objc_class_name_Protocol
-# error.h
-# everything inside is declared but no longer defined?!
-# hashtable2.h
-_NXCreateHashTableFromZone
-_NXCreateHashTable
-_NXFreeHashTable
-_NXEmptyHashTable
-_NXResetHashTable
-_NXCompareHashTables
-_NXCopyHashTable
-_NXCountHashTable
-_NXHashMember
-_NXHashGet
-_NXHashInsert
-_NXHashInsertIfAbsent
-_NXHashRemove
-_NXInitHashState
-_NXNextHashState
-_NXPtrHash
-_NXStrHash
-_NXPtrIsEqual
-_NXStrIsEqual
-_NXNoEffectFree
-_NXReallyFree
-_NXPtrPrototype
-_NXStrPrototype
-_NXPtrStructKeyPrototype
-_NXStrStructKeyPrototype
-_NXUniqueString
-_NXUniqueStringWithLength
-_NXUniqueStringNoCopy
-_NXCopyStringBuffer
-_NXCopyStringBufferFromZone
-# maptable.h
-_NXCreateMapTableFromZone
-_NXCreateMapTable
-_NXFreeMapTable
-_NXResetMapTable
-_NXCompareMapTables
-_NXCountMapTable
-_NXMapMember
-_NXMapGet
-_NXMapInsert
-_NXMapRemove
-_NXInitMapState
-_NXNextMapState
-_NXPtrValueMapPrototype
-_NXStrValueMapPrototype
-_NXObjectMapPrototype
-#
-# Functions that aren't in the headers but are used or are useful.
-#
-# sudo find / -xdev -type f -perm -0111 \! -name "libobjc*dylib" -print -exec nm -u {} \; > /tmp/all-used-symbols
-# (repeat with any other disks you want checked, appending to the same file)
-# nm /usr/lib/libobjc.dylib | awk '$2 ~ /^[ADST]$/' | colrm 1 11 | sort -u > /tmp/objc-exports
-# (note that you need an unstripped, un-nmedited libobjc.dylib)
-# grep -f /tmp/objc-exports /tmp/all-used-symbols | sort -u > /tmp/used-objc-symbols
-# grep -v -f /tmp/used-objc-symbols /tmp/objc-exports | sort -u > /tmp/unused-objc-symbols
-#
-__class_printDuplicateCacheEntries
-__class_printMethodCaches
-__class_printMethodCacheStatistics
-__objc_create_zone
-__objc_error
-__objc_flush_caches
-__objc_msgForward
-__objc_resolve_categories_for_class
-__objc_setClassLoader
-__objc_setNilReceiver
-__objc_getNilReceiver
-__objcInit
-_class_lookupMethod
-_class_respondsToMethod
-_instrumentObjcMessageSends
-_objc_getOrigClass
-# magic, or garbage?
-__dummy
-_do_not_remove_this_dummy_function
-# used by debugging tools like heap
-__objc_debug_class_hash
-# used by Foundation's NSAutoreleaseFreedObjectCheckEnabled
-__objc_getFreedObjectClass
+++ /dev/null
-# Functions and variables explicitly exported from ObjC.
-# GrP 2002-2-4
-# Note that some commonly used functions are *not* listed in the
-# ObjC headers (e.g. objc_flush_caches())
-# List.h
-.objc_class_name_List
-# objc-class.h
-_object_setInstanceVariable
-_object_getInstanceVariable
-_class_createInstance
-_class_createInstanceFromZone
-_class_setVersion
-_class_getVersion
-_class_getInstanceVariable
-_class_getInstanceMethod
-_class_getClassMethod
-_class_addMethods
-_class_removeMethods
-_class_poseAs
-_method_getNumberOfArguments
-_method_getSizeOfArguments
-_method_getArgumentInfo
-_class_nextMethodList
-# objc-auto.h - actually, everything possible for now
-_objc_collect
-_objc_collect_generation
-_objc_numberAllocated
-_objc_isAuto
-_objc_collecting_enabled
-_objc_allocate_object
-_objc_assign_strongCast
-_objc_assign_global
-_objc_assign_ivar
-_objc_assign_strongCast_generic
-_objc_assign_global_generic
-_objc_assign_ivar_generic
-_objc_assign_strongCast_CF
-_objc_assign_ivar_address_CF
-_objc_collect_init
-_objc_is_finalized
-_objc_memmove_collectable
-_objc_collect_if_needed
-# objc-exception.h
-_objc_exception_throw
-_objc_exception_try_enter
-_objc_exception_try_exit
-_objc_exception_extract
-_objc_exception_match
-_objc_exception_get_functions
-_objc_exception_set_functions
-# objc-sync.h
-_objc_sync_enter
-_objc_sync_exit
-_objc_sync_wait
-_objc_sync_notify
-_objc_sync_notifyAll
-# objc-load.h
-_objc_loadModules
-_objc_loadModule
-_objc_unloadModules
-# objc-runtime.h
-_objc_getClass
-_objc_getMetaClass
-_objc_msgSend
-# non-nil entry points disabled for now
-# _objc_msgSendNonNil
-_objc_msgSend_stret
-# _objc_msgSendNonNil_stret
-_objc_msgSendSuper
-_objc_msgSendSuper_stret
-_objc_msgSendv
-_objc_msgSendv_stret
-_objc_getClassList
-_objc_getClasses
-_objc_lookUpClass
-_objc_getRequiredClass
-_objc_addClass
-_objc_setClassHandler
-_objc_setMultithreaded
-__alloc
-__copy
-__realloc
-__dealloc
-__zoneAlloc
-__zoneRealloc
-__zoneCopy
-__error
-# objc.h
-_sel_isMapped
-_sel_getName
-_sel_getUid
-_sel_registerName
-_object_getClassName
-_object_getIndexedIvars
-# Object.h
-.objc_class_name_Object
-_object_dispose
-_object_copy
-_object_copyFromZone
-_object_realloc
-_object_reallocFromZone
-# Protocol.h
-.objc_class_name_Protocol
-# error.h
-# everything inside is declared but no longer defined?!
-# hashtable2.h
-_NXCreateHashTableFromZone
-_NXCreateHashTable
-_NXFreeHashTable
-_NXEmptyHashTable
-_NXResetHashTable
-_NXCompareHashTables
-_NXCopyHashTable
-_NXCountHashTable
-_NXHashMember
-_NXHashGet
-_NXHashInsert
-_NXHashInsertIfAbsent
-_NXHashRemove
-_NXInitHashState
-_NXNextHashState
-_NXPtrHash
-_NXStrHash
-_NXPtrIsEqual
-_NXStrIsEqual
-_NXNoEffectFree
-_NXReallyFree
-_NXPtrPrototype
-_NXStrPrototype
-_NXPtrStructKeyPrototype
-_NXStrStructKeyPrototype
-_NXUniqueString
-_NXUniqueStringWithLength
-_NXUniqueStringNoCopy
-_NXCopyStringBuffer
-_NXCopyStringBufferFromZone
-# maptable.h
-_NXCreateMapTableFromZone
-_NXCreateMapTable
-_NXFreeMapTable
-_NXResetMapTable
-_NXCompareMapTables
-_NXCountMapTable
-_NXMapMember
-_NXMapGet
-_NXMapInsert
-_NXMapRemove
-_NXInitMapState
-_NXNextMapState
-_NXPtrValueMapPrototype
-_NXStrValueMapPrototype
-_NXObjectMapPrototype
-#
-# Functions that aren't in the headers but are used or are useful.
-#
-# sudo find / -xdev -type f -perm -0111 \! -name "libobjc*dylib" -print -exec nm -u {} \; > /tmp/all-used-symbols
-# (repeat with any other disks you want checked, appending to the same file)
-# nm /usr/lib/libobjc.dylib | awk '$2 ~ /^[ADST]$/' | colrm 1 11 | sort -u > /tmp/objc-exports
-# (note that you need an unstripped, un-nmedited libobjc.dylib)
-# grep -f /tmp/objc-exports /tmp/all-used-symbols | sort -u > /tmp/used-objc-symbols
-# grep -v -f /tmp/used-objc-symbols /tmp/objc-exports | sort -u > /tmp/unused-objc-symbols
-#
-__class_printDuplicateCacheEntries
-__class_printMethodCaches
-__class_printMethodCacheStatistics
-__objc_create_zone
-__objc_error
-__objc_flush_caches
-__objc_msgForward
-__objc_resolve_categories_for_class
-__objc_setClassLoader
-__objc_setNilReceiver
-__objc_getNilReceiver
-__objcInit
-_class_lookupMethod
-_class_respondsToMethod
-_instrumentObjcMessageSends
-_objc_getOrigClass
-# magic, or garbage?
-__dummy
-_do_not_remove_this_dummy_function
-# used by debugging tools like heap
-__objc_debug_class_hash
-# used by Foundation's NSAutoreleaseFreedObjectCheckEnabled
-__objc_getFreedObjectClass
//////////////////////////////////////////////////////////////////////
//
-// CALL_MCOUNTER counterName
+// CALL_MCOUNTER
//
-// Allocate and maintain a counter for the call site.
+// Calls mcount() profiling routine. Must be called immediately on
+// function entry, before any prologue executes.
//
-// Takes: counterName - name of counter.
//////////////////////////////////////////////////////////////////////
.macro CALL_MCOUNTER
#ifdef PROFILE
+ // Current stack contents: ret
pushl %ebp
movl %esp,%ebp
- LOAD_STATIC_WORD %eax, $0, LOCAL_SYMBOL
+ subl $kEight,%esp
+ // Current stack contents: ret, ebp, pad, pad
CALL_EXTERN(mcount)
- .data
- .align 2
-$0:
- .long 0
- .text
movl %ebp,%esp
popl %ebp
#endif
********************************************************************/
ENTRY _objc_msgSend
- CALL_MCOUNTER LP0
+ CALL_MCOUNTER
movl self(%esp), %eax
call L_get_pc_thunk.edx // load new receiver
1: movl __objc_nilReceiver-1b(%edx),%eax
testl %eax, %eax // return nil if no new receiver
- je LMsgSendDone
+ je LMsgSendReturnZero
movl %eax, self(%esp) // send to new receiver
jmp LMsgSendReceiverOk
+LMsgSendReturnZero:
+ // %eax is already zero
+ movl $0,%edx
LMsgSendDone:
ret
********************************************************************/
ENTRY _objc_msgSendSuper
- CALL_MCOUNTER LP1
+ CALL_MCOUNTER
movl super(%esp), %eax
#else
pushl %ebp
movl %esp, %ebp
+ // stack is currently aligned assuming no extra arguments
movl (marg_list+4)(%ebp), %edx
addl $8, %edx // skip self & selector
movl (marg_size+4)(%ebp), %ecx
shrl $2, %ecx
je LMsgSendvArgsOK
- // %esp = %esp - (16 - ((numVariableArguments && 3) << 2))
+ // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
movl %ecx, %eax // 16-byte align stack
andl $3, %eax
shll $2, %eax
- neg %eax
- addl $16, %eax
- subl %eax, %esp
+ subl $16, %esp
+ addl %eax, %esp
LMsgSendvArgLoop:
decl %ecx
#endif
END_ENTRY _objc_msgSendv
-
/********************************************************************
*
* double objc_msgSend_fpret(id self, SEL _cmd,...);
********************************************************************/
ENTRY _objc_msgSend_fpret
+ CALL_MCOUNTER
movl self(%esp), %eax
********************************************************************/
ENTRY _objc_msgSend_stret
- CALL_MCOUNTER LP2
+ CALL_MCOUNTER
movl self_stret(%esp), %eax
// guaranteed non-nil entry point (disabled for now)
// .globl _objc_msgSendNonNil_stret
// _objc_msgSendNonNil_stret:
-// CALL_MCOUNTER LP3
+// CALL_MCOUNTER
// movl self_stret(%esp), %eax
// jmp LMsgSendStretReceiverOk
********************************************************************/
ENTRY _objc_msgSendSuper_stret
- CALL_MCOUNTER LP4
+ CALL_MCOUNTER
movl super_stret(%esp), %eax
#else
pushl %ebp
movl %esp, %ebp
+ subl $12, %esp // align stack assuming no extra arguments
movl (marg_list_stret+4)(%ebp), %edx
addl $8, %edx // skip self & selector
movl (marg_size_stret+4)(%ebp), %ecx
shrl $2, %ecx
jle LMsgSendvStretArgsOK
+ // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
movl %ecx, %eax // 16-byte align stack
andl $3, %eax
shll $2, %eax
- subl $12, %esp
+ subl $16, %esp
addl %eax, %esp
LMsgSendvStretArgLoop:
; DO NOT CHANGE THE PREVIOUS SIX INSTRUCTIONS - see note above
cmplwi r11,0 ; return nil if no new receiver
- beqlr
+ beq LMsgSendReturnZero
mr r3,r11 ; send to new receiver
lwz r12,ISA(r11) ; class = receiver->isa
b LMsgSendReceiverOk
+LMsgSendReturnZero:
+ li r3, 0
+ li r4, 0
+ lis r12, ha16(kRTAddress_zero)
+ lfd f1, lo16(kRTAddress_zero)(r12)
+ lfd f2, lo16(kRTAddress_zero)(r12)
+
; WARNING - This blr marks the end of the copy to the ObjC runtime pages and
; also marks the beginning of the cache miss code. Do not move
; around without checking the ObjC runtime pages initialization code.
LMsgSendExit:
END_ENTRY _objc_msgSend
+/********************************************************************
+ *
+ * double objc_msgSend_fpret(id self, SEL op, ...);
+ *
+ ********************************************************************/
+
+ ENTRY _objc_msgSend_fpret
+ b _objc_msgSend
+ END_ENTRY _objc_msgSend_fpret
/********************************************************************
* struct_type objc_msgSend_stret(id self,
lwz r11,lo16(__objc_nilReceiver-1b)(r11)
mtlr r0
- cmplwi r11,0 ; return nil if no new receiver
+ cmplwi r11,0 ; return if no new receiver
beqlr
mr r4,r11 ; send to new receiver
END_ENTRY _objc_msgSendv
+/********************************************************************
+ * double objc_msgSendv_fpret(id self, SEL op, unsigned arg_size,
+ * marg_list arg_frame);
+ ********************************************************************/
+
+ ENTRY _objc_msgSendv_fpret
+ b _objc_msgSendv
+ END_ENTRY _objc_msgSendv_fpret
/********************************************************************
* struct_type objc_msgSendv_stret(id self,
// Absolute address of data in the RTP area
// These count forwards from the lo end of the RTP area.
// These are not locked down and can be moved if necessary.
-#define kRTAddress_ignoredSelector OBJC_UINTPTR_T(kRTPagesHi-kRTPagesSize)
+#define kRTAddress_zero OBJC_UINTPTR_T(kRTPagesHi-kRTPagesSize) // 16 zero bytes
+#define kRTAddress_ignoredSelector OBJC_UINTPTR_T(kRTAddress_zero+16) // string "<ignored selector>"
-#define kIgnore kRTAddress_ignoredSelector // ppc 0xfffef000
+#define kIgnore kRTAddress_ignoredSelector // ppc 0xfffef010
/*********************************************************************
End of runtime page layout.
"objc_assign_strongCast", objc_assign_strongCast_gc, objc_assign_strongCast_non_gc);
// initialize data in ObjC runtime pages
+ memset((char *)kRTAddress_zero, 0, 16);
strcpy((char *)kIgnore, "<ignored selector>");
// re-protect the ObjC runtime pages for execution
/* Forwarding */
+/* Note that objc_msgSendv_stret() does not return a structure type,
+ * and should not be cast to do so. This is unlike objc_msgSend_stret()
+ * and objc_msgSendSuper_stret().
+ */
+
OBJC_EXPORT id objc_msgSendv(id self, SEL op, unsigned arg_size, marg_list arg_frame);
OBJC_EXPORT void objc_msgSendv_stret(void * stretAddr, id self, SEL op, unsigned arg_size, marg_list arg_frame);
+#ifdef __i386__
+OBJC_EXPORT double objc_msgSendv_fpret(id self, SEL op, unsigned arg_size, marg_list arg_frame);
+#endif
+
/*
getting all the classes in the application...
static void _objc_unmap_image(const headerType *mh);
static BOOL connect_class(struct objc_class *cls);
static void add_category_to_loadable_list(struct objc_category *cat);
-static vm_range_t get_shared_range(vm_address_t start, vm_address_t end);
-static void offer_shared_range(vm_address_t start, vm_address_t end);
-static void install_shared_range(vm_range_t remote, vm_address_t local);
-static void clear_shared_range_file_cache(void);
/***********************************************************************
return;
}
+
// Major loop - process all modules in the header
mods = hi->mod_ptr;
/***********************************************************************
* _objc_fixup_selector_refs. Register all of the selectors in each
* image, and fix them all up.
-*
-* If the image is a dylib (not a bundle or an executable), and contains
-* at least one full aligned page of selector refs, this function uses
-* the shared range functions to try to recycle already-written memory
-* from other processes.
**********************************************************************/
static void _objc_fixup_selector_refs (const header_info * hi)
{
aligned_start = round_page(local_sels);
aligned_end = trunc_page(local_sels + local_size);
- if (aligned_start >= aligned_end ||
- hi->mhdr->filetype == MH_BUNDLE ||
- hi->mhdr->filetype == MH_EXECUTE)
- {
- // Less than a page of sels, OR bundle or executable - fix in place
-
- map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size,
- hi->mhdr->filetype == MH_BUNDLE);
-
- if (PrintSharing) {
- _objc_inform("SHARING: NONE [%p..%p) (%d pages) for %s",
- local_sels, local_sels+local_size,
- (aligned_end > aligned_start ?
- (aligned_end-aligned_start) / vm_page_size : 0),
- _nameForHeader(hi->mhdr));
- }
- }
- else {
- // At least one page of sels - try to use sharing
- vm_range_t remote_range;
-
- if (PrintSharing) {
- _objc_inform("SHARING: looking for range [%p..%p) ...",
- aligned_start, aligned_end);
- }
-
- remote_range = get_shared_range(aligned_start, aligned_end);
-
- if (remote_range.address != 0) {
- // Sharing succeeded - fix using remote_range
- BOOL stomped;
-
- // local_sels..aligned_start (unshared)
- map_selrefs((SEL *)local_sels, (SEL *)local_sels,
- aligned_start - local_sels, NO);
- // aligned_start..aligned_end (shared)
- stomped =
- map_selrefs((SEL *)aligned_start, (SEL *)remote_range.address,
- aligned_end - aligned_start, NO);
- // aligned_end..local_sels+local_size (unshared)
- map_selrefs((SEL *)aligned_end, (SEL *)aligned_end,
- local_sels+local_size - aligned_end, NO);
-
- install_shared_range(remote_range, aligned_start);
-
- if (PrintSharing) {
- _objc_inform("SHARING: %s [%p..%p) (%d pages) for %s",
- stomped ? "TRIED" : "USING",
- local_sels, local_sels+local_size,
- (aligned_end-aligned_start) / vm_page_size,
- _nameForHeader(hi->mhdr));
- }
- }
- else {
- // Sharing failed, including first process -
- // fix in place and then offer to share
-
- map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size, NO);
-
- offer_shared_range(aligned_start, aligned_end);
-
- if (PrintSharing) {
- _objc_inform("SHARING: OFFER [%p..%p) (%d pages) for %s",
- local_sels, local_sels+local_size,
- (aligned_end-aligned_start) / vm_page_size,
- _nameForHeader(hi->mhdr));
- }
- }
- }
+ map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size,
+ hi->mhdr->filetype == MH_BUNDLE);
}
}
_objc_fixup_protocol_objects_for_image(hInfo);
}
- // Close any shared range file left open during selector uniquing
- clear_shared_range_file_cache();
-
firstTime = NO;
// Call pending +load methods.
}
-/**********************************************************************
- * Shared range support:
- *
- * Some libraries contain many pages worth of selector references.
- * In most processes, these libraries get loaded at the same addresses,
- * so the selectors are uniqued to the same values. To save memory,
- * the runtime tries to share these memory pages across processes.
- *
- * A file /tmp/objc_sharing_<arch>_<euid> records memory ranges and process
- * IDs. When a set of selector refs is to be uniqued, this file is checked
- * for a matching memory range being shared by another process. If
- * such a range is found:
- * 1. map the sharing process's memory somewhere into this address space
- * 2. read from the real selector refs and write into the mapped memory.
- * 3. vm_copy from the mapped memory to the real selector refs location
- * 4. deallocate the mapped memory
- *
- * The mapped memory is merely used as a guess. Correct execution is
- * guaranteed no matter what values the mapped memory actually contains.
- * If the mapped memory really matches the values needed in this process,
- * the mapped memory will be unchanged. If the mapped memory doesn't match,
- * or contains random values, it will be fixed up to the correct values.
- * The memory is shared whenever the guess happens to be correct.
- *
- * The file of shared ranges is imprecise. Processes may die leaving
- * their entries in the file. A PID may be recycled to some process that
- * does not use Objective-C. The sharing mechanism is robust in the face
- * of these failures. Bad shared memory is simply fixed up. No shared
- * memory means the selectors are fixed in place. If an entry in the
- * file is found to be unusable, the process that finds it will instead
- * offer to share its own memory, replacing the bad entry in the file.
- *
- * Individual entries in the file are written atomically, but the file is
- * otherwise unsynchronized. At worst, a sharing opportunity may be missed
- * because two new entries are written simultaneously in the same place.
- **********************************************************************/
-
-
-struct remote_range_t {
- vm_range_t range;
- pid_t pid;
-};
-
-
-// Cache for the last shared range file used, and its EUID.
-static pthread_mutex_t sharedRangeLock = PTHREAD_MUTEX_INITIALIZER;
-static uid_t sharedRangeEUID = 0;
-static FILE * sharedRangeFile = NULL;
-static BOOL sharedRangeFileInUse = NO;
-
-
-/**********************************************************************
-* open_shared_range_file
-* Open the shared range file "/tmp/objc_sharing_<arch>_<euid>" in
-* the given mode.
-* The returned file should be closed with close_shared_range_file().
-**********************************************************************/
-static FILE *open_shared_range_file(BOOL create)
-{
- const char arch[] =
-#if defined(__ppc__) || defined(ppc)
- "ppc";
-#elif defined(__ppc64__) || defined(ppc64)
- "ppc64";
-#elif defined(__i386__) || defined(i386)
- "i386";
-#else
-# error "unknown architecture"
-#endif
- char filename[18 + sizeof(arch) + 1 + 3*sizeof(uid_t) + 1];
- uid_t euid;
- FILE *file = NULL;
- int fd;
-
- // Never share when superuser
- euid = geteuid();
- if (euid == 0) {
- if (PrintSharing) {
- _objc_inform("SHARING: superuser never shares");
- }
- return NULL;
- }
-
- // Return cached file if it matches and it's not still being used
- pthread_mutex_lock(&sharedRangeLock);
- if (!sharedRangeFileInUse && euid == sharedRangeEUID) {
- file = sharedRangeFile;
- sharedRangeFileInUse = YES;
- pthread_mutex_unlock(&sharedRangeLock);
- rewind(file);
- return file;
- }
- pthread_mutex_unlock(&sharedRangeLock);
-
- // Open /tmp/objc_sharing_<euid>
- snprintf(filename,sizeof(filename), "/tmp/objc_sharing_%s_%u", arch, euid);
- fd = secure_open(filename, O_RDWR | (create ? O_CREAT : 0), euid);
- if (fd >= 0) {
- file = fdopen(fd, "r+");
- }
-
- if (file) {
- // Cache this file if there's no already-open file cached
- pthread_mutex_lock(&sharedRangeLock);
- if (!sharedRangeFileInUse) {
- sharedRangeFile = file;
- sharedRangeEUID = euid;
- sharedRangeFileInUse = YES;
- }
- pthread_mutex_unlock(&sharedRangeLock);
- }
- else {
- // open() or fdopen() failed
- if (PrintSharing) {
- _objc_inform("SHARING: bad or missing sharing file '%s': %s",
- filename, errno ? strerror(errno) :
- "potential security violation");
- }
- }
-
- return file;
-}
-
-
-/**********************************************************************
-* close_shared_range_file
-* Close a file opened with open_shared_range_file.
-* The file may actually be kept open and cached for a future
-* open_shared_range_file call. If so, clear_shared_range_file_cache()
-* can be used to really close the file.
-**********************************************************************/
-static void close_shared_range_file(FILE *file)
-{
- // Flush any writes in case the file is kept open.
- fflush(file);
-
- pthread_mutex_lock(&sharedRangeLock);
- if (file == sharedRangeFile && sharedRangeFileInUse) {
- // This file is the cached shared file.
- // Leave the file open and cached, but no longer in use.
- sharedRangeFileInUse = NO;
- } else {
- // This is not the cached file.
- fclose(file);
- }
- pthread_mutex_unlock(&sharedRangeLock);
-}
-
-
-/**********************************************************************
-* clear_shared_range_file_cache
-* Really close any file left open by close_shared_range_file.
-* This is called by map_images() after loading multiple images, each
-* of which may have used the shared range file.
-**********************************************************************/
-static void clear_shared_range_file_cache(void)
-{
- pthread_mutex_lock(&sharedRangeLock);
- if (sharedRangeFile && !sharedRangeFileInUse) {
- fclose(sharedRangeFile);
- sharedRangeFile = NULL;
- sharedRangeEUID = 0;
- sharedRangeFileInUse = 0;
- }
- pthread_mutex_unlock(&sharedRangeLock);
-}
-
-
-/**********************************************************************
-* get_shared_range
-* Try to find a shared range matching addresses [aligned_start..aligned_end).
-* If a range is found, it is mapped into this process and returned.
-* If no range is found, or the found range could not be mapped for
-* some reason, the range {0, 0} is returned.
-* aligned_start and aligned_end must be page-aligned.
-**********************************************************************/
-static vm_range_t get_shared_range(vm_address_t aligned_start,
- vm_address_t aligned_end)
-{
- struct remote_range_t remote;
- vm_range_t result;
- FILE *file;
-
- result.address = 0;
- result.size = 0;
-
- // Open shared range file, but don't create it
- file = open_shared_range_file(NO);
- if (!file) return result;
-
- // Search for the desired memory range
- while (1 == fread(&remote, sizeof(remote), 1, file)) {
- if (remote.pid != 0 &&
- remote.range.address == aligned_start &&
- remote.range.size == aligned_end - aligned_start)
- {
- // Found a match in the file - try to grab the memory
- mach_port_name_t remote_task;
- vm_prot_t cur_prot, max_prot;
- vm_address_t local_addr;
- kern_return_t kr;
-
- // Find the task offering the memory
- kr = task_for_pid(mach_task_self(), remote.pid, &remote_task);
- if (kr != KERN_SUCCESS) {
- // task is dead
- if (PrintSharing) {
- _objc_inform("SHARING: no task for pid %d: %s",
- remote.pid, mach_error_string(kr));
- }
- break;
- }
-
- // Map the memory into our process
- local_addr = 0;
- kr = vm_remap(mach_task_self(), &local_addr, remote.range.size,
- 0 /*alignment*/, 1 /*anywhere*/,
- remote_task, remote.range.address,
- 1 /*copy*/, &cur_prot, &max_prot, VM_INHERIT_NONE);
- mach_port_deallocate(mach_task_self(), remote_task);
-
- if (kr != KERN_SUCCESS) {
- // couldn't map memory
- if (PrintSharing) {
- _objc_inform("SHARING: vm_remap from pid %d failed: %s",
- remote.pid, mach_error_string(kr));
- }
- break;
- }
-
- if (!(cur_prot & VM_PROT_READ) || !(cur_prot & VM_PROT_WRITE)) {
- // Received memory is not mapped read/write - don't use it
- // fixme try to change permissions? check max_prot?
- if (PrintSharing) {
- _objc_inform("SHARING: memory from pid %d not read/write",
- remote.pid);
- }
- vm_deallocate(mach_task_self(), local_addr, remote.range.size);
- break;
- }
-
- // Success
- result.address = local_addr;
- result.size = remote.range.size;
- }
- }
-
- close_shared_range_file(file);
- return result;
-}
-
-
-/**********************************************************************
-* offer_shared_range
-* Offer memory range [aligned_start..aligned_end) in this process
-* to other Objective-C-using processes.
-* If some other entry in the shared range list matches this range,
-* is is overwritten with this process's PID. (Thus any stale PIDs are
-* replaced.)
-* If the shared range file could not be updated for any reason, this
-* function fails silently.
-* aligned_start and aligned_end must be page-aligned.
-**********************************************************************/
-static void offer_shared_range(vm_address_t aligned_start,
- vm_address_t aligned_end)
-{
- struct remote_range_t remote;
- struct remote_range_t local;
- BOOL found = NO;
- FILE *file;
- int err = 0;
-
- local.range.address = aligned_start;
- local.range.size = aligned_end - aligned_start;
- local.pid = getpid();
-
- // Open shared range file, creating if necessary
- file = open_shared_range_file(YES);
- if (!file) return;
-
- // Find an existing entry for this range, if any
- while (1 == fread(&remote, sizeof(remote), 1, file)) {
- if (remote.pid != 0 &&
- remote.range.address == aligned_start &&
- remote.range.size == aligned_end - aligned_start)
- {
- // Found a match - overwrite it
- err = fseek(file, -sizeof(remote), SEEK_CUR);
- found = YES;
- break;
- }
- }
-
- if (!found) {
- // No existing entry - write at the end of the file
- err = fseek(file, 0, SEEK_END);
- }
-
- if (err == 0) {
- fwrite(&local, sizeof(local), 1, file);
- }
-
- close_shared_range_file(file);
-}
-
-
-/**********************************************************************
-* install_shared_range
-* Install a shared range received from get_shared_range() into
-* its final resting place.
-* If possible, the memory is copied using virtual memory magic rather
-* than actual data writes. dst always gets updated values, even if
-* virtual memory magic is not possible.
-* The shared range is always deallocated.
-* src and dst must be page-aligned.
-**********************************************************************/
-static void install_shared_range(vm_range_t src, vm_address_t dst)
-{
- kern_return_t kr;
-
- // Copy from src to dst
- kr = vm_copy(mach_task_self(), src.address, src.size, dst);
- if (kr != KERN_SUCCESS) {
- // VM copy failed. Use non-VM copy.
- if (PrintSharing) {
- _objc_inform("SHARING: vm_copy failed: %s", mach_error_string(kr));
- }
- memmove((void *)dst, (void *)src.address, src.size);
- }
-
- // Unmap the shared range at src
- vm_deallocate(mach_task_self(), src.address, src.size);
-}