Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

objc4-274, released with OS X v10.4.4

  • Loading branch information...
commit 2b649a8e55b7bb3f1331b5f5713cc920a2cd9c6c 1 parent 4353fa1
@bavarious authored
View
348 Makefile
@@ -79,7 +79,7 @@ NMEDIT = /usr/bin/nmedit
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=
@@ -101,7 +101,7 @@ endif
ifeq "$(ORDERFILE)" ""
-ORDERFILE = $(wildcard /usr/local/lib/OrderFiles/libobjc.order)
+ORDERFILE = $(SRCROOT)/libobjc.order
endif
ifneq "$(ORDERFILE)" ""
ORDER = -sectorder __TEXT __text $(ORDERFILE)
@@ -113,7 +113,7 @@ ifeq "$(USER)" ""
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
@@ -158,3 +158,345 @@ MODULE_SOURCES=
OTHER_SOURCES=
# headers to install in /usr/include/objc
PUBLIC_HEADERS=
+# headers that don't get installed
+PRIVATE_HEADERS=
+# headers to install in /usr/local/include/objc
+OTHER_HEADERS=
+
+# runtime
+SOURCES += $(addprefix runtime/, \
+ Object.m Protocol.m hashtable2.m maptable.m objc-class.m objc-errors.m \
+ objc-file.m objc-load.m objc-moninit.c objc-runtime.m objc-sel.m \
+ objc-sync.m objc-exception.m objc-auto.m objc-sel-set.m objc-rtp.m \
+ )
+PUBLIC_HEADERS += $(addprefix runtime/, \
+ objc-class.h objc-api.h objc-load.h objc-runtime.h objc.h Object.h \
+ objc-sync.h objc-exception.h objc-auto.h \
+ Protocol.h error.h hashtable2.h \
+ )
+PRIVATE_HEADERS += runtime/objc-private.h runtime/objc-config.h runtime/objc-sel-table.h runtime/objc-sel-set.h runtime/objc-rtp.h
+OTHER_HEADERS += runtime/maptable.h runtime/objc-auto.h
+
+# OldClasses
+SOURCES += runtime/OldClasses.subproj/List.m
+PUBLIC_HEADERS += runtime/OldClasses.subproj/List.h
+
+# Messengers
+SOURCES += runtime/Messengers.subproj/objc-msg.s
+OTHER_SOURCES += runtime/Messengers.subproj/objc-msg-ppc.s runtime/Messengers.subproj/objc-msg-i386.s
+
+# Auto support
+SOURCES += runtime/Auto.subproj/objc-auto.s
+OTHER_SOURCES += runtime/Auto.subproj/objc-auto-ppc.s runtime/Auto.subproj/objc-auto-i386.s
+
+# RTP symbols for gdb
+# See also $(OBJROOT)/runtime/objc-rtp-sym.ppc.o rule below.
+OTHER_SOURCES += runtime/objc-rtp-sym.s
+
+# Interposing support.
+# This code is built into a second module so dyld's function interposing
+# can manipulate the calls.
+MODULE_SOURCES += runtime/Messengers.subproj/objc-msg-stub.s
+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 libobjc.order
+
+OBJECTS = $(addprefix $(OBJROOT)/, $(addsuffix .o, $(basename $(SOURCES) ) ) )
+OBJECTS_OPTIMIZED = $(OBJECTS:.o=.opt.o)
+OBJECTS_DEBUG = $(OBJECTS:.o=.debug.o)
+OBJECTS_PROFILE = $(OBJECTS:.o=.profile.o)
+
+MODULE_OBJECTS = $(addprefix $(OBJROOT)/, $(addsuffix .o, $(basename $(MODULE_SOURCES) ) ) )
+MODULE_OBJECTS_OPTIMIZED = $(MODULE_OBJECTS:.o=.opt.o)
+MODULE_OBJECTS_DEBUG = $(MODULE_OBJECTS:.o=.debug.o)
+MODULE_OBJECTS_PROFILE = $(MODULE_OBJECTS:.o=.profile.o)
+
+# For simplicity, each object target depends on all objc headers. Most of
+# them come close to requiring this anyway, and rebuild from scratch is fast.
+DEPEND_HEADERS = $(addprefix $(SRCROOT)/, \
+ $(PUBLIC_HEADERS) $(PRIVATE_HEADERS) $(OTHER_HEADERS) )
+
+$(OBJROOT)/%.opt.o : $(SRCROOT)/%.m $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_OPTIMIZED) "$<" -c -o "$@"
+
+$(OBJROOT)/%.debug.o : $(SRCROOT)/%.m $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_DEBUG) "$<" -c -o "$@"
+
+$(OBJROOT)/%.profile.o : $(SRCROOT)/%.m $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_PROFILE) "$<" -c -o "$@"
+
+$(OBJROOT)/%.opt.o : $(SRCROOT)/%.c $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_OPTIMIZED) "$<" -c -o "$@"
+
+$(OBJROOT)/%.debug.o : $(SRCROOT)/%.c $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_DEBUG) "$<" -c -o "$@"
+
+$(OBJROOT)/%.profile.o : $(SRCROOT)/%.c $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_PROFILE) "$<" -c -o "$@"
+
+$(OBJROOT)/%.opt.o : $(SRCROOT)/%.s $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_OPTIMIZED) "$<" -c -o "$@"
+
+$(OBJROOT)/%.debug.o : $(SRCROOT)/%.s $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_DEBUG) "$<" -c -o "$@"
+
+$(OBJROOT)/%.profile.o : $(SRCROOT)/%.s $(DEPEND_HEADERS)
+ $(SILENT) $(ECHO) " ... $<"
+ $(SILENT) $(CC) $(CFLAGS_PROFILE) "$<" -c -o "$@"
+
+# Additional dependency: objc-msg.s depends on objc-msg-ppc.s and
+# objc-msg-i386.s, which it includes.
+$(OBJROOT)/runtime/Messengers.subproj/objc-msg.opt.o \
+$(OBJROOT)/runtime/Messengers.subproj/objc-msg.debug.o \
+$(OBJROOT)/runtime/Messengers.subproj/objc-msg.profile.o : \
+ $(SRCROOT)/runtime/Messengers.subproj/objc-msg-ppc.s \
+ $(SRCROOT)/runtime/Messengers.subproj/objc-msg-i386.s
+
+# Additional dependency: objc-msg-sutb.s depends on objc-msg-stub-ppc.s and
+# objc-msg-stub-i386.s, which it includes.
+$(OBJROOT)/runtime/Messengers.subproj/objc-msg-stub.opt.o \
+$(OBJROOT)/runtime/Messengers.subproj/objc-msg-stub.debug.o \
+$(OBJROOT)/runtime/Messengers.subproj/objc-msg-stub.profile.o : \
+ $(SRCROOT)/runtime/Messengers.subproj/objc-msg-stub-ppc.s \
+ $(SRCROOT)/runtime/Messengers.subproj/objc-msg-stub-i386.s
+
+# Additional dependency: objc-auto.s depends on objc-auto-ppc.s and
+# objc-auto-i386.s, which it includes.
+$(OBJROOT)/runtime/Auto.subproj/objc-auto.opt.o \
+$(OBJROOT)/runtime/Auto.subproj/objc-auto.debug.o \
+$(OBJROOT)/runtime/Auto.subproj/objc-auto.profile.o : \
+ $(SRCROOT)/runtime/Auto.subproj/objc-auto-ppc.s \
+ $(SRCROOT)/runtime/Auto.subproj/objc-auto-i386.s
+
+# Additional rules: objc-rtp-sym.s needs to be built with a per-arch seg1addr,
+# and need to be stripped here because stripping the dylib does not remove
+# debug info from the magic sections.
+# objc-rtp-sym.s is not in SOURCES, and objc-rtp-sym.o is not in OBJECTS
+$(OBJROOT)/runtime/objc-rtp-sym.ppc.o: $(SRCROOT)/runtime/objc-rtp-sym.s
+ $(SILENT) $(CC) $(CFLAGS_OPTIMIZED) -arch ppc "$<" -c -o "$@.temp"
+ $(SILENT) $(STRIP) -S "$@.temp"
+ $(SILENT) $(LD) -arch ppc -seg1addr 0xfffec000 "$@.temp" -r -o "$@"
+
+$(OBJROOT)/runtime/objc-rtp-sym.i386.o: $(SRCROOT)/runtime/objc-rtp-sym.s
+ $(SILENT) $(CC) $(CFLAGS_OPTIMIZED) -arch i386 "$<" -c -o "$@.temp"
+ $(SILENT) $(STRIP) -S "$@.temp"
+ $(SILENT) $(LD) -arch i386 -seg1addr 0xfffe8000 "$@.temp" -r -o "$@"
+
+
+# These are the main targets:
+# build builds the library to OBJROOT and SYMROOT
+# installsrc copies the sources to SRCROOT
+# installhdrs install only the headers to DSTROOT
+# install build, then install the headers and library to DSTROOT
+# clean removes build products in OBJROOT and SYMROOT
+#
+# optimized same as 'build' but builds optimized library only
+# debug same as 'build' but builds debug library only
+# profile same as 'build' but builds profile library only
+
+# Default build doesn't currently build the debug library.
+build: prebuild build-optimized build-profile postbuild
+
+optimized: prebuild build-optimized postbuild
+debug: prebuild build-debug postbuild
+profile: prebuild build-profile postbuild
+
+installsrc:
+ $(SILENT) $(ECHO) "Installing source from . to $(SRCROOT)..."
+ifeq "$(SRCROOT)" "."
+ $(SILENT) $(ECHO) "SRCROOT must be defined to be the destination directory; it cannot be '.'"
+ exit 1
+endif
+ $(SILENT) $(TAR) -cf $(SRCROOT)/objc4.sources.tar $(SOURCES) $(PUBLIC_HEADERS) $(PRIVATE_HEADERS) $(OTHER_HEADERS) $(OTHER_SOURCES) $(MODULE_SOURCES)
+ $(SILENT) $(CD) $(SRCROOT) && $(TAR) -xf $(SRCROOT)/objc4.sources.tar
+ $(SILENT) $(REMOVE) -f $(SRCROOT)/objc4.sources.tar
+
+installhdrs:
+ $(SILENT) $(ECHO) "Installing headers from $(SRCROOT) to $(DSTROOT)/$(HEADER_INSTALLDIR)..."
+
+ $(SILENT) $(MKDIRS) $(DSTROOT)/$(PUBLIC_HEADER_INSTALLDIR)
+ -$(SILENT) $(CHMOD) +w $(DSTROOT)/$(PUBLIC_HEADER_INSTALLDIR)/*.h
+ $(SILENT) $(COPY) $(addprefix $(SRCROOT)/, $(PUBLIC_HEADERS) ) \
+ $(DSTROOT)/$(PUBLIC_HEADER_INSTALLDIR)
+# duplicate hashtable2.h to hashtable.h
+ $(SILENT) $(COPY) $(DSTROOT)/$(PUBLIC_HEADER_INSTALLDIR)/hashtable2.h \
+ $(DSTROOT)/$(PUBLIC_HEADER_INSTALLDIR)/hashtable.h
+ $(SILENT) $(CHMOD) -w $(DSTROOT)/$(PUBLIC_HEADER_INSTALLDIR)/*.h
+ $(SILENT) $(CHMOD) a+r $(DSTROOT)/$(PUBLIC_HEADER_INSTALLDIR)/*.h
+
+ $(SILENT) $(MKDIRS) $(DSTROOT)/$(OTHER_HEADER_INSTALLDIR)
+ -$(SILENT) $(CHMOD) +w $(DSTROOT)/$(OTHER_HEADER_INSTALLDIR)/*.h
+ $(SILENT) $(COPY) $(addprefix $(SRCROOT)/, $(OTHER_HEADERS) ) \
+ $(DSTROOT)/$(OTHER_HEADER_INSTALLDIR)
+ $(SILENT) $(CHMOD) -w $(DSTROOT)/$(OTHER_HEADER_INSTALLDIR)/*.h
+ $(SILENT) $(CHMOD) a+r $(DSTROOT)/$(OTHER_HEADER_INSTALLDIR)/*.h
+
+
+ $(SILENT) $(RM) -f $(DSTROOT)$(PUBLIC_HEADER_DIR)$(PUBLIC_HEADER_DIR_SUFFIX)/hashtable.h
+
+
+install: build installhdrs
+ $(SILENT) $(ECHO) "Installing products from $(SYMROOT) to $(DSTROOT)..."
+
+ $(SILENT) $(MKDIRS) $(DSTROOT)/$(INSTALLDIR)
+ -$(SILENT) $(CHMOD) +w $(DSTROOT)/$(INSTALLDIR)
+
+ $(SILENT) $(REMOVE) -f $(DSTROOT)/$(INSTALLDIR)/libobjc.$(VERSION_NAME)$(LIBRARY_EXT)
+ $(SILENT) $(REMOVE) -f $(DSTROOT)/$(INSTALLDIR)/libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT)
+ $(SILENT) $(REMOVE) -f $(DSTROOT)/$(INSTALLDIR)/libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT)
+
+# optimized
+ $(SILENT) $(COPY) $(SYMROOT)/libobjc.$(VERSION_NAME)$(LIBRARY_EXT) $(DSTROOT)/$(INSTALLDIR)
+ $(SILENT) $(STRIP) -S $(DSTROOT)/$(INSTALLDIR)/libobjc.$(VERSION_NAME)$(LIBRARY_EXT)
+ -$(SILENT) $(CHOWN) root:wheel $(DSTROOT)/$(INSTALLDIR)/libobjc.$(VERSION_NAME)$(LIBRARY_EXT)
+ $(SILENT) $(CHMOD) 755 $(DSTROOT)/$(INSTALLDIR)/libobjc.$(VERSION_NAME)$(LIBRARY_EXT)
+ $(SILENT) $(CD) $(DSTROOT)/$(INSTALLDIR) && \
+ $(SYMLINK) libobjc.$(VERSION_NAME)$(LIBRARY_EXT) libobjc$(LIBRARY_EXT)
+
+# debug (allowed not to exist)
+ -$(SILENT) $(COPY) $(SYMROOT)/libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT) $(DSTROOT)/$(INSTALLDIR)
+ -$(SILENT) $(CHOWN) root:wheel $(DSTROOT)/$(INSTALLDIR)/libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT)
+ -$(SILENT) $(CHMOD) 755 $(DSTROOT)/$(INSTALLDIR)/libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT)
+ -$(SILENT) $(CD) $(DSTROOT)/$(INSTALLDIR) && \
+ test -e libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT) && \
+ $(SYMLINK) libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT) libobjc_debug$(LIBRARY_EXT) && \
+ $(SYMLINK) libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT) libobjc.$(VERSION_NAME)_debug$(LIBRARY_EXT)
+
+
+# profile (allowed not to exist)
+ -$(SILENT) $(COPY) $(SYMROOT)/libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT) $(DSTROOT)/$(INSTALLDIR)
+ -$(SILENT) $(CHOWN) root:wheel $(DSTROOT)/$(INSTALLDIR)/libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT)
+ -$(SILENT) $(CHMOD) 755 $(DSTROOT)/$(INSTALLDIR)/libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT)
+ -$(SILENT) $(CD) $(DSTROOT)/$(INSTALLDIR) && \
+ test -e libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT) && \
+ $(SYMLINK) libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT) libobjc_profile$(LIBRARY_EXT) && \
+ $(SYMLINK) libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT) libobjc.$(VERSION_NAME)_profile$(LIBRARY_EXT)
+
+
+clean:
+ $(SILENT) $(ECHO) "Deleting build products..."
+ $(SILENT) $(REMOVE) -f \
+ $(foreach A, $(ARCH_LIST), \
+ $(OBJROOT)/libobjc_debug.$A.$(VERSION_NAME)$(LIBRARY_EXT) \
+ $(OBJROOT)/libobjc_profile.$A.$(VERSION_NAME)$(LIBRARY_EXT) \
+ $(OBJROOT)/libobjc.$A.$(VERSION_NAME)$(LIBRARY_EXT) \
+ $(OBJROOT)/runtime/objc-rtp-sym.$A.o \
+ $(OBJROOT)/runtime/objc-rtp-sym.$A.o.temp \
+ )
+
+ $(SILENT) $(REMOVE) -f $(SYMROOT)/libobjc.optimized.o
+ $(SILENT) $(REMOVE) -f $(SYMROOT)/libobjc.debug.o
+ $(SILENT) $(REMOVE) -f $(SYMROOT)/libobjc.profile.o
+
+ $(SILENT) $(REMOVE) -f $(SYMROOT)/libobjc.$(VERSION_NAME)$(LIBRARY_EXT)
+ $(SILENT) $(REMOVE) -f $(SYMROOT)/libobjc_debug.$(VERSION_NAME)$(LIBRARY_EXT)
+ $(SILENT) $(REMOVE) -f $(SYMROOT)/libobjc_profile.$(VERSION_NAME)$(LIBRARY_EXT)
+
+ $(SILENT) $(REMOVE) -f $(OBJECTS_OPTIMIZED)
+ $(SILENT) $(REMOVE) -f $(OBJECTS_DEBUG)
+ $(SILENT) $(REMOVE) -f $(OBJECTS_PROFILE)
+
+ $(SILENT) $(REMOVE) -f $(MODULE_OBJECTS_OPTIMIZED)
+ $(SILENT) $(REMOVE) -f $(MODULE_OBJECTS_DEBUG)
+ $(SILENT) $(REMOVE) -f $(MODULE_OBJECTS_PROFILE)
+
+ $(SILENT) $(REMOVE) -rf $(SYMROOT)/ProjectHeaders
+
+prebuild:
+ $(SILENT) $(ECHO) "Prebuild-setup..."
+
+# Install headers into $(SYMROOT)/ProjectHeaders so #includes can find them
+# even if they're not installed in /usr.
+ $(SILENT) $(MKDIRS) $(SYMROOT)
+ $(SILENT) $(REMOVE_RECUR) $(SYMROOT)/ProjectHeaders
+ $(SILENT) $(MKDIRS) $(SYMROOT)/ProjectHeaders
+ $(SILENT) $(ECHO) "Copying headers from $(SRCROOT) to $(SYMROOT)/ProjectHeaders..."
+ $(SILENT) $(COPY) $(addprefix $(SRCROOT)/, $(PRIVATE_HEADERS) ) $(SYMROOT)/ProjectHeaders
+ $(SILENT) $(MKDIRS) $(SYMROOT)/ProjectHeaders/objc
+ $(SILENT) $(COPY) $(addprefix $(SRCROOT)/, $(PUBLIC_HEADERS) ) $(SYMROOT)/ProjectHeaders/objc
+ $(SILENT) $(COPY) $(addprefix $(SRCROOT)/, $(OTHER_HEADERS) ) $(SYMROOT)/ProjectHeaders/objc
+
+
+
+build-optimized: prebuild-optimized compile-optimized link-optimized
+build-debug: prebuild-debug compile-debug link-debug
+build-profile: prebuild-profile compile-profile link-profile
+
+
+prebuild-optimized:
+ $(SILENT) $(ECHO) "Building (optimized) ..."
+ $(SILENT) $(MKDIRS) $(foreach S, $(SUBDIRS), $(OBJROOT)/$(S) )
+
+prebuild-debug:
+ $(SILENT) $(ECHO) "Building (debug) ..."
+ $(SILENT) $(MKDIRS) $(foreach S, $(SUBDIRS), $(OBJROOT)/$(S) )
+
+prebuild-profile:
+ $(SILENT) $(ECHO) "Building (profile) ..."
+ $(SILENT) $(MKDIRS) $(foreach S, $(SUBDIRS), $(OBJROOT)/$(S) )
+
+
+compile-optimized: $(OBJECTS_OPTIMIZED) $(MODULE_OBJECTS_OPTIMIZED) $(foreach A, $(ARCH_LIST), $(OBJROOT)/runtime/objc-rtp-sym.$A.o )
+compile-debug: $(OBJECTS_DEBUG) $(MODULE_OBJECTS_DEBUG) $(foreach A, $(ARCH_LIST), $(OBJROOT)/runtime/objc-rtp-sym.$A.o )
+compile-profile: $(OBJECTS_PROFILE) $(MODULE_OBJECTS_PROFILE) $(foreach A, $(ARCH_LIST), $(OBJROOT)/runtime/objc-rtp-sym.$A.o )
+
+
+# link lib-suffix, LDFLAGS, OBJECTS, MODULE_OBJECTS
+# libsuffix should be "" or _debug or _profile
+ifeq "$(PLATFORM)" "Darwin"
+
+define link
+ $(foreach A, $(ARCH_LIST), \
+ $(SILENT) $(LD) -r \
+ -arch $A \
+ -o $(OBJROOT)/libobjc$1.$A.o \
+ $3 ; \
+ $(SILENT) $(CC) $2 \
+ -arch $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) \
+ -o $(OBJROOT)/libobjc$1.$A.$(VERSION_NAME)$(LIBRARY_EXT) \
+ $(OBJROOT)/libobjc$1.$A.o $4 ; \
+ )
+ $(SILENT) $(LIPO) \
+ -create -output $(SYMROOT)/libobjc$1.$(VERSION_NAME)$(LIBRARY_EXT) \
+ $(foreach A, $(ARCH_LIST), -arch $A $(OBJROOT)/libobjc$1.$A.$(VERSION_NAME)$(LIBRARY_EXT) )
+endef
+
+else
+# PLATFORM != Darwin
+define link
+ $(SILENT) $(ECHO) "Don't know how to link for platform '$(PLATFORM)'"
+endef
+
+endif
+
+
+link-optimized:
+ $(SILENT) $(ECHO) "Linking (optimized)..."
+ $(call link,,$(LDFLAGS_OPTIMIZED),$(OBJECTS_OPTIMIZED),$(MODULE_OBJECTS_OPTIMIZED) )
+
+link-debug:
+ $(SILENT) $(ECHO) "Linking (debug)..."
+ $(call link,_debug,$(LDFLAGS_DEBUG),$(OBJECTS_DEBUG),$(MODULE_OBJECTS_DEBUG) )
+
+link-profile:
+ $(SILENT) $(ECHO) "Linking (profile)..."
+ $(call link,_profile,$(LDFLAGS_PROFILE),$(OBJECTS_PROFILE),$(MODULE_OBJECTS_PROFILE) )
+
+
+postbuild:
+ $(SILENT) $(ECHO) "Done!"
+
+
View
135 libobjc.order
@@ -0,0 +1,135 @@
+__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
View
2  objc-exports
@@ -64,11 +64,13 @@ _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
View
138 runtime/Messengers.subproj/objc-msg-i386.s
@@ -65,6 +65,7 @@ _objc_entryPoints:
.long __cache_getImp
.long __cache_getMethod
.long _objc_msgSend
+ .long _objc_msgSend_fpret
.long _objc_msgSend_stret
.long _objc_msgSendSuper
.long _objc_msgSendSuper_stret
@@ -75,6 +76,7 @@ _objc_exitPoints:
.long LGetImpExit
.long LGetMethodExit
.long LMsgSendExit
+ .long LMsgSendFpretExit
.long LMsgSendStretExit
.long LMsgSendSuperExit
.long LMsgSendSuperStretExit
@@ -322,24 +324,21 @@ $0:
//////////////////////////////////////////////////////////////////////
//
-// 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
@@ -715,7 +714,7 @@ LGetImpExit:
********************************************************************/
ENTRY _objc_msgSend
- CALL_MCOUNTER LP0
+ CALL_MCOUNTER
movl self(%esp), %eax
@@ -740,9 +739,12 @@ LMsgSendNilSelf:
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
@@ -766,7 +768,7 @@ LMsgSendExit:
********************************************************************/
ENTRY _objc_msgSendSuper
- CALL_MCOUNTER LP1
+ CALL_MCOUNTER
movl super(%esp), %eax
@@ -802,6 +804,7 @@ LMsgSendSuperExit:
#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
@@ -809,13 +812,12 @@ LMsgSendSuperExit:
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
@@ -836,6 +838,100 @@ LMsgSendvArgsOK:
#endif
END_ENTRY _objc_msgSendv
+/********************************************************************
+ *
+ * double objc_msgSend_fpret(id self, SEL _cmd,...);
+ *
+ ********************************************************************/
+
+ ENTRY _objc_msgSend_fpret
+ CALL_MCOUNTER
+
+ movl self(%esp), %eax
+
+// check whether receiver is nil
+ testl %eax, %eax
+ je LMsgSendFpretNilSelf
+
+// receiver is non-nil: search the cache
+LMsgSendFpretReceiverOk:
+ CacheLookup WORD_RETURN, MSG_SEND, LMsgSendFpretCacheMiss
+ movl $kFwdMsgSend, %edx // flag word-return for _objc_msgForward
+ jmp *%eax // goto *imp
+
+// cache miss: go search the method lists
+LMsgSendFpretCacheMiss:
+ MethodTableLookup WORD_RETURN, MSG_SEND
+ movl $kFwdMsgSend, %edx // flag word-return for _objc_msgForward
+ jmp *%eax // goto *imp
+
+// message sent to nil: redirect to nil receiver, if any
+LMsgSendFpretNilSelf:
+ call L_get_pc_thunk.edx // load new receiver
+1: movl __objc_nilReceiver-1b(%edx),%eax
+ testl %eax, %eax // return zero if no new receiver
+ je LMsgSendFpretReturnZero
+ movl %eax, self(%esp) // send to new receiver
+ jmp LMsgSendFpretReceiverOk
+LMsgSendFpretReturnZero:
+ fldz
+LMsgSendFpretDone:
+ ret
+
+LMsgSendFpretExit:
+ END_ENTRY _objc_msgSend_fpret
+
+/********************************************************************
+ * double objc_msgSendv_fpret(id self, SEL _cmd, unsigned size, marg_list frame);
+ *
+ * On entry:
+ * (sp+4) is the message receiver,
+ * (sp+8) is the selector,
+ * (sp+12) is the size of the marg_list, in bytes,
+ * (sp+16) is the address of the marg_list
+ *
+ ********************************************************************/
+
+ ENTRY _objc_msgSendv_fpret
+
+#if defined(KERNEL)
+ trap // _objc_msgSendv is not for the kernel
+#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
+ subl $8, %ecx // skip self & selector
+ shrl $2, %ecx
+ je LMsgSendvFpretArgsOK
+
+ // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
+ movl %ecx, %eax // 16-byte align stack
+ andl $3, %eax
+ shll $2, %eax
+ subl $16, %esp
+ addl %eax, %esp
+
+LMsgSendvFpretArgLoop:
+ decl %ecx
+ movl 0(%edx, %ecx, 4), %eax
+ pushl %eax
+ jg LMsgSendvFpretArgLoop
+
+LMsgSendvFpretArgsOK:
+ movl (selector+4)(%ebp), %ecx
+ pushl %ecx
+ movl (self+4)(%ebp),%ecx
+ pushl %ecx
+ call _objc_msgSend_fpret
+ movl %ebp,%esp
+ popl %ebp
+
+ ret
+#endif
+ END_ENTRY _objc_msgSendv_fpret
/********************************************************************
*
@@ -852,7 +948,7 @@ LMsgSendvArgsOK:
********************************************************************/
ENTRY _objc_msgSend_stret
- CALL_MCOUNTER LP2
+ CALL_MCOUNTER
movl self_stret(%esp), %eax
@@ -886,7 +982,7 @@ LMsgSendStretDone:
// 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
@@ -913,7 +1009,7 @@ LMsgSendStretExit:
********************************************************************/
ENTRY _objc_msgSendSuper_stret
- CALL_MCOUNTER LP4
+ CALL_MCOUNTER
movl super_stret(%esp), %eax
@@ -954,6 +1050,7 @@ LMsgSendSuperStretExit:
#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
@@ -961,10 +1058,11 @@ LMsgSendSuperStretExit:
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:
View
28 runtime/Messengers.subproj/objc-msg-ppc.s
@@ -868,12 +868,19 @@ LMsgSendNilSelf:
; 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.
@@ -888,6 +895,15 @@ LMsgSendCacheMiss:
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,
@@ -939,7 +955,7 @@ LMsgSendStretNilSelf:
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
@@ -1282,6 +1298,14 @@ LMsgSendvSendIt:
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,
View
5 runtime/objc-rtp.h
@@ -108,9 +108,10 @@
// 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.
View
1  runtime/objc-rtp.m
@@ -103,6 +103,7 @@ __private_extern__ void rtp_init(void)
"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
View
28 runtime/objc-runtime.h
@@ -78,6 +78,25 @@ OBJC_EXPORT id objc_msgSend(id self, SEL op, ...);
OBJC_EXPORT id objc_msgSendSuper(struct objc_super *super, SEL op, ...);
+/* Floating-point-returning Messaging Primitives (prototypes)
+ *
+ * On some platforms, the ABI for functions returning a floating-point
+ * value is incompatible with that for functions returning an integral type.
+ * objc_msgSend_fpret must be used for these.
+ *
+ * ppc: objc_msgSend_fpret not used
+ * ppc64: objc_msgSend_fpret not used
+ * i386: objc_msgSend_fpret REQUIRED
+ *
+ * For `float` or `long double` return types, cast the function
+ * to an appropriate function pointer type first.
+ */
+
+#ifdef __i386__
+OBJC_EXPORT double objc_msgSend_fpret(id self, SEL op, ...);
+#endif
+
+
/* Struct-returning Messaging Primitives (prototypes)
*
* For historical reasons, the prototypes for the struct-returning
@@ -106,8 +125,17 @@ OBJC_EXPORT id objc_msgSendSuper(struct objc_super *super, SEL op, ...);
/* 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...
View
417 runtime/objc-runtime.m
@@ -289,10 +289,6 @@
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);
/***********************************************************************
@@ -1022,6 +1018,7 @@ static void _objc_read_categories_from_image (header_info * hi)
return;
}
+
// Major loop - process all modules in the header
mods = hi->mod_ptr;
@@ -2355,11 +2352,6 @@ static void verify_gc_readiness(BOOL wantsGC, header_info *hi)
/***********************************************************************
* _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)
{
@@ -2381,75 +2373,8 @@ 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);
}
}
@@ -2670,9 +2595,6 @@ static void map_images(const struct dyld_image_info infoList[],
_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.
@@ -3177,336 +3099,3 @@ __private_extern__ int secure_open(const char *filename, int flags, uid_t euid)
}
-/**********************************************************************
- * 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);
-}
Please sign in to comment.
Something went wrong with that request. Please try again.