+Only in ld: CVS
+diff -ubr ld/Makefile ld/Makefile
+--- ld/Makefile Fri Sep 6 18:27:43 2002
++++ ld/Makefile Mon Aug 25 23:04:37 2003
+@@ -9,10 +9,10 @@
+ -DKERNEL -DKERNEL_PRIVATE -DAPPLE -DNeXT -DLIBSA_PRIVATE
+
+
+-MIG = $(NEXT_ROOT)/usr/bin/mig
++MIG = mig
+
+ ifeq "macos" "$(RC_OS)"
+- X_CFLAGS := $(shell if [ "$(RC_RELEASE)" != "Beaker" ] && \
++ X_CFLAGS := $(shell if [ `uname` != "Linux" ] && [ "$(RC_RELEASE)" != "Beaker" ] && \
+ [ "$(RC_RELEASE)" != "Bunsen" ] && \
+ [ "$(RC_RELEASE)" != "Gonzo" ] && \
+ [ "$(RC_RELEASE)" != "Kodiak" ]; then \
+@@ -21,10 +21,19 @@
+ endif
+
+ ifneq "mwccppc" "$(notdir $(CC))"
+- GCC_FLAGS = -Wall -Wno-precomp $(X_CFLAGS)
++ ifeq "Linux" "$(shell uname)"
++ GCC_FLAGS = -Wall $(X_CFLAGS) -D__ppc__ -I/usr/include -I../../../macosx-include
++ else
++ GCC_FLAGS = -Wall $(X_CFLAGS)
++ endif
+ endif
+
+-USE_DEPENDENCY_FILE := $(shell if [ "$(notdir $(CC))" != "mwccppc" ]; then \
++# Hack: Add ../misc to the path because it contains seg_hack and ver_string
++ifneq ($(findstring ../misc,$(PATH)),../misc)
++ PATH:=../misc:../../misc:$(PATH)
++endif
++
++USE_DEPENDENCY_FILE := $(shell if [ `uname` != "Linux" ] && [ "$(notdir $(CC))" != "mwccppc" ]; then \
+ echo YES ; else echo NO ; \
+ fi; )
+
+@@ -78,7 +87,7 @@
+ fvmlibs.c layout.c specs.c pass2.c generic_reloc.c rld.c sets.c \
+ 4byte_literals.c 8byte_literals.c literal_pointers.c dylibs.c \
+ indirect_sections.c mod_sections.c i860_reloc.c ppc_reloc.c \
+- m88k_reloc.c hppa_reloc.c sparc_reloc.c coalesced_sections.c
++ m88k_reloc.c hppa_reloc.c sparc_reloc.c coalesced_sections.c fake-mach.c
+ OBJS = $(CFILES:.c=.o)
+ INSTALL_FILES = $(CFILES) $(HFILES) Makefile notes \
+ make.defs make_defs.h librld.ofileList
+@@ -107,12 +116,12 @@
+ OFILE_DIR=. SRCROOT=.. RC_CFLAGS="$(RC_CFLAGS)" \
+ LIBSTUFF="-L../../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+- MAKEINCDIR=`pwd` COPTS="-DDEBUG" CC="$(CC)"; \
++ MAKEINCDIR="`pwd`" COPTS="-DDEBUG" CC="$(CC)"; \
+ else \
+ cd $(OBJROOT)/ld_dir; $(MAKE) -f $(SRCROOT)/Makefile ld.NEW \
+ VPATH=$(SRCROOT) OFILE_DIR=$(OBJROOT)/ld_dir \
+ SYMROOT=$(SYMROOT)/ld_dir SRCROOT=$(SRCROOT) \
+- MAKEINCDIR=`pwd` COPTS="-DDEBUG" \
++ MAKEINCDIR="`pwd`" COPTS="-DDEBUG" \
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+ RC_CFLAGS="$(RC_CFLAGS)" CC="$(CC)"; \
+@@ -120,19 +129,19 @@
+
+ ld_g_build: ld_g_dir
+ cd ld_g_dir; $(MAKE) -f ../Makefile ld_g.NEW VPATH=.. OFILE_DIR=. \
+- SRCROOT=.. MAKEINCDIR=`pwd` COPTS="-DDEBUG" OFLAG="" \
++ SRCROOT=.. MAKEINCDIR="`pwd`" COPTS="-DDEBUG" OFLAG="" \
+ LIBSTUFF="-L../../libstuff -lstuff"
+
+ ld_p_build: ld_p_dir
+ cd ld_p_dir; $(MAKE) -f ../Makefile ld.NEW VPATH=.. OFILE_DIR=. \
+- SRCROOT=.. MAKEINCDIR=`pwd` COPTS="-pg -DDEBUG" \
++ SRCROOT=.. MAKEINCDIR="`pwd`" COPTS="-pg -DDEBUG" \
+ LIBSTUFF="-L../../libstuff -lstuff_p"
+
+ shlib_ofiles: $(OBJROOT)/shlib_obj $(SYMROOT)/ld_dir
+ @if [ $(SRCROOT) = . ]; \
+ then \
+ (cd shlib_obj; $(MAKE) -f ../Makefile librld.o VPATH=.. \
+- MAKEINCDIR=`pwd` OFILE_DIR=. SRCROOT=.. \
++ MAKEINCDIR="`pwd`" OFILE_DIR=. SRCROOT=.. \
+ COPTS="-static -DRLD -DSHLIB -I/LocalDeveloper/Headers/libsys" \
+ LIBSTUFF="-L../../libstuff -lstuff_s" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" CC="$(CC)" \
+@@ -147,7 +156,7 @@
+ COPTS="-static -DRLD -DSHLIB -I/LocalDeveloper/Headers/libsys" \
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff_s" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+- MAKEINCDIR=`pwd` RC_ARCHS="$(RC_ARCHS)"); \
++ MAKEINCDIR="`pwd`" RC_ARCHS="$(RC_ARCHS)"); \
+ rm -f $(OBJROOT)/shlib_obj/librld.ofileList; \
+ cp librld.ofileList $(OBJROOT)/shlib_obj; \
+ fi
+@@ -156,7 +165,7 @@
+ @if [ $(SRCROOT) = . ]; \
+ then \
+ (cd ptmp_obj; $(MAKE) -f ../Makefile librld_pg.a VPATH=.. \
+- MAKEINCDIR=`pwd` OFILE_DIR=. SRCROOT=.. \
++ MAKEINCDIR="`pwd`" OFILE_DIR=. SRCROOT=.. \
+ LIBSTUFF="-L../../libstuff -lstuff_p" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" CC="$(CC)" \
+ RC_CFLAGS="$(RC_CFLAGS)" COPTS="-dynamic -DRLD -pg"); \
+@@ -173,7 +182,7 @@
+ RC_CFLAGS="$(RC_CFLAGS)" CC="$(CC)" \
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff_p" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+- MAKEINCDIR=`pwd` COPTS="-dynamic -DRLD -pg"); \
++ MAKEINCDIR="`pwd`" COPTS="-dynamic -DRLD -pg"); \
+ rm -f $(OBJROOT)/profile_obj/librld.o; \
+ rm -f $(OBJROOT)/profile_obj/librld.ofileList; \
+ cp $(OBJROOT)/ptmp_obj/librld.o $(OBJROOT)/profile_obj/librld.o; \
+@@ -186,7 +195,7 @@
+ @if [ $(SRCROOT) = . ]; \
+ then \
+ (cd otmp_obj; $(MAKE) -f ../Makefile librld_static.a VPATH=.. \
+- MAKEINCDIR=`pwd` OFILE_DIR=. SRCROOT=.. \
++ MAKEINCDIR="`pwd`" OFILE_DIR=. SRCROOT=.. \
+ LIBSTUFF="-L../../libstuff -lstuff" CC="$(CC)" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+ RC_CFLAGS="$(RC_CFLAGS)" COPTS="-static -DRLD"); \
+@@ -204,7 +213,7 @@
+ RC_CFLAGS="$(RC_CFLAGS)" CC="$(CC)" \
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+- MAKEINCDIR=`pwd` COPTS="-static -DRLD"); \
++ MAKEINCDIR="`pwd`" COPTS="-static -DRLD"); \
+ rm -f $(OBJROOT)/optimized_obj/librld.o; \
+ rm -f $(OBJROOT)/optimized_obj/librld.ofileList; \
+ cp $(OBJROOT)/otmp_obj/librld.o $(OBJROOT)/optimized_obj/librld.o;\
+@@ -217,7 +226,7 @@
+ @if [ $(SRCROOT) = . ]; \
+ then \
+ (cd dtmp_obj; $(MAKE) -f ../Makefile librld.a VPATH=.. \
+- MAKEINCDIR=`pwd` OFILE_DIR=. SRCROOT=.. \
++ MAKEINCDIR="`pwd`" OFILE_DIR=. SRCROOT=.. \
+ LIBSTUFF="-L../../libstuff -lstuff" CC="$(CC)" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+ RC_CFLAGS="$(RC_CFLAGS)" COPTS="-dynamic -DRLD"); \
+@@ -232,7 +241,7 @@
+ RC_CFLAGS="$(RC_CFLAGS)" CC="$(CC)" \
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+- MAKEINCDIR=`pwd` COPTS="-dynamic -DRLD"); \
++ MAKEINCDIR="`pwd`" COPTS="-dynamic -DRLD"); \
+ rm -f $(OBJROOT)/dynamic_obj/librld.o; \
+ rm -f $(OBJROOT)/dynamic_obj/librld.ofileList; \
+ cp $(OBJROOT)/dtmp_obj/librld.o $(OBJROOT)/dynamic_obj/librld.o;\
+@@ -243,7 +252,7 @@
+ @if [ $(SRCROOT) = . ]; \
+ then \
+ cd sarld_dir; $(MAKE) -f ../Makefile libsarld.a VPATH=.. \
+- MAKEINCDIR=`pwd` OFILE_DIR=. SRCROOT=.. \
++ MAKEINCDIR="`pwd`" OFILE_DIR=. SRCROOT=.. \
+ COPTS="-static -DRLD -DSA_RLD" CC="$(CC)" \
+ LIBSTUFF="-L../../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+@@ -255,14 +264,14 @@
+ COPTS="-static -DRLD -DSA_RLD" RC_CFLAGS="$(RC_CFLAGS)" \
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+- MAKEINCDIR=`pwd` RC_ARCHS="$(RC_ARCHS)"; \
++ MAKEINCDIR="`pwd`" RC_ARCHS="$(RC_ARCHS)"; \
+ fi
+
+ kld_build: $(OBJROOT)/dynamic_kld $(OBJROOT)/static_kld $(SYMROOT)/ld_dir
+ @if [ $(SRCROOT) = . ]; \
+ then \
+ cd dynamic_kld; $(MAKE) -f ../Makefile libkld.dylib VPATH=.. \
+- MAKEINCDIR=`pwd` OFILE_DIR=. SRCROOT=.. \
++ MAKEINCDIR="`pwd`" OFILE_DIR=. SRCROOT=.. \
+ COPTS="-DRLD -DKLD" CC="$(CC)" \
+ LIBSTUFF="-L../../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+@@ -274,12 +283,12 @@
+ COPTS="-DRLD -DKLD" RC_CFLAGS="$(RC_CFLAGS)" \
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" \
+- MAKEINCDIR=`pwd` RC_ARCHS="$(RC_ARCHS)"; \
++ MAKEINCDIR="`pwd`" RC_ARCHS="$(RC_ARCHS)"; \
+ fi
+ @if [ $(SRCROOT) = . ]; \
+ then \
+ cd static_kld; $(MAKE) -f ../Makefile libkld.a VPATH=.. \
+- MAKEINCDIR=`pwd` OFILE_DIR=. SRCROOT=.. \
++ MAKEINCDIR="`pwd`" OFILE_DIR=. SRCROOT=.. \
+ COPTS="-static -DRLD -DKLD $(KERN)" CC="$(CC)" \
+ LIBSTUFF="-L../../libstuff -lstuff" PRIVATE_IFLAG="" \
+ LIBMACHO="-L../../libmacho/otmp_obj -lmacho_static" \
+@@ -293,7 +302,7 @@
+ LIBSTUFF="-L$(SYMROOT)/../libstuff -lstuff" \
+ LIBMACHO="-L$(SYMROOT)/../libmacho -lmacho_static" \
+ VERS_STRING_FLAGS="$(VERS_STRING_FLAGS)" PRIVATE_IFLAG="" \
+- MAKEINCDIR=`pwd` RC_ARCHS="$(RC_ARCHS)"; \
++ MAKEINCDIR="`pwd`" RC_ARCHS="$(RC_ARCHS)"; \
+ fi
+
+ ld.NEW: $(OBJS) ld_vers.o makeUser.o
+@@ -341,8 +350,9 @@
+ makeUser.c ld.c: make.h
+
+ make.h makeUser.c: make.defs
+- $(MIG) $(MIG_FLAGS) $(SRCROOT)/make.defs
+- rm -f makeServer.c
++ #~ $(MIG) $(MIG_FLAGS) $(SRCROOT)/make.defs
++ #~ rm -f makeServer.c
++ cp $(SRCROOT)/makeUser.c .
+
+ ld_vers.o: ld_vers.c
+ ifeq "mwccppc" "$(notdir $(CC))"
+diff -ubr ld/coalesced_sections.c ld/coalesced_sections.c
+--- ld/coalesced_sections.c Tue Jan 14 23:35:24 2003
++++ ld/coalesced_sections.c Mon Aug 25 22:11:47 2003
+@@ -579,15 +579,15 @@
+ /*
+ * The number of relocation entries in the output file is based
+ * on one of three different cases:
+- * The output file is a dynamic shared library file
++ * The output file is a multi module dynamic shared library
+ * The output file has a dynamic linker load command
+ * The output does not have a dynamic linker load command
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /*
+- * For dynamic shared library files the modules are kept
+- * separate so external relocation entries on input will be
+- * external relocation entries on output. For local
++ * For a multi module dynamic shared library the modules are
++ * kept separate so external relocation entries on input
++ * will be external relocation entries on output. For local
+ * relocation entries only non-position-independent local
+ * relocation entries are kept. Modules of dylibs are not
+ * linked together and can only be slid keeping all sections
+diff -ubr ld/dylibs.c ld/dylibs.c
+--- ld/dylibs.c Fri Sep 6 18:27:43 2002
++++ ld/dylibs.c Mon Aug 25 22:11:47 2003
+@@ -116,7 +116,8 @@
+ */
+ __private_extern__
+ void
+-merge_dylibs(void)
++merge_dylibs(
++enum bool force_weak)
+ {
+ unsigned long i;
+ struct mach_header *mh;
+@@ -142,7 +143,9 @@
+ * file. Only record the library itself.
+ */
+ if((lc->cmd != LC_LOAD_DYLIB &&
+- lc->cmd != LC_LOAD_WEAK_DYLIB) || mh->filetype != MH_DYLIB){
++ lc->cmd != LC_LOAD_WEAK_DYLIB) ||
++ (mh->filetype != MH_DYLIB &&
++ mh->filetype != MH_DYLIB_STUB) ){
+ dl = (struct dylib_command *)lc;
+ mdl = lookup_merged_dylib(dl);
+ if(filetype == MH_DYLIB && dylib_install_name != NULL &&
+@@ -151,6 +154,7 @@
+ "same install_name (%s) as the output",
+ dylib_install_name);
+ p = add_dynamic_lib(DYLIB, dl, cur_obj);
++ p->force_weak_dylib = force_weak;
+ mdl->dynamic_library = p;
+ }
+ }
+diff -ubr ld/dylibs.h ld/dylibs.h
+--- ld/dylibs.h Fri Sep 6 18:27:43 2002
++++ ld/dylibs.h Mon Aug 25 12:12:28 2003
+@@ -55,7 +55,7 @@
+ __private_extern__ void create_dylib_id_command(
+ void);
+ __private_extern__ void merge_dylibs(
+- void);
++ enum bool force_weak);
+ __private_extern__ void add_dylib_segment(
+ struct segment_command *sg,
+ char *dylib_name,
+Only in ld: dynamic_profile_obj
+Only in ld: fake-mach.c
+diff -ubr ld/generic_reloc.c ld/generic_reloc.c
+--- ld/generic_reloc.c Tue Jan 14 23:35:24 2003
++++ ld/generic_reloc.c Mon Aug 25 22:11:47 2003
+@@ -351,13 +351,13 @@
+ /*
+ * If the symbol is undefined (or common) or a global coalesced
+ * symbol where we need to force an external relocation entry
+- * and we are not prebinding no relocation is done.
+- * Or if the output file is MH_DYLIB no relocation is done
++ * and we are not prebinding no relocation is done. Or if the
++ * output file is a multi module MH_DYLIB no relocation is done
+ * unless the symbol is a private extern or we are prebinding.
+ */
+ if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) ||
+ (force_extern_reloc == TRUE && prebinding == FALSE) ||
+- (filetype == MH_DYLIB &&
++ ((filetype == MH_DYLIB && multi_module_dylib == TRUE) &&
+ (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) &&
+ prebinding == FALSE) ) )
+ value = 0;
+@@ -728,18 +728,19 @@
+ * For external relocation entries that the symbol is
+ * defined (not undefined or common) but not when we are
+ * forcing an external relocation entry for a global
+- * coalesced symbol and if the output file is not MH_DYLIB
+- * or the symbol is a private extern it is changed to a
+- * local relocation entry using the section that symbol is
+- * defined in. If still undefined or forcing an external
+- * relocation entry for a global coalesced symbol then the
+- * index of the symbol in the output file is set into
+- * r_symbolnum.
++ * coalesced symbol and if the output file is not a multi
++ * module MH_DYLIB or the symbol is a private extern, it is
++ * changed to a local relocation entry using the section
++ * that symbol is defined in. If still undefined or forcing
++ * an external relocation entry for a global coalesced
++ * symbol, then the index of the symbol in the output file
++ * is set into r_symbolnum.
+ */
+ else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF &&
+ (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD &&
+ force_extern_reloc == FALSE &&
+- (filetype != MH_DYLIB ||
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){
+ reloc->r_extern = 0;
+ /*
+diff -ubr ld/hppa_reloc.c ld/hppa_reloc.c
+--- ld/hppa_reloc.c Tue Jan 14 23:35:24 2003
++++ ld/hppa_reloc.c Mon Aug 25 22:11:47 2003
+@@ -384,13 +384,13 @@
+ /*
+ * If the symbol is undefined (or common) or a global coalesced
+ * symbol where we need to force an external relocation entry
+- * and we are not prebinding no relocation is done.
+- * Or if the output file is MH_DYLIB no relocation is done
++ * and we are not prebinding no relocation is done. Or if the
++ * output file is a multi module MH_DYLIB no relocation is done
+ * unless the symbol is a private extern or we are prebinding.
+ */
+ if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) ||
+ (force_extern_reloc == TRUE && prebinding == FALSE) ||
+- (filetype == MH_DYLIB &&
++ ((filetype == MH_DYLIB && multi_module_dylib == TRUE) &&
+ (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) &&
+ prebinding == FALSE) ) )
+ value = 0;
+@@ -807,7 +807,9 @@
+ section_map, r_address) +
+ 8;
+ if(save_reloc == 0 &&
+- (filetype != MH_DYLIB || (r_extern == 1 &&
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
++ (r_extern == 1 &&
+ (merged_symbol->nlist.n_type & N_PEXT) ==
+ N_PEXT)) &&
+ (output_for_dyld == FALSE || r_extern == 0 ||
+@@ -1001,7 +1003,8 @@
+ r_address) +
+ 8);
+ if(save_reloc == 0 &&
+- (filetype != MH_DYLIB || (r_extern == 1 &&
++ ((filetype != MH_DYLIB || multi_module_dylib == FALSE) ||
++ (r_extern == 1 &&
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)) &&
+ (output_for_dyld == FALSE || r_extern == 0 ||
+ (merged_symbol->nlist.n_type & N_TYPE) != N_UNDF) &&
+@@ -1054,18 +1057,19 @@
+ * For external relocation entries that the symbol is
+ * defined (not undefined or common) but not when we are
+ * forcing an external relocation entry for a global
+- * coalesced symbol and if the output file is not MH_DYLIB
+- * or the symbol is a private extern it is changed to a
+- * local relocation entry using the section that symbol is
+- * defined in. If still undefined or forcing an external
+- * relocation entry for a global coalesced symbol then the
+- * index of the symbol in the output file is set into
+- * r_symbolnum.
++ * coalesced symbol and if the output file is not a multi
++ * module MH_DYLIB or the symbol is a private extern, it is
++ * changed to a local relocation entry using the section
++ * that symbol is defined in. If still undefined or forcing
++ * an external relocation entry for a global coalesced
++ * symbol, then the index of the symbol in the output file
++ * is set into r_symbolnum.
+ */
+ else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF &&
+ (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD &&
+ force_extern_reloc == FALSE &&
+- (filetype != MH_DYLIB ||
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){
+ reloc->r_extern = 0;
+ /*
+diff -ubr ld/i860_reloc.c ld/i860_reloc.c
+--- ld/i860_reloc.c Tue Jan 14 23:35:24 2003
++++ ld/i860_reloc.c Mon Aug 25 22:11:47 2003
+@@ -370,13 +370,13 @@
+ /*
+ * If the symbol is undefined (or common) or a global coalesced
+ * symbol where we need to force an external relocation entry
+- * and we are not prebinding no relocation is done.
+- * Or if the output file is MH_DYLIB no relocation is done
++ * and we are not prebinding no relocation is done. Or if the
++ * output file is a multi module MH_DYLIB no relocation is done
+ * unless the symbol is a private extern or we are prebinding.
+ */
+ if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) ||
+ (force_extern_reloc == TRUE && prebinding == FALSE) ||
+- (filetype == MH_DYLIB &&
++ ((filetype == MH_DYLIB && multi_module_dylib == TRUE) &&
+ (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) &&
+ prebinding == FALSE) ) )
+ value = 0;
+@@ -762,19 +762,21 @@
+ * For external relocation entries that the symbol is
+ * defined (not undefined or common) but not when we are
+ * forcing an external relocation entry for a global
+- * coalesced symbol and if the output file is not MH_DYLIB
+- * or the symbol is a private extern it is changed to a
+- * local relocation entry using the section that symbol is
+- * defined in. If still undefined or forcing an external
+- * relocation entry for a global coalesced symbol then the
+- * index of the symbol in the output file is set into
+- * r_symbolnum.
++ * coalesced symbol and if the output file is not a multi
++ * module MH_DYLIB or the symbol is a private extern, it is
++ * changed to a local relocation entry using the section
++ * that symbol is defined in. If still undefined or forcing
++ * an external relocation entry for a global coalesced
++ * symbol, then the index of the symbol in the output file
++ * is set into r_symbolnum.
+ */
+ if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF &&
+ (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD &&
+ force_extern_reloc == FALSE &&
+- (filetype != MH_DYLIB ||
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){
++ reloc->r_extern = 0;
+ reloc->r_extern = 0;
+ /*
+ * If this symbol was in the base file then no futher
+diff -ubr ld/indirect_sections.c ld/indirect_sections.c
+--- ld/indirect_sections.c Tue Jan 14 23:35:24 2003
++++ ld/indirect_sections.c Mon Aug 25 22:11:47 2003
+@@ -370,11 +370,13 @@
+ (merged_symbol->definition_object->section_maps[
+ merged_symbol->nlist.n_sect - 1].
+ s->flags & SECTION_TYPE) == S_COALESCED){
+- if(output_for_dyld && has_dynamic_linker_command &&
++ if((output_for_dyld && has_dynamic_linker_command &&
+ (((merged_symbol->nlist.n_desc & N_WEAK_DEF) !=
+ N_WEAK_DEF) ||
+ ((merged_symbol->nlist.n_type & N_PEXT) == N_PEXT &&
+- keep_private_externs == FALSE) ) )
++ keep_private_externs == FALSE) ) ) ||
++ (filetype == MH_DYLIB && multi_module_dylib == FALSE &&
++ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT) )
+ fine_relocs[i].indirect_defined = TRUE;
+ else
+ fine_relocs[i].indirect_defined = FALSE;
+@@ -386,7 +388,7 @@
+ if((merged_symbol->nlist.n_type & N_TYPE) == N_ABS)
+ section_map->absolute_indirect_defineds = TRUE;
+
+- if(filetype == MH_DYLIB ||
++ if((filetype == MH_DYLIB && multi_module_dylib == TRUE) ||
+ section_type == S_NON_LAZY_SYMBOL_POINTERS ||
+ fine_relocs[i].indirect_defined == FALSE){
+ fine_relocs[i].output_offset = lookup_indirect_item(
+@@ -685,15 +687,16 @@
+ merged_symbol = (struct merged_symbol *)
+ merged_symbol->nlist.n_value;
+ /*
+- * For dynamic shared library format files the merged sections
+- * that could have had external relocation entries must be
+- * resolved to private extern symbols. This is because for
+- * MH_DYLIB files all modules share the merged sections and the
+- * entire section gets relocated when the library is mapped in.
+- * So the above restriction assures the merged section will get
+- * relocated properly and can be shared amoung library modules.
++ * For multi module dynamic shared library format files the
++ * merged sections that could have had external relocation
++ * entries must be resolved to private extern symbols. This is
++ * because for multi module MH_DYLIB files all modules share the
++ * merged sections and the entire section gets relocated when
++ * the library is mapped in. So the above restriction assures
++ * the merged section will get relocated properly and can be
++ * shared amoung library modules.
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /*
+ * If the symbol is undefined or not a private extern it is
+ * an error for in this section for a MH_DYLIB file.
+@@ -704,19 +707,20 @@
+ merged_symbol->defined_in_dylib == TRUE)){
+ if(merged_symbol->error_flagged_for_dylib == 0){
+ error_with_cur_obj("illegal undefined reference "
+- "for MH_DYLIB output file to symbol: %s from "
+- "section (%.16s,%.16s) relocation entry: %lu",
+- merged_symbol->nlist.n_un.n_name,
+- s->segname, s->sectname, i);
++ "for multi module MH_DYLIB output file to "
++ "symbol: %s from section (%.16s,%.16s) "
++ "relocation entry: %lu",
++ merged_symbol->nlist.n_un.n_name, s->segname,
++ s->sectname, i);
+ merged_symbol->error_flagged_for_dylib = 1;
+ }
+ }
+ else if((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT){
+ if(merged_symbol->error_flagged_for_dylib == 0){
+ error_with_cur_obj("illegal external reference for "
+- "MH_DYLIB output file to symbol: %s (not a "
+- "private extern symbol) from section (%.16s,"
+- "%.16s) relocation entry: %lu",
++ "multi module MH_DYLIB output file to symbol: "
++ "%s (not a private extern symbol) from section "
++ "(%.16s,%.16s) relocation entry: %lu",
+ merged_symbol->nlist.n_un.n_name,
+ s->segname, s->sectname, i);
+ merged_symbol->error_flagged_for_dylib = 1;
+@@ -760,18 +764,19 @@
+ /*
+ * The number of relocation entries in the output file is based
+ * on one of three different cases:
+- * The output file is a dynamic shared library file
++ * The output file is a multi module dynamic shared library
+ * The output file has a dynamic linker load command
+ * The output does not have a dynamic linker load command
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /*
+- * For dynamic shared library files there are no external
+- * relocation entries that will be left as external as
+- * checked above. Only non-position-independent local
+- * relocation entries are kept. Modules of dylibs are not
+- * linked together and can only be slid keeping all sections
+- * relative to each other the same.
++ * For multi module dynamic shared library files there are
++ * no external relocation entries that will be left as
++ * external as checked above. Only non-position-independent
++ * local relocation entries are kept. Modules of multi
++ * module dylibs are not linked together and can only be
++ * slid keeping all sections relative to each other the
++ * same.
+ */
+ if(pic == FALSE)
+ ms->nlocrel += 1 + pair;
+@@ -884,7 +889,7 @@
+ #if defined(DEBUG) && defined(PROBE_COUNT)
+ data->nprobes++;
+ #endif
+- hashval = ((long)merged_symbol) % INDIRECT_SECTION_HASHSIZE;
++ hashval = ((unsigned long)merged_symbol) % INDIRECT_SECTION_HASHSIZE;
+ for(bp = data->hashtable[hashval]; bp; bp = bp->next){
+ #if defined(DEBUG) && defined(PROBE_COUNT)
+ data->nprobes++;
+@@ -1296,7 +1301,7 @@
+ if(nindirectsyms == 0)
+ return;
+ if(strip_level == STRIP_ALL)
+- fatal("can't use -s with input files containg indirect symbols "
++ fatal("can't use -s with input files containing indirect symbols "
+ "(output file must contain at least global symbols, for "
+ "maximum stripping use -x)");
+ indirect_symbols = (unsigned long *)(output_addr +
+diff -ubr ld/layout.c ld/layout.c
+--- ld/layout.c Tue Jan 14 23:35:24 2003
++++ ld/layout.c Mon Aug 25 23:22:05 2003
+@@ -42,18 +42,22 @@
+ #include "stuff/openstep_mach.h"
+ #include <mach-o/fat.h>
+ #include <mach-o/loader.h>
+-#import <mach/m68k/thread_status.h>
+-#import <mach/ppc/thread_status.h>
+-#import <mach/m88k/thread_status.h>
+-#import <mach/i860/thread_status.h>
+-#import <mach/i386/thread_status.h>
+-#import <mach/hppa/thread_status.h>
+-#import <mach/sparc/thread_status.h>
++#include <mach/m68k/thread_status.h>
++#include <mach/ppc/thread_status.h>
++#include <mach/m88k/thread_status.h>
++#include <mach/i860/thread_status.h>
++#include <mach/i386/thread_status.h>
++#include <mach/hppa/thread_status.h>
++#include <mach/sparc/thread_status.h>
+ #include <mach-o/nlist.h>
+ #include <mach-o/reloc.h>
++
++#include <mach/kern_return.h>
++
+ #if defined(RLD) && !defined(SA_RLD) && !(defined(KLD) && defined(__STATIC__))
++typedef void NXStream;
+ #include <mach-o/rld.h>
+-#include <streams/streams.h>
++//~ #include <streams/streams.h>
+ #endif /* defined(RLD) && !defined(SA_RLD) &&
+ !(defined(KLD) && defined(__STATIC__)) */
+ #include "stuff/arch.h"
+@@ -73,6 +77,15 @@
+ #include "mach-o/sarld.h"
+ #include "indirect_sections.h"
+
++#if ( defined(__MWERKS__) && !defined(__private_extern__) )
++#define __private_extern__ __declspec(private_extern)
++#elif ( defined(__linux__) && !defined(__private_extern__) )
++#define __private_extern__ extern
++#endif
++
++/** gcc on Linux defines powerpc, if we are compiling on a powerpc. */
++#undef powerpc
++
+ #ifdef RLD
+ __private_extern__ long RLD_DEBUG_OUTPUT_FILENAME_flag;
+ #endif
+@@ -213,8 +226,11 @@
+ if(filetype == MH_EXECUTE ||
+ filetype == MH_BUNDLE ||
+ filetype == MH_DYLIB ||
+- filetype == MH_DYLINKER)
++ filetype == MH_DYLINKER){
+ setup_link_editor_symbols();
++ if(undefined_flag == UNDEFINED_DEFINE_A_WAY)
++ define_undefined_symbols_a_way();
++ }
+ if(filetype == MH_PRELOAD)
+ define_link_editor_preload_symbols(TRUE);
+ #endif /* !defined(RLD) */
+@@ -644,6 +660,7 @@
+ if(strip_level != STRIP_ALL)
+ linkedit_segment.sg.filesize +=
+ (nmerged_symbols
++ - nstripped_merged_symbols
+ + nlocal_symbols
+ - nmerged_symbols_referenced_only_from_dylibs) *
+ sizeof(struct nlist) +
+@@ -998,6 +1015,7 @@
+ if(strip_level != STRIP_ALL){
+ output_symtab_info.symtab_command.nsyms =
+ nmerged_symbols
++ - nstripped_merged_symbols
+ + nlocal_symbols
+ - nmerged_symbols_referenced_only_from_dylibs;
+ output_symtab_info.symtab_command.strsize =
+@@ -1301,20 +1319,21 @@
+
+ #ifdef RLD
+ /*
+- * For rld() the output format is MH_OBJECT and only the contents of the
+- * segment (the entire vmsize not just the filesize) without headers is
+- * allocated and the address the segment is linked to is the address of
+- * this memory.
++ * For rld() the output format is MH_OBJECT and the contents of the
++ * first segment (the entire vmsize not just the filesize), if it exists,
++ * plus headers are allocated and the address the segment is linked to
++ * is the address of this memory.
+ */
+ output_size = 0;
+- if(first_msg != NULL){
+ #ifndef SA_RLD
+ kern_return_t r;
+ #endif
+ unsigned long allocate_size;
+
+ headers_size = round(headers_size, max_align);
+- output_size = headers_size + first_msg->sg.vmsize;
++ output_size = headers_size;
++ if(first_msg != NULL)
++ output_size += first_msg->sg.vmsize;
+ allocate_size = output_size;
+ if(strip_level != STRIP_ALL)
+ allocate_size += output_symtab_info.symtab_command.nsyms *
+@@ -1346,6 +1365,8 @@
+ #endif /* RLD_VM_ALLOC_DEBUG */
+ sets[cur_set].output_addr = output_addr;
+ sets[cur_set].output_size = output_size;
++
++ if(first_msg != NULL){
+ if(address_func != NULL){
+ if(RLD_DEBUG_OUTPUT_FILENAME_flag)
+ first_msg->sg.vmaddr =
+@@ -2194,12 +2215,18 @@
+ (unsigned int)(ms->s.addr +
+ fine_relocs[k].output_offset),
+ (unsigned int)
+- (k == object_file->section_maps[j].
+- nfine_relocs - 1 ?
+- object_file->section_maps[j].s->size -
+- fine_relocs[k].input_offset :
+- fine_relocs[k + 1].input_offset -
+- fine_relocs[k].input_offset));
++ (k == (unsigned int)
++ ((object_file->section_maps[j].
++ nfine_relocs) -
++ (unsigned int)1) ?
++ (unsigned int)
++ (object_file->section_maps[j].s->size) -
++ (unsigned int)(fine_relocs[k].
++ input_offset) :
++ (unsigned int)(fine_relocs[k + 1].
++ input_offset) -
++ (unsigned int)(fine_relocs[k].
++ input_offset)));
+ print_obj_name(object_file);
+ print("\n");
+ }
+diff -ubr ld/ld.c ld/ld.c
+--- ld/ld.c Tue Jan 14 23:35:24 2003
++++ ld/ld.c Mon Aug 25 22:11:47 2003
+@@ -50,6 +50,9 @@
+ #include <mach/mach.h>
+ #include <mach/mach_error.h>
+ #include "stuff/seg_addr_table.h"
++#ifndef RLD
++#include "stuff/symbol_list.h"
++#endif
+ #include "make.h"
+ #include <mach/mach_init.h>
+ #if defined(__OPENSTEP__) || defined(__GONZO_BUNSEN_BEAKER__)
+@@ -91,8 +94,11 @@
+ __private_extern__ char *outputfile = NULL;
+ /* type of output file */
+ __private_extern__ unsigned long filetype = MH_EXECUTE;
++/* multi or single module dylib output */
++__private_extern__ enum bool multi_module_dylib = TRUE;
+ #ifndef RLD
+ static enum bool filetype_specified = FALSE;
++static enum bool moduletype_specified = FALSE;
+ /* if the -A flag is specified use to set the object file type */
+ static enum bool Aflag_specified = FALSE;
+ #endif /* !defined(RLD) */
+@@ -190,6 +196,19 @@
+ /* Strip the base file symbols (the -A argument's symbols) */
+ __private_extern__ enum bool strip_base_symbols = FALSE;
+
++#ifndef RLD
++/*
++ * Data structures to perform selective exporting of global symbols.
++ * save_symbols is the names of the symbols from -exported_symbols_list
++ * remove_symbols is the names of the symbols from -unexported_symbols_list
++ */
++__private_extern__ struct symbol_list *save_symbols = NULL;
++__private_extern__ unsigned long nsave_symbols = 0;
++__private_extern__ struct symbol_list *remove_symbols = NULL;
++__private_extern__ unsigned long nremove_symbols = 0;
++#endif /* RLD */
++
++
+ /* The list of symbols to be traced */
+ __private_extern__ char **trace_syms = NULL;
+ __private_extern__ unsigned long ntrace_syms = 0;
+@@ -251,6 +270,7 @@
+ static enum bool read_only_reloc_flag_specified = FALSE;
+ static enum bool sect_diff_reloc_flag_specified = FALSE;
+ static enum bool weak_reference_mismatches_specified = FALSE;
++static enum bool prebind_all_twolevel_modules_specified = FALSE;
+ #endif
+
+ /* True if -m is specified to allow multiply symbols, as a warning */
+@@ -418,7 +438,8 @@
+ char *argv[],
+ char *envp[])
+ {
+- unsigned long i, j, symbols_created, objects_specified, sections_created;
++ int i;
++ unsigned long j, symbols_created, objects_specified, sections_created;
+ unsigned long table_size;
+ int fd;
+ char *p, *symbol_name, *indr_symbol_name, *endp, *file_name;
+@@ -438,11 +459,16 @@
+ enum weak_reference_mismatches_handling new_weak_reference_mismatches;
+ enum bool is_framework;
+ char *has_suffix;
++ struct symbol_list *sp;
++ char *exported_symbols_list, *unexported_symbols_list;
++ enum bool missing_syms;
+
+ #ifdef __MWERKS__
+ char **dummy;
+ dummy = envp;
+ #endif
++ exported_symbols_list = NULL;
++ unexported_symbols_list = NULL;
+
+ progname = argv[0];
+ #ifndef BINARY_COMPARE
+@@ -487,6 +513,8 @@
+ p = &(argv[i][1]);
+ switch(*p){
+ case 'l':
++ if(p[1] == '\0')
++ fatal("-l: argument missing");
+ /* path searched abbrevated file name, processed in the
+ next pass of parsing arguments */
+ break;
+@@ -559,7 +587,13 @@
+ prebind_allow_overlap = TRUE;
+ }
+ else if(strcmp(p, "prebind_all_twolevel_modules") == 0){
++ if(prebind_all_twolevel_modules_specified == TRUE &&
++ prebind_all_twolevel_modules == FALSE)
++ fatal("both -prebind_all_twolevel_modules and "
++ "-noprebind_all_twolevel_modules can't be "
++ "specified");
+ prebind_all_twolevel_modules = TRUE;
++ prebind_all_twolevel_modules_specified = TRUE;
+ }
+ else if(strcmp(p, "private_bundle") == 0){
+ private_bundle = TRUE;
+@@ -808,6 +842,15 @@
+ else if(strcmp(p, "nomultidefs") == 0){
+ nomultidefs = TRUE;
+ }
++ else if(strcmp(p, "noprebind_all_twolevel_modules") == 0){
++ if(prebind_all_twolevel_modules_specified == TRUE &&
++ prebind_all_twolevel_modules == TRUE)
++ fatal("both -prebind_all_twolevel_modules and "
++ "-noprebind_all_twolevel_modules can't be "
++ "specified");
++ prebind_all_twolevel_modules = FALSE;
++ prebind_all_twolevel_modules_specified = TRUE;
++ }
+ else
+ goto unknown_flag;
+ break;
+@@ -882,6 +925,9 @@
+ static_specified = TRUE;
+ twolevel_namespace = FALSE;
+ }
++ else if(strcmp(p, "search_paths_first") == 0){
++ search_paths_first = TRUE;
++ }
+ /*
+ * Flags for specifing information about sections.
+ */
+@@ -1225,6 +1271,15 @@
+ sub_librarys[nsub_librarys++] = argv[i+1];
+ i += 1;
+ }
++ /* -single_module for MH_DYLIB output */
++ else if(strcmp(p, "single_module") == 0){
++ if(moduletype_specified == TRUE &&
++ multi_module_dylib == TRUE)
++ fatal("can't specify both -single_module and "
++ "-multi_module");
++ moduletype_specified = TRUE;
++ multi_module_dylib = FALSE;
++ }
+ else
+ goto unknown_flag;
+ break;
+@@ -1409,6 +1464,16 @@
+ new_multiply_defined_unused_flag;
+ break;
+ }
++ /* -multi_module for MH_DYLIB output */
++ else if(strcmp(p, "multi_module") == 0){
++ if(moduletype_specified == TRUE &&
++ multi_module_dylib == FALSE)
++ fatal("can't specify both -single_module and "
++ "-multi_module");
++ moduletype_specified = TRUE;
++ multi_module_dylib = TRUE;
++ break;
++ }
+ /* treat multiply defined symbols as a warning not a
+ hard error */
+ if(p[1] != '\0')
+@@ -1426,6 +1491,10 @@
+ new_undefined_flag = UNDEFINED_WARNING;
+ else if(strcmp(argv[i], "suppress") == 0)
+ new_undefined_flag = UNDEFINED_SUPPRESS;
++ else if(strcmp(argv[i], "dynamic_lookup") == 0)
++ new_undefined_flag = UNDEFINED_DYNAMIC_LOOKUP;
++ else if(strcmp(argv[i], "define_a_way") == 0)
++ new_undefined_flag = UNDEFINED_DEFINE_A_WAY;
+ else{
+ fatal("-undefined: unknown argument: %s", argv[i]);
+ new_undefined_flag = UNDEFINED_ERROR;
+@@ -1450,6 +1519,17 @@
+ i += 1;
+ break;
+ }
++ else if(strcmp(p, "unexported_symbols_list") == 0){
++ if(i + 1 >= argc)
++ fatal("%s: argument missing", argv[i]);
++ if(remove_symbols != NULL)
++ fatal("%s: multiply specified", argv[i]);
++ setup_symbol_list(argv[i+1], &remove_symbols,
++ &nremove_symbols);
++ unexported_symbols_list = argv[i+1];
++ i += 1;
++ break;
++ }
+ if(p[1] != '\0')
+ goto unknown_flag;
+ /* cause the specified symbol name to be undefined */
+@@ -1467,6 +1547,17 @@
+ filetype = MH_EXECUTE;
+ break;
+ }
++ else if(strcmp(p, "exported_symbols_list") == 0){
++ if(i + 1 >= argc)
++ fatal("%s: argument missing", argv[i]);
++ if(save_symbols != NULL)
++ fatal("%s: multiply specified", argv[i]);
++ setup_symbol_list(argv[i+1], &save_symbols,
++ &nsave_symbols);
++ exported_symbols_list = argv[i+1];
++ i += 1;
++ break;
++ }
+ /* specify the entry point, the symbol who's value to be
+ used as the program counter in the unix thread */
+ if(p[1] != '\0')
+@@ -1526,6 +1617,26 @@
+ new_weak_reference_mismatches;
+ break;
+ }
++ else if(strcmp(p, "weak_library") == 0){
++ if(i + 1 >= argc)
++ fatal("-weak_library: argument missing");
++ /* object file argv[i] processed in the next pass of
++ parsing arguments */
++ i += 1;
++ }
++ else if(strncmp(p, "weak-l", sizeof("weak-l") - 1) == 0){
++ if(p[sizeof("weak-l") - 1] == '\0')
++ fatal("-weak-l: argument missing");
++ /* path searched abbrevated file name, processed in the
++ next pass of parsing arguments */
++ }
++ else if(strcmp(p, "weak_framework") == 0){
++ if(i + 1 >= argc)
++ fatal("-weak_framework: argument missing");
++ /* path searched abbrevated framework name, processed
++ in the next pass of parsing arguments */
++ i += 1;
++ }
+ else
+ goto unknown_flag;
+ break;
+@@ -1664,7 +1775,7 @@
+ rc_trace_dylibs = TRUE;
+ if(getenv("RC_TRACE_PREBINDING_DISABLED") != NULL)
+ rc_trace_prebinding_disabled = TRUE;
+- if(getenv("XBS_TRACE_BUNDLE_LOADER") != NULL &&
++ if(getenv("LD_TRACE_BUNDLE_LOADER") != NULL &&
+ bundle_loader != NULL)
+ print("[Logging for XBS] Referenced bundle loader: %s\n",
+ bundle_loader);
+@@ -1702,7 +1813,8 @@
+ }
+ if(getenv("LD_PREBIND_ALLOW_OVERLAP") != NULL)
+ prebind_allow_overlap = TRUE;
+- if(getenv("LD_PREBIND_ALL_TWOLEVEL_MODULES") != NULL)
++ if(prebind_all_twolevel_modules_specified == FALSE &&
++ getenv("LD_PREBIND_ALL_TWOLEVEL_MODULES") != NULL)
+ prebind_all_twolevel_modules = TRUE;
+
+ /*
+@@ -1765,6 +1877,31 @@
+ if(save_reloc && strip_base_symbols == TRUE)
+ fatal("can't use -b with -r (resulting file would not be "
+ "relocatable)");
++ if(keep_private_externs == TRUE){
++ if(save_symbols != NULL)
++ fatal("can't use both -keep_private_externs and "
++ "-exported_symbols_list");
++ if(remove_symbols != NULL)
++ fatal("can't use both -keep_private_externs and "
++ "-unexported_symbols_list");
++ }
++ if(save_symbols != NULL && remove_symbols != NULL){
++ for(j = 0; j < nremove_symbols ; j++){
++ sp = bsearch(remove_symbols[j].name,
++ save_symbols, nsave_symbols,
++ sizeof(struct symbol_list),
++ (int (*)(const void *, const void *))
++ symbol_list_bsearch);
++ if(sp != NULL){
++ error("symbol name: %s is listed in both "
++ "-exported_symbols_list and -unexported_symbols_list "
++ "(can't be both exported and unexported)",
++ remove_symbols[j].name);
++ }
++ }
++ if(errors != 0)
++ ld_exit(1);
++ }
+ if(filetype_specified == TRUE && filetype == MH_OBJECT){
+ if(dynamic == TRUE)
+ fatal("incompatible to specifiy -object when -dynamic is used "
+@@ -2032,6 +2169,9 @@
+ if(nallowable_clients != 0)
+ fatal("-allowable_client flags can only be used when -dylib "
+ "is also specified");
++ if(moduletype_specified == TRUE)
++ fatal("-single_module or -multi_module flags can only be used "
++ "when -dylib is also specified");
+ }
+ if(filetype == MH_BUNDLE){
+ if(dynamic == FALSE)
+@@ -2094,9 +2234,26 @@
+ warning("flag: -init %s ignored (-dylib was not specified",
+ init_name);
+ }
+- if(twolevel_namespace == TRUE && undefined_flag != UNDEFINED_ERROR){
+- fatal("-undefined error must be used when -twolevel_namespace is "
+- "in effect");
++ if(twolevel_namespace == TRUE &&
++ undefined_flag != UNDEFINED_ERROR &&
++ undefined_flag != UNDEFINED_DYNAMIC_LOOKUP &&
++ undefined_flag != UNDEFINED_DEFINE_A_WAY){
++ if(macosx_deployment_target >=MACOSX_DEPLOYMENT_TARGET_10_3)
++ fatal("-undefined error, -undefined dynamic_lookup or "
++ "-undefined define_a_way must be used when "
++ "-twolevel_namespace is in effect");
++ else
++ fatal("-undefined error or -undefined define_a_way must be "
++ "used when -twolevel_namespace is in effect");
++ }
++ if(undefined_flag == UNDEFINED_DYNAMIC_LOOKUP){
++ if(dynamic == FALSE)
++ fatal("incompatible flag -undefined dynamic_lookup used (must "
++ "specify \"-dynamic\" to be used)");
++ if(macosx_deployment_target < MACOSX_DEPLOYMENT_TARGET_10_3)
++ fatal("flag: -undefined dynamic_lookup can't be used with "
++ "MACOSX_DEPLOYMENT_TARGET environment variable set to: "
++ "%s", macosx_deployment_target_name);
+ }
+ if(twolevel_namespace == TRUE && nundef_syms != 0){
+ fatal("can't use -U flags when -twolevel_namespace is in effect");
+@@ -2181,10 +2338,9 @@
+ * can have one.
+ */
+ if(seglinkedit_specified == FALSE){
+- if((filetype == MH_EXECUTE || filetype == MH_BUNDLE ||
++ if(filetype == MH_EXECUTE || filetype == MH_BUNDLE ||
+ filetype == MH_FVMLIB ||
+- filetype == MH_DYLIB || filetype == MH_DYLINKER) &&
+- strip_level != STRIP_ALL)
++ filetype == MH_DYLIB || filetype == MH_DYLINKER)
+ seglinkedit = TRUE;
+ else
+ seglinkedit = FALSE;
+@@ -2215,12 +2371,12 @@
+ * output force the bundle_loader to be loaded first.
+ */
+ if(bundle_loader != NULL && twolevel_namespace == FALSE){
+- pass1(bundle_loader, FALSE, FALSE, FALSE, TRUE);
++ pass1(bundle_loader, FALSE, FALSE, FALSE, TRUE, FALSE);
+ }
+ for(i = 1 ; i < argc ; i++){
+ if(*argv[i] != '-'){
+ /* just a normal object file name */
+- pass1(argv[i], FALSE, FALSE, FALSE, FALSE);
++ pass1(argv[i], FALSE, FALSE, FALSE, FALSE, FALSE);
+ objects_specified++;
+ }
+ else{
+@@ -2234,20 +2390,20 @@
+ * loaded first above.
+ */
+ if(twolevel_namespace == TRUE)
+- pass1(argv[i+1], FALSE, FALSE, FALSE, TRUE);
++ pass1(argv[i+1], FALSE, FALSE, FALSE, TRUE, FALSE);
+ i++;
+ break;
+ }
+ break;
+ case 'l':
+ /* path searched abbrevated file name */
+- pass1(argv[i], TRUE, FALSE, FALSE, FALSE);
++ pass1(argv[i], TRUE, FALSE, FALSE, FALSE, FALSE);
+ objects_specified++;
+ break;
+ case 'A':
+ if(base_obj != NULL)
+ fatal("only one -A argument can be specified");
+- pass1(argv[++i], FALSE, TRUE, FALSE, FALSE);
++ pass1(argv[++i], FALSE, TRUE, FALSE, FALSE, FALSE);
+ objects_specified++;
+ break;
+ case 'f':
+@@ -2255,7 +2411,7 @@
+ if(dynamic == FALSE)
+ fatal("incompatible flag -framework used (must "
+ "specify \"-dynamic\" to be used)");
+- pass1(argv[++i], FALSE, FALSE, TRUE, FALSE);
++ pass1(argv[++i], FALSE, FALSE, TRUE, FALSE, FALSE);
+ objects_specified++;
+ }
+ if(strcmp(p, "filelist") == 0){
+@@ -2296,7 +2452,8 @@
+ file_name = mkstr(dirname, "/",
+ file_name, NULL);
+ }
+- pass1(file_name, FALSE, FALSE, FALSE, FALSE);
++ pass1(file_name, FALSE, FALSE, FALSE, FALSE,
++ FALSE);
+ objects_specified++;
+ file_name = addr + j + 1;
+ }
+@@ -2314,7 +2471,8 @@
+ break;
+ case 'u':
+ if(strcmp(p, "undefined") == 0 ||
+- strcmp(p, "umbrella") == 0){
++ strcmp(p, "umbrella") == 0 ||
++ strcmp(p, "unexported_symbols_list") == 0){
+ i++;
+ break;
+ }
+@@ -2421,6 +2579,23 @@
+ case 'w':
+ if(strcmp(p, "weak_reference_mismatches") == 0)
+ i++;
++ else if(strcmp(p, "weak_library") == 0){
++ pass1(argv[++i], FALSE, FALSE, FALSE, FALSE, TRUE);
++ objects_specified++;
++ }
++ else if(strncmp(p, "weak-l", sizeof("weak-l") - 1) == 0){
++ /* path searched abbrevated file name */
++ pass1(argv[i] + sizeof("weak"), TRUE, FALSE, FALSE,
++ FALSE, TRUE);
++ objects_specified++;
++ }
++ else if(strcmp(p, "weak_framework") == 0){
++ if(dynamic == FALSE)
++ fatal("incompatible flag -weak_framework used (must"
++ " specify \"-dynamic\" to be used)");
++ pass1(argv[++i], FALSE, FALSE, TRUE, FALSE, TRUE);
++ objects_specified++;
++ }
+ break;
+ }
+ }
+@@ -2511,6 +2686,38 @@
+ layout();
+
+ /*
++ * Check to that the exported or unexported symbols listed were seen.
++ */
++ if(save_symbols != NULL){
++ missing_syms = FALSE;
++ for(j = 0; j < nsave_symbols ; j++){
++ if(save_symbols[j].seen == FALSE){
++ if(missing_syms == FALSE){
++ error("symbols names listed in "
++ "-exported_symbols_list: %s not in linked "
++ "objects", exported_symbols_list);
++ missing_syms = TRUE;
++ }
++ printf("%s\n", save_symbols[j].name);
++ }
++ }
++ }
++ if(remove_symbols != NULL){
++ missing_syms = FALSE;
++ for(j = 0; j < nremove_symbols ; j++){
++ if(remove_symbols[j].seen == FALSE){
++ if(missing_syms == FALSE){
++ error("symbols names listed in "
++ "-unexported_symbols_list: %s not in linked "
++ "objects", unexported_symbols_list);
++ missing_syms = TRUE;
++ }
++ printf("%s\n", remove_symbols[j].name);
++ }
++ }
++ }
++
++ /*
+ * If there were any errors from layout() then don't continue.
+ */
+ if(errors != 0)
+@@ -2718,7 +2925,9 @@
+ int dummy;
+ dummy = sig;
+ #endif
+- cleanup();
++ if(output_addr != NULL)
++ unlink(outputfile);
++ _exit(1);
+ }
+
+ /*
+diff -ubr ld/ld.h ld/ld.h
+--- ld/ld.h Tue Jan 14 23:35:24 2003
++++ ld/ld.h Mon Aug 25 12:12:29 2003
+@@ -41,6 +41,7 @@
+ STRIP_L_SYMBOLS,
+ STRIP_DEBUG,
+ STRIP_NONGLOBALS,
++ STRIP_DYNAMIC_EXECUTABLE,
+ STRIP_ALL
+ };
+
+@@ -48,7 +49,9 @@
+ enum undefined_check_level {
+ UNDEFINED_ERROR,
+ UNDEFINED_WARNING,
+- UNDEFINED_SUPPRESS
++ UNDEFINED_SUPPRESS,
++ UNDEFINED_DYNAMIC_LOOKUP,
++ UNDEFINED_DEFINE_A_WAY
+ };
+
+ /* The error level check for (twolevel namespace) multiply defined symbols */
+@@ -96,6 +99,8 @@
+ __private_extern__ char *outputfile;
+ /* type of output file */
+ __private_extern__ unsigned long filetype;
++/* multi or single module dylib output */
++__private_extern__ enum bool multi_module_dylib;
+
+ /*
+ * The architecture of the output file as specified by -arch and the cputype
+@@ -161,6 +166,18 @@
+ __private_extern__ enum strip_levels strip_level;
+ /* Strip the base file symbols (the -A argument's symbols) */
+ __private_extern__ enum bool strip_base_symbols;
++
++#ifndef RLD
++/*
++ * Data structures to perform selective exporting of global symbols.
++ * save_symbols is the names of the symbols from -exported_symbols_list
++ * remove_symbols is the names of the symbols from -unexported_symbols_list
++ */
++__private_extern__ struct symbol_list *save_symbols;
++__private_extern__ unsigned long nsave_symbols;
++__private_extern__ struct symbol_list *remove_symbols;
++__private_extern__ unsigned long nremove_symbols;
++#endif /* RLD */
+
+ /* The list of symbols to be traced */
+ __private_extern__ char **trace_syms;
+diff -ubr ld/literal_pointers.c ld/literal_pointers.c
+--- ld/literal_pointers.c Tue Jan 14 23:35:25 2003
++++ ld/literal_pointers.c Mon Aug 25 22:11:47 2003
+@@ -149,8 +149,8 @@
+ */
+ fine_relocs = allocate(nliterals * sizeof(struct fine_reloc));
+ memset(fine_relocs, '\0', nliterals * sizeof(struct fine_reloc));
+- for(i = 0; i < nliterals; i++){
+- fine_relocs[i].output_offset = -1;
++ for(j = 0; j < nliterals; j++){
++ fine_relocs[j].output_offset = -1;
+ }
+ section_map->fine_relocs = fine_relocs;
+ section_map->nfine_relocs = nliterals;
+@@ -374,15 +374,16 @@
+ continue;
+ }
+ /*
+- * For dynamic shared library format files the merged sections that
+- * could have had external relocation entries must be resolved to
+- * private extern symbols. This is because for MH_DYLIB files all
+- * modules share the merged sections and the entire section gets
+- * relocated when the library is mapped in. So the above
+- * restriction assures the merged section will get relocated
+- * properly and can be shared amoung library modules.
++ * For multi module dynamic shared library format files the
++ * merged sections that could have had external relocation
++ * entries must be resolved to private extern symbols. This is
++ * because for multi module MH_DYLIB files all modules share the
++ * merged sections and the entire section gets relocated when
++ * the library is mapped in. So the above restriction assures
++ * the merged section will get relocated properly and can be
++ * shared amoung library modules.
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /*
+ * If the symbol is undefined or not a private extern it is an
+ * error for in this section for a MH_DYLIB file.
+@@ -390,21 +391,22 @@
+ if(merged_symbol->nlist.n_type == (N_EXT | N_UNDF)){
+ if(merged_symbol->error_flagged_for_dylib == 0){
+ error_with_cur_obj("illegal undefined reference for "
+- "MH_DYLIB output file to symbol: %s from a literal "
+- "pointer section (section (%.16s,%.16s) relocation "
+- "entry: %lu)", merged_symbol->nlist.n_un.n_name,
+- s->segname, s->sectname, i);
++ "multi module MH_DYLIB output file to symbol: %s "
++ "from a literal pointer section (section (%.16s,"
++ "%.16s) relocation entry: %lu)",
++ merged_symbol->nlist.n_un.n_name, s->segname,
++ s->sectname, i);
+ merged_symbol->error_flagged_for_dylib = 1;
+ }
+ }
+ else if((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT){
+ if(merged_symbol->error_flagged_for_dylib == 0){
+ error_with_cur_obj("illegal external reference for "
+- "MH_DYLIB output file to symbol: %s (not a private "
+- "extern symbol) from a literal pointer section "
+- "(section (%.16s,%.16s) relocation entry: %lu)",
+- merged_symbol->nlist.n_un.n_name, s->segname,
+- s->sectname, i);
++ "multi module MH_DYLIB output file to symbol: %s "
++ "(not a private extern symbol) from a literal "
++ "pointer section (section (%.16s,%.16s) relocation "
++ "entry: %lu)", merged_symbol->nlist.n_un.n_name,
++ s->segname, s->sectname, i);
+ merged_symbol->error_flagged_for_dylib = 1;
+ }
+ }
+@@ -567,7 +569,7 @@
+ * for this literal does not have an output_offset of -1 it is an error
+ * because we have seen it before.
+ */
+- if(fine_relocs[r_address/4].output_offset != -1){
++ if((int)(fine_relocs[r_address/4].output_offset) != -1){
+ error_with_cur_obj("more than one relocation entry for literal "
+ "pointer at address 0x%x (r_address 0x%x) in section "
+ "(%.16s,%.16s)", (unsigned int)(s->addr + r_address),
+@@ -606,16 +608,16 @@
+ /*
+ * The number of relocation entries in the output file is based
+ * on one of three different cases:
+- * The output file is a dynamic shared library file
++ * The output file is a multi module dynamic shared library
+ * The output file has a dynamic linker load command
+ * The output does not have a dynamic linker load command
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /*
+- * For dynamic shared library files there are no external
+- * relocation entries that will be left as external as
+- * checked above. Only non-sectdiff local relocation
+- * entries are kept. Modules of dylibs are not linked
++ * For a multi module dynamic shared library there are no
++ * external relocation entries that will be left as external as
++ * checked above. Only non-sectdiff local relocation entries
++ * are kept. Modules of multi module dylibs are not linked
+ * together and can only be slid keeping all sections
+ * relative to each other the same.
+ */
+diff -ubr ld/m88k_reloc.c ld/m88k_reloc.c
+--- ld/m88k_reloc.c Tue Jan 14 23:35:25 2003
++++ ld/m88k_reloc.c Mon Aug 25 22:11:47 2003
+@@ -373,13 +373,13 @@
+ /*
+ * If the symbol is undefined (or common) or a global coalesced
+ * symbol where we need to force an external relocation entry
+- * and we are not prebinding no relocation is done.
+- * Or if the output file is MH_DYLIB no relocation is done
++ * and we are not prebinding no relocation is done. Or if the
++ * output file is a multi module MH_DYLIB no relocation is done
+ * unless the symbol is a private extern or we are prebinding.
+ */
+ if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) ||
+ (force_extern_reloc == TRUE && prebinding == FALSE) ||
+- (filetype == MH_DYLIB &&
++ ((filetype == MH_DYLIB && multi_module_dylib == TRUE) &&
+ (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) &&
+ prebinding == FALSE) ) )
+ value = 0;
+@@ -910,18 +910,19 @@
+ * For external relocation entries that the symbol is
+ * defined (not undefined or common) but not when we are
+ * forcing an external relocation entry for a global
+- * coalesced symbol and if the output file is not MH_DYLIB
+- * or the symbol is a private extern it is changed to a
+- * local relocation entry using the section that symbol is
+- * defined in. If still undefined or forcing an external
+- * relocation entry for a global coalesced symbol then the
+- * index of the symbol in the output file is set into
+- * r_symbolnum.
++ * coalesced symbol and if the output file is not a multi
++ * module MH_DYLIB or the symbol is a private extern, it is
++ * changed to a local relocation entry using the section
++ * that symbol is defined in. If still undefined or forcing
++ * an external relocation entry for a global coalesced
++ * symbol, then the index of the symbol in the output file
++ * is set into r_symbolnum.
+ */
+ else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF &&
+ (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD &&
+ force_extern_reloc == FALSE &&
+- (filetype != MH_DYLIB ||
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){
+ reloc->r_extern = 0;
+ /*
+Only in ld: make.h
+Only in ld: makeUser.c
+diff -ubr ld/mod_sections.c ld/mod_sections.c
+--- ld/mod_sections.c Tue Jan 14 23:35:25 2003
++++ ld/mod_sections.c Mon Aug 25 22:11:47 2003
+@@ -56,8 +56,8 @@
+ */
+ static struct merged_section *dylib_ms_init = NULL;
+ static struct merged_section *dylib_ms_term = NULL;
+-static unsigned long ninit = 0;
+-static unsigned long nterm = 0;
++__private_extern__ unsigned long ninit = 0;
++__private_extern__ unsigned long nterm = 0;
+ #endif /* !defined(RLD) */
+
+ /*
+diff -ubr ld/mod_sections.h ld/mod_sections.h
+--- ld/mod_sections.h Tue Apr 30 00:37:20 2002
++++ ld/mod_sections.h Mon Aug 25 12:12:29 2003
+@@ -28,6 +28,8 @@
+ /*
+ * Global types, variables and routines declared in the file modinit_sections.c.
+ */
++__private_extern__ unsigned long ninit;
++__private_extern__ unsigned long nterm;
+
+ __private_extern__ void mod_section_merge(
+ void *data,
+diff -ubr ld/notes ld/notes
+--- ld/notes Tue Jan 14 23:35:25 2003
++++ ld/notes Mon Aug 25 12:12:29 2003
+@@ -23,6 +23,420 @@
+ - For m68k builds -finline-functions crashes the compiler (used in the Makefile
+ on the ld_build target).
+
++Changes for the 5.12 release (the cctools-477 release):
++- Picked up changes to kld interfaces. Changes in rld.c and layout.c .
++ Radar bug #3270588.
++
++Changes for the 5.12 release (the cctools-473 release):
++- Fixed a bug with the use of a modulus operator on a signed value which caused
++ a crash. The fix was to cast to unsigned long not long. The problem was in
++ lookup_indirect_item() in indirect_sections.c when it used the modulus
++ operator to come up with a hash value. Radar bug #3255992.
++
++Changes for the 5.12 release (the cctools-472 release):
++- Moved the #ifndef RLD in output_local_symbols() in symbols.c down so that
++ the call to swap_nlist() is not ifdef'ed out. This allows cross building of
++ a kernel's symbol file with kld. Radar bug #3251273.
++
++Changes for the 5.12 release (the cctools-471 release):
++- Backed out the change to call to _exit() in ld_exit() in ld.c in Radar bug
++ #3237013 as it does not flush the stdio buffers. Then changed the handler()
++ routine in ld.c used for signals to not call ld_exit() and instead unlink(2)
++ the output file if one was created and call _exit(1). Radar bug #3245341.
++- Fixed a problem in the kld libraries where the code that was not ignoring the
++ alignment of non-regular non-zerofill sections from the base file. A missing
++ #ifdef KLD and test of the base file was needed on one more place in
++ merge_sections() in sections.c . Radar bug #3245534.
++
++Changes for the 5.12 release (the cctools-470 release):
++- Changed the call to exit() in ld_exit() in ld.c to _exit as it was causing a
++ hang in dyld when used with signal handlers. Radar bug #3237013.
++- Added the flag -search_paths_first to cause -lx flags to search each path
++ for .dylib then .a before searching next path. Radar bug #3176974.
++ - Added the enum bool variable search_paths_first to pass1.c and pass1.h and
++ code to parse out the option and set variable in main() in ld.c .
++ - The new static routines search_paths_for_lname() and search_path_for_lname()
++ were added to pass1.c .
++ - In pass1() in pass1.c a test of the new search_paths_first variable is done
++ and if TRUE then search_paths_for_lname() is called.
++
++Changes for the 5.12 release (the cctools-468 release):
++- Added support to force a dynamic library to be marked weak in the output.
++ This can be done using these three flags:
++ -weak_framework Foo
++ -weak-lx
++ -weak_library library_filename
++ Radar bug #3069758.
++ - Added parsing out "-weak_framework", "-weak-lx"and "-weak_library" to
++ ld.c and calling pass1() with the force_weak parameter as TRUE.
++ - Added the new boolean parameter force_weak to pass1() in pass1.c and
++ pass1.h . Changed the existing calls to pass1() in ld.c to pass the new
++ boolean parameter force_weak as FALSE.
++ - Added the new boolean parameter force_weak to pass1_fat(), pass1_archive()
++ and pass1_object() in pass1.c . Propagated the passing of this new
++ parameter down through the calls. And passed it as FALSE in call to
++ pass1_fat() and pass1_object() from open_dylib().
++ - Added the new boolean parameter force_weak to merge() in pass1.c . And
++ passed this as the parameter force_weak parameter or FALSE in the existing
++ calls.
++ - Added the new boolean parameter force_weak to merge_dylibs() in dylibs.c and
++ dylibs.h . After the call to add_dynamic_lib() the parameter force_weak is
++ set into the field force_weak_dylib in the dynamic_library struct.
++ - Added the boolean field force_weak_dylib to the dynamic_library structure
++ in pass1.h .
++ - Changed merge_dylib_module_symbols() in symbols.c to test the
++ force_weak_dylib field of the dynamic_library structure and if TRUE set the
++ N_WEAK_REF bit on the merged symbol to mark the symbol as a weak reference.
++
++Changes for the 5.12 release (the cctools-468 release):
++- Added support for the new use of the previously unused value 3 for r_length
++ to mean that the conditional branch was predicted using the Y-bit and the
++ sign of the displacement and opcode. Radar bug #3223045.
++ - Changed ppc_reloc() in ppc_reloc.c to correctly flip the Y-bit for
++ PPC_RELOC_BR14 r_types with an r_length value of 3 for branch conditions
++ that are not branch always and the sign of the displacement is different
++ after relocation.
++- Fixed a problem when linking against stub libraries that the dependencies of
++ the stub libraries were getting recored in the output file. This caused them
++ to have LC_LOAD_DYLIB load commands which inturn messed up the recorded
++ library ordinals. The fix is in merge_dylibs() in dylibs.c to add a check
++ that the object's file type was not MH_DYLIB_STUB. Radar bug #3220772.
++
++Changes for the 5.12 release (the cctools-467 release):
++- Added support for the PPC_RELOC_LO14_SECTDIFF relocation type used with
++ double word load/store instructions. Radar bug #3218027.
++ - Changed ppc_reloc() in ppc_reloc.c treat a PPC_RELOC_LO14_SECTDIFF as it
++ other PowerPC section difference relocation entries and expect it to have
++ a pair. And added cases for PPC_RELOC_LO14_SECTDIFF to relocate it as it
++ would for PPC_RELOC_LO14.
++
++Changes for the 5.12 release (the cctools-466 release):
++- Added the new treatment of "-undefined define_a_way" to define all undefined
++ symbols as private extern symbols. This is a temporary work around to not
++ having dead-code stripping that also strips the undefined references from
++ dead code. Radar bug 3216770.
++ - Added the undefined_check_level enum UNDEFINED_DEFINE_A_WAY to ld.h .
++ - Added parsing out "-undefined define_a_way" in main() in ld.c and modified
++ checks to allow its use with -twolevel_namespace.
++ - Added the define_a_way bit field in the merged_symbol struct in symbols.h .
++ - Added the define_undefined_symbols_a_way() routine to symbols.c and
++ symbols.h . This routines sets up the undefined symbols to be defined and
++ sets the define_a_way bit field in the merged_symbol.
++ - Added code at the end of define_link_editor_dylib_symbols() in symbols.c to
++ loop through the symbol table and set the address of the symbols with the
++ define_a_way bit field set.
++ - In layout() in layout.c after it sets up the link editor defined symbols
++ a check of the undefined_flag for UNDEFINED_DEFINE_A_WAY is made and if so
++ a call to define_undefined_symbols_a_way() is made.
++- Fixed the incorrect casts on the comparison of the nlist struct's n_strx field
++ where the value being compared to was casted to a long. The correct fix was
++ to cast n_strx to an unsigned long.
++- Added the "-undefined dynamic_lookup" option for use in two-level namespace
++ images to all undefined symbols to be looked up dynamically with flat
++ namespace semantics. Radar bug #3210803.
++ - Added the undefined_check_level enum UNDEFINED_DYNAMIC_LOOKUP to ld.h .
++ - Added parsing out "-undefined dynamic_lookup" in main() in ld.c and modified
++ checks to allow its use with -twolevel_namespace. Also added checks when
++ "-undefined dynamic_lookup" is not allowed for -static and when
++ MACOSX_DEPLOYMENT_TARGET is less than 10.3 .
++ - Changed process_undefineds() in symbols.c to changed its check of
++ undefined_flag != UNDEFINED_SUPPRESS
++ to
++ (undefined_flag == UNDEFINED_ERROR ||
++ undefined_flag == UNDEFINED_WARNING)
++ and added an else cause to that if to check if undefined_flag is
++ UNDEFINED_DYNAMIC_LOOKUP and then set the library ordinal to
++ DYNAMIC_LOOKUP_ORDINAL if -r is not used and two-level namespace is in
++ effect.
++ - Changed check_symbol() in symbols.c to not treat a symbol with the library
++ ordinal DYNAMIC_LOOKUP_ORDINAL as an error.
++ - Changed merge_dylib_module_symbols() in symbols.c in the second loop that
++ loops through the symbols referenced by the dylib module when it is doing
++ symbol tracing to check the library_ordinal for DYNAMIC_LOOKUP_ORDINAL.
++ And if it is DYNAMIC_LOOKUP_ORDINAL not use it as a library ordinal and
++ let it just get printed as an unbounded reference.
++ - Changed merge_dylib_module_symbols() in symbols.c in the second loop where
++ it resolves the undefined references and changed the logic where it selects
++ how to resolve the symbol. It now sets a new boolean, resolve_flat, based
++ on the old logic plus looking at library_ordinal for DYNAMIC_LOOKUP_ORDINAL.
++ - Changed search_dynamic_libs() in pass1.c when it is has an undefined symbol
++ from a two-level namespace image to check the library ordinal for
++ DYNAMIC_LOOKUP_ORDINAL and if so treat it an internal error. Since the
++ above change to merge_dylib_module_symbols() should never let this happen.
++ - Also added this same check as above and internal error message to
++ process_undefineds() in symbols.c in two places. Also added a missing
++ check in the loop looking for previous undefined two-level namespace symbols
++ that did not check the twolevel_reference field before using the
++ library_ordinal. And added a check for DYNAMIC_LOOKUP_ORDINAL in the
++ loop the prints the references in the -Y loop.
++
++Changes for the 5.12 release (the cctools-464 release):
++- Changed the they way N_BINCL stabs with non-zero n_value fields are handled so
++ the n_value is not changed. Radar bug #3201935.
++ - Added field input_N_BINCL_n_value to the struct localsym_block in symbols.h
++ - In merged_symbols() in symbols.c when a new N_BINCL is found the n_value
++ of the N_BINCL nlist is saved in the input_N_BINCL_n_value field. And if
++ not zero the variable sum is set to that value. Later when a new symbol in
++ the group in encountered if input_N_BINCL_n_value is not zero then the
++ string for that symbol is not sum'ed.
++
++Changes for the 5.12 release (the cctools-464 release):
++- Made changes to build cleanly with gcc3.3
++ - Removed -Wno-precomp from the Makefile
++ - Fixed warnings for "comparison between signed and unsigned" in ld.c,
++ layout.c, pass2.c, literal_pointers.c, pass1.c, rld.c and sets.c .
++
++Changes for the 5.12 release (the cctools-463 release):
++- Added support for linking against MH_DYLIB_STUB libraries. Radar bug #3193744.
++ - Added a check for the MH_DYLIB_STUB filetype along with MH_DYLIB in
++ merge_symbols() in symbols.c .
++ - Added the testing of the filetype not being MH_DYLIB_STUB along with
++ testing of the section type not being S_ZEROFILL before checking the size
++ and offset of the section contents in check_cur_obj() in pass1.c .
++ - Added the testing for MH_DYLIB_STUB along with MH_DYLIB in a few places
++ in check_cur_obj() in pass1.c for various error checks.
++ - Changed the setting of cur_obj->dylib in check_cur_obj() in pass1.c to
++ include the MH_DYLIB_STUB filetype.
++
++Changes for the 5.12 release (the cctools-462 release):
++- Fixed a bug in the displacement overflow checking of a PPC_RELOC_BR14
++ relocation entry. The mask that was used was 0xfffe0000 which should
++ have been 0xffff8000 in the PPC_RELOC_BR14 cases in ppc_reloc.c .
++ Radar bug #3190434.
++
++Changes for the 5.12 release (the cctools-457 release):
++- For the -single_module dylib case the symbol stubs for coalesced private
++ extern symbols were not being removed when they could be. The change is in
++ indirect_section_merge() in indirect_sections.c after the test if the
++ merged symbol is a coalesced symbol the if statement on line 373. An
++ additional case was added to the if expression such that if the output file
++ is a dylib and not multi-module and the symbol is private extern then the
++ expression is TRUE and indirect_defined is set to TRUE. Radar bug #3163714.
++
++Changes for the 5.12 release (the cctools-456 release):
++- Changed XBS_TRACE_BUNDLE_LOADER to LD_TRACE_BUNDLE_LOADER in ld.c. Radar bug
++ #3152604.
++
++Changes for the 5.12 release (the cctools-454 release):
++- Fixed a bug when using the -m flag and having a multiple definition of a
++ private extern symbol. The problem was in merge_symbols the counts of
++ private exterals are first incremented. Then after multiply_defined() is
++ called a check was needed to see if allow_multiply_defined_symbols is TRUE
++ (the -m flag specified) and the counts for private exterals needed to be
++ decremented. Radar bug #3143764.
++- Fixed a bug when creating an indirect symbol when the referenced symbol is
++ a private extern symbol that causes an internal overlap error. Radar bug
++ #3134759.
++ - Added code in reduce_indr_symbols() in symbols.c so the N_PEXT bit is
++ checked and then the counts of private exterals (nmerged_private_symbols)
++ and the object's count (nprivatesym) are incremented.
++ - Changed assign_output_symbol_indexes() in symbols.c to check the N_PEXT
++ bit of the indirect symbol if the symbol is N_INDR to correctly determine
++ if the symbol is a private extern symbol in the two places it checks this
++ bit.
++
++Changes for the 5.12 release (the cctools-450 release):
++- Added some double quotes in the Makefile around uses of `pwd` to be "`pwd`" so
++ if this were in a directory with a space it would work. Radar bug #3114622.
++- Changed is_output_local_symbol() in symbols.c to strip symbols in sections
++ with the S_ATTR_STRIP_STATIC_SYMS attribute. To do this n_ssect and the
++ object struct that the symbol came from is passed to is_output_local_symbol().
++ Radar bug #3114458.
++- Changed the -x flag to strip private externs that will be local symbols in the
++ output file. Radar bug #3114182.
++ - Changed is_output_local_symbol() in symbols.c for the STRIP_NONGLOBALS case
++ (the -x flag) to return FALSE causing all local symbols to be stripped.
++ This strips private externs that were local symbols in the input object
++ files.
++ - Changed assign_output_symbol_indexes() in symbols.c to rebuild the merged
++ string table if we are stripping non-globals and we are not keeping private
++ externs and we have some private externs in the merged symbol table, and the
++ output is not a multi-module dylib. Then if this is the case the number of
++ private externs in each object is added to nstripped_merged_symbols so those
++ symbols are not counted.
++ - Changed output_merged_symbols() in symbols.c to check the strip_level for
++ STRIP_NONGLOBALS, and the output is not a multi-module dylib and not put ou
++ private externs in this case.
++
++Changes for the 5.12 release (the cctools-447 release):
++- Fixed a problem with -x not stripping STABS with the P_EXT bit on them. The
++ odd stab:
++ 00000000 - 00 0000 3c gcc2_compiled.
++ was not stripped because of a bug in is_output_local_symbol() in symbols.c in
++ the STRIP_NONGLOBALS because it did not first check for N_STAB bits in n_type.
++ Radar bug #3104019.
++- Added the -noprebind_all_twolevel_modules flag that overrides the setting
++ of the environment variable LD_PREBIND_ALL_TWOLEVEL_MODULES. The changes are
++ in ld.c . Radar bug #3055372.
++- Fixed a bug that was causing dynamic libraries that had nothing referenced in
++ them that also were used indirectly that did have symbols indirectly
++ referenced in them to be LC_LOAD_WEAK_DYLIB. The problem was that references
++ from dylibs that were were causing the some_symbols_referenced field to be
++ set for the dylib. The fix was to merge_dylib_module_symbols() symbols.c
++ where it sets some_symbols_referenced. Radar bug #3094497.
++- Removed the const off of link_edit_common_object in symbols.[ch] to get rid
++ of warnings and since it is now written on.
++
++Changes for the 5.11 release (the cctools-446 release):
++- Changed it so that when -s is used on a dynamic dynamic executable it rebuilds
++ the string table in assign_output_symbol_indexes() in symbols.c so that the
++ symbol names for the discarded symbols don't end up in the string table.
++ Radar bug #3089997.
++- Fixed a bug when using an export list and not listing a common symbol would
++ cause an internal overlap error. Radar bug #3088916.
++ - Changed define_common_symbols() in symbols.c right after
++ exports_list_processing() is called to check the N_PEXT bit and increment
++ the counts of private exterals. Both the object's count (nprivatesym) and
++ the global count (nmerged_private_symbols).
++ - Changed assign_output_symbol_indexes() in symbols.c to add the
++ link_edit_common_object object to the list of objects before counting
++ and assigning indexes to private extern symbols. Then at the end of the
++ loop copying back the updated object and taking it back off the list.
++
++Changes for the 5.11 release (the cctools-445 release):
++- Changed the semantics of -s on dynamic executables to do the same stripping
++ as strip(1) with no arguments. That is only save undefined symbols and
++ global symbols marked referenced dynamically. Radar bug #2545288.
++ - Added the STRIP_DYNAMIC_EXECUTABLE enum value to strip_levels in ld.h .
++ - Added the variable nstripped_merged_symbols to symbols.c and symbols.h to
++ set to the number of merged symbol being stripped out. This is non-zero
++ when the strip_level is STRIP_DYNAMIC_EXECUTABLE.
++ - Changed assign_output_symbol_indexes() in symbols.c so that if strip_level
++ is STRIP_ALL and has_dynamic_linker_command is set to change strip_level
++ to STRIP_DYNAMIC_EXECUTABLE;
++ - Changed assign_output_symbol_indexes() to assign indexes to only undefined
++ symbols and global symbols marked referenced dynamically and add up the
++ number of merged symbol being stripped out into nstripped_merged_symbols.
++ - Added the case label for STRIP_DYNAMIC_EXECUTABLE in
++ is_output_local_symbol() in symbols.c to also return FALSE.
++ - Changed output_merged_symbols() in symbols.c to check the strip_level for
++ STRIP_DYNAMIC_EXECUTABLE and the REFERENCED_DYNAMICALLY of the symbol
++ and not put out those symbols in that case.
++ - Changed layout_segments() in layout.c when setting the
++ linkedit_segment.sg.filesize and output_symtab_info.symtab_command.nsyms
++ to subtract nstripped_merged_symbols.
++ - Fixed a typo in an error message in output_indirect_symbols() in
++ indirect_sections.c (changed "containg" to "containing").
++
++Changes for the 5.11 release (the cctools-444 release):
++- Added the -exported_symbols_list and -unexported_symbols_list flags. Radar
++ bug #3083844.
++ - Changes in ld.c and ld.h for adding the save_symbols and remove_symbols
++ variables and parsing and checking the flags. As well as checking to see
++ that the symbols were seen after pass1.
++ - Changed merge_symbol() in symbols.c to check if the symbol is on the
++ save_symbols or remove_symbols list and set the N_PEXT bit as needed.
++- Fixed a problem with ppc JSR's and doing an ld -r where the JBSR has an
++ external relocation entry and the symbol is not defined in the output.
++ The code in ppc_reloc.c was:
++ if(r_extern){
++ value += offset;
++ other_half = value;
++ }
++ else{
++ value += other_half;
++ other_half = value;
++ }
++ And in the case of an external relocation entry where the symbol was
++ undefined 'offset' was not set. For JBSR external relocation entries the
++ offset part of "symbol+offset" is stored in the PAIR relocation entry in
++ 'other_half'. This is because the displacement of the bl instruction is for
++ the branch island. So the correct code works out to be the same as the
++ non-extern case and was changed to just this:
++ value += other_half;
++ other_half = value;
++ Radar bug #3054747.
++
++Changes for the 5.11 release (the cctools-443 release):
++- Added the -single_module and -multi_module flags. Radar bug #3080780.
++ - Changes in ld.c and ld.h for adding the boolean multi_module_dylib and
++ parsing and checking the flags.
++ - Changed one place in coalesced_sections.c in coalesced_section_merge()
++ where the number of relocation is determined. The MH_DYLIB case was changed
++ to include multi_module_dylib == TRUE.
++ - Changed two places in the relocation routines in generic_reloc.c,
++ i860_reloc.c, m88k_reloc.c, sparc_reloc.c, hppa_reloc.c and ppc_reloc.c.
++ For external relocation entries where the symbol is defined, if the output
++ file is a multi_module dylib no relocation is done unless the symbol is a
++ private extern or we are prebinding. In this case the relocation entry is
++ left as extern. For single_module dylibs the relocation is done and the
++ relocation entry turned into a local relocation entry.
++ - Changed two places in the relocation routines in hppa_reloc.c and
++ ppc_reloc.c for JBSR relocations. The JBSR relocation code does not do
++ relocation if multi_module dylib. but will do it for a single_module dylib.
++ - Changed indirect_sections.c in indirect_section_merge() in three places:
++ - The fine relocation entry for defined external symbols are kept in dylibs
++ if it is a multi_module dylib (not kept for single_module dylibs).
++ - The check external relocation entries resolving to private extern being is
++ flagged as an error is only done for multi_module dylibs.
++ - The code that counts up the relocation entries, was changed in the dylib
++ case to include multi_module_dylib == TRUE.
++ - Changed literal_pointers.c in two places:
++ - In literal_pointer_merge() the check external relocation entries resolving
++ to private extern being is flagged as an error is only done for
++ multi_module dylibs.
++ - In the static count_reloc() routine where the number of relocation is
++ determined, the MH_DYLIB case was changed to include
++ multi_module_dylib == TRUE.
++ - Changed objects.c in three places:
++ - In object_index() zero is returned when multi_module_dylib == FALSE.
++ - In fine_reloc_output_address() if the reloc is in a symbol stub section
++ and the symbol is defined and it is not in a multi_module dylib then
++ the merge symbol value from the fine_reloc is used.
++ - In fine_reloc_output_sectnum() if the reloc is in a symbol stub section
++ and the symbol is defined and it is not in a multi_module dylib then
++ the merge symbol section number from the fine_reloc is used.
++ - Changed sections.c in three places:
++ - In layout_relocs_for_dyld() the check that merged sections don't have
++ any external relocation entries in dylibs had multi_module_dylib == TRUE
++ added to it.
++ - In count_relocs() the dylib case for the code counting the number of
++ relocation entries had multi_module_dylib == TRUE added to it.
++ - In reloc_output_for_dyld() a matching change for the above change to
++ count_relocs() was made for the dylib case addin multi_module_dylib ==TRUE
++ to it.
++ - Changed many places in symbols.c:
++ - In the routine merge_symbols()
++ - The number of defined externals is now only counted in the multi
++ module dylib case (need to be able allocate the reference maps).
++ - For a merged symbol that is a weak definition that is discarded, the
++ symbol counts for the reference map are adjusted and the reference
++ flags are updated only in the multi_module dylib case.
++ - The reference map flags are only set in the multi_module dylib case.
++ - In the routine command_line_symbol() and command_line_indr_symbol() the
++ reference map flags are set only in the multi_module dylib case.
++ - In the routine merge_dylib_module_symbols() and
++ merge_bundle_loader_symbols() for a merged symbol that is a weak
++ definition that is discarded, the symbol counts for the reference map are
++ adjusted and the reference flags are updated only in the multi_module
++ dylib case.
++ - In define_common_symbols() a check for multi_module dylib is made and
++ it is an error if there is a common symbol to define. Also the traceing
++ of commons is not done in dylib if multi_module_dylib == TRUE.
++ - In setup_link_editor_symbols() the code is not changed for the one place
++ that MH_DYLIB is used. As the reference table will be ignored and
++ output_dysymtab_info.dysymtab_command.nextrefsyms will be reset
++ layout_dylib_tables() for single module dylibs.
++ - In output_merged_symbols() the N_INDR symbols are set to the defining
++ symbol if it is a multi_module dylib and defined in the same object or
++ in a single module dylib.
++ - In layout_dylib_tables() the existing code for the reference table and
++ module table where placed in if statements with multi_module_dylib == TRUE
++ and new code was added for the single module case. For the reference
++ table its size is reset based on the defined and undefined merged symbols.
++ The module table size is one and a variable, dylib_single_module_name, was
++ added to save the pointer to the module name in the merged symbol table.
++ - In output_dylib_tables() the existing code for the reference table and
++ module table where placed in if statements with multi_module_dylib == TRUE
++ and new code was added for the single module case. For the reference
++ table its is built from the merged symbol table's defined and undefined
++ symbols. The one module table entry is built from the a variable,
++ dylib_single_module_name, which is a pointer to the module name in the
++ merged symbol table and the values in output_dysymtab_info.
++ -Changed mod_sections.c and mod_sections.h so that ninit and nterm were
++ __private_extern__ so that output_dylib_tables() in symbols.c could use
++ them for the single module dylib module table entry.
++
+ Changes for the 5.11 release (the cctools-440 release):
+ - Fixed the warnings about extra tokens at end of #endif directive in
+ 4byte_literals.c, 8byte_literals.c, coalesced_sections.c, cstring_literals.c,
+diff -ubr ld/objects.c ld/objects.c
+--- ld/objects.c Tue Jan 14 23:35:25 2003
++++ ld/objects.c Mon Aug 25 22:11:47 2003
+@@ -110,7 +110,7 @@
+ /*
+ * object_index() returns the index into the module table for a object file
+ * structure. It is only used in the creation of the table of contents entries
+- * in a MH_DYLIB file.
++ * in a multi module MH_DYLIB file.
+ */
+ __private_extern__
+ unsigned long
+@@ -121,6 +121,8 @@
+ struct object_list *object_list, **p;
+ struct object_file *cmp_obj;
+
++ if(multi_module_dylib == FALSE)
++ return(0);
+ index = 0;
+ for(p = &objects; *p; p = &(object_list->next)){
+ object_list = *p;
+@@ -417,6 +419,7 @@
+ else if((map->s->flags & SECTION_TYPE) == S_SYMBOL_STUBS &&
+ fine_reloc->indirect_defined == TRUE){
+ if(filetype != MH_DYLIB ||
++ (filetype == MH_DYLIB && multi_module_dylib == FALSE) ||
+ (cur_obj == fine_reloc->merged_symbol->definition_object &&
+ input_offset - fine_reloc->input_offset == 0)){
+ if(cur_obj == fine_reloc->merged_symbol->definition_object)
+@@ -559,7 +562,7 @@
+ }
+ else if((map->s->flags & SECTION_TYPE) == S_SYMBOL_STUBS &&
+ fine_reloc->indirect_defined == TRUE &&
+- filetype != MH_DYLIB){
++ (filetype != MH_DYLIB || multi_module_dylib == FALSE)){
+ merged_symbol = (struct merged_symbol *)fine_reloc->output_offset;
+ if((merged_symbol->nlist.n_type & N_TYPE) == N_INDR)
+ merged_symbol = (struct merged_symbol *)
+diff -ubr ld/pass1.c ld/pass1.c
+--- ld/pass1.c Tue Jan 14 23:35:25 2003
++++ ld/pass1.c Mon Aug 25 22:11:47 2003
+@@ -71,6 +71,9 @@
+ #include "sets.h"
+
+ #ifndef RLD
++/* TRUE if -search_paths_first was specified */
++__private_extern__ enum bool search_paths_first = FALSE;
++
+ /* the user specified directories to search for -lx names, and the number
+ of them */
+ __private_extern__ char **search_dirs = NULL;
+@@ -156,6 +159,15 @@
+ char *name,
+ char **file_name,
+ int *fd);
++static void search_paths_for_lname(
++ const char *lname_argument,
++ char **file_name,
++ int *fd);
++static void search_path_for_lname(
++ const char *dir,
++ const char *lname_argument,
++ char **file_name,
++ int *fd);
+ #endif /* !defined(RLD) */
+
+ static void pass1_fat(
+@@ -164,7 +176,8 @@
+ unsigned long file_size,
+ enum bool base_name,
+ enum bool dylib_only,
+- enum bool bundle_loader);
++ enum bool bundle_loader,
++ enum bool force_weak);
+
+ static void pass1_archive(
+ char *file_name,
+@@ -172,7 +185,8 @@
+ unsigned long file_size,
+ enum bool base_name,
+ enum bool from_fat_file,
+- enum bool bundle_loader);
++ enum bool bundle_loader,
++ enum bool force_weak);
+
+ static enum bool check_archive_arch(
+ char *file_name,
+@@ -192,7 +206,8 @@
+ enum bool base_name,
+ enum bool from_fat_file,
+ enum bool dylib_only,
+- enum bool bundle_loader);
++ enum bool bundle_loader,
++ enum bool force_weak);
+
+ #ifndef RLD
+ static void load_init_dylib_module(
+@@ -295,7 +310,8 @@
+ enum bool lname,
+ enum bool base_name,
+ enum bool framework_name,
+-enum bool bundle_loader)
++enum bool bundle_loader,
++enum bool force_weak)
+ {
+ int fd;
+ char *file_name;
+@@ -335,13 +351,22 @@
+ }
+ else{
+ if(dynamic == TRUE){
++ if(search_paths_first == TRUE){
++ search_paths_for_lname(&name[2], &file_name, &fd);
++ }
++ else{
+ p = mkstr("lib", &name[2], ".dylib", NULL);
+ search_for_file(p, &file_name, &fd);
+- }
+ if(fd == -1){
+ p = mkstr("lib", &name[2], ".a", NULL);
+ search_for_file(p, &file_name, &fd);
+ }
++ }
++ }
++ else{
++ p = mkstr("lib", &name[2], ".a", NULL);
++ search_for_file(p, &file_name, &fd);
++ }
+ if(fd == -1)
+ fatal("can't locate file for: %s", name);
+ free(p);
+@@ -444,15 +469,15 @@
+ new_archive_or_fat(file_name, file_addr, file_size);
+ #endif /* RLD */
+ pass1_fat(file_name, file_addr, file_size, base_name, FALSE,
+- bundle_loader);
++ bundle_loader, force_weak);
+ }
+ else if(file_size >= SARMAG && strncmp(file_addr, ARMAG, SARMAG) == 0){
+ pass1_archive(file_name, file_addr, file_size, base_name, FALSE,
+- bundle_loader);
++ bundle_loader, force_weak);
+ }
+ else{
+ pass1_object(file_name, file_addr, file_size, base_name, FALSE,
+- FALSE, bundle_loader);
++ FALSE, bundle_loader, force_weak);
+ }
+ #ifdef VM_SYNC_DEACTIVATE
+ vm_msync(mach_task_self(), (vm_address_t)file_addr,
+@@ -524,6 +549,65 @@
+ }
+ }
+ }
++
++/*
++ * search_paths_for_lname() takes the argument to a -lx option and and trys to
++ * open a file with the name libx.dylib or libx.a. This routine is only used
++ * when the -search_paths_first option is specified and -dynamic is in effect.
++ * And looks for a file name ending in .dylib then .a in each directory before
++ * looking in the next directory. The list of the -L search directories and in
++ * the standard directories are searched in that order. If this is sucessful
++ * it returns a pointer to the file name indirectly through file_name and the
++ * open file descriptor indirectly through fd.
++ */
++static
++void
++search_paths_for_lname(
++const char *lname_argument,
++char **file_name,
++int *fd)
++{
++ unsigned long i;
++
++ *fd = -1;
++ for(i = 0; i < nsearch_dirs ; i++){
++ search_path_for_lname(search_dirs[i], lname_argument, file_name,fd);
++ if(*fd != -1)
++ return;
++ }
++ for(i = 0; standard_dirs[i] != NULL ; i++){
++ search_path_for_lname(standard_dirs[i],lname_argument,file_name,fd);
++ if(*fd != -1)
++ return;
++ }
++}
++
++/*
++ * search_path_for_lname() takes the argument to a -lx option and and trys to
++ * open a file with the name libx.dylib then libx.a in the specified directory
++ * name. This routine is only used when the -search_paths_first option is
++ * specified and -dynamic is in effect. If this is sucessful it returns a
++ * pointer to the file name indirectly through file_name and the open file
++ * descriptor indirectly through fd.
++ */
++static
++void
++search_path_for_lname(
++const char *dir,
++const char *lname_argument,
++char **file_name,
++int *fd)
++{
++ *file_name = mkstr(dir, "/", "lib", lname_argument, ".dylib", NULL);
++ if((*fd = open(*file_name, O_RDONLY)) != -1)
++ return;
++ free(*file_name);
++
++ *file_name = mkstr(dir, "/", "lib", lname_argument, ".a", NULL);
++ if((*fd = open(*file_name, O_RDONLY)) != -1)
++ return;
++ free(*file_name);
++}
+ #endif /* !defined(RLD) */
+
+ #ifndef RLD
+@@ -549,7 +633,8 @@
+ unsigned long file_size,
+ enum bool base_name,
+ enum bool dylib_only,
+-enum bool bundle_loader)
++enum bool bundle_loader,
++enum bool force_weak)
+ {
+ struct fat_header *fat_header;
+ #ifdef __LITTLE_ENDIAN__
+@@ -671,11 +756,11 @@
+ goto pass1_fat_return;
+ }
+ pass1_archive(file_name, arch_addr, arch_size,
+- base_name, TRUE, bundle_loader);
++ base_name, TRUE, bundle_loader, force_weak);
+ }
+ else{
+ pass1_object(file_name, arch_addr, arch_size, base_name, TRUE,
+- dylib_only, bundle_loader);
++ dylib_only, bundle_loader, force_weak);
+ }
+ goto pass1_fat_return;
+ }
+@@ -697,11 +782,11 @@
+ goto pass1_fat_return;
+ }
+ pass1_archive(file_name, arch_addr, arch_size, base_name, TRUE,
+- bundle_loader);
++ bundle_loader, force_weak);
+ }
+ else{
+ pass1_object(file_name, arch_addr, arch_size, base_name, TRUE,
+- dylib_only, bundle_loader);
++ dylib_only, bundle_loader, force_weak);
+ }
+ goto pass1_fat_return;
+ }
+@@ -729,11 +814,11 @@
+ goto pass1_fat_return;
+ }
+ pass1_archive(file_name, arch_addr, arch_size,
+- base_name, TRUE, bundle_loader);
++ base_name, TRUE, bundle_loader, force_weak);
+ }
+ else{
+ pass1_object(file_name, arch_addr, arch_size, base_name, TRUE,
+- dylib_only, bundle_loader);
++ dylib_only, bundle_loader, force_weak);
+ }
+ goto pass1_fat_return;
+ }
+@@ -867,7 +952,8 @@
+ unsigned long file_size,
+ enum bool base_name,
+ enum bool from_fat_file,
+-enum bool bundle_loader)
++enum bool bundle_loader,
++enum bool force_weak)
+ {
+ unsigned long i, j, offset;
+ #ifndef RLD
+@@ -1153,7 +1239,7 @@
+ print_obj_name(cur_obj);
+ print("loaded because of -all_load flag\n");
+ }
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, force_weak);
+ length = round(ar_size + ar_name_size, sizeof(short));
+ offset = (offset - ar_name_size) + length;
+ }
+@@ -1271,7 +1357,7 @@
+ if(toc_byte_sex != host_byte_sex)
+ swap_ranlib(ranlibs, nranlibs, host_byte_sex);
+ for(i = 0; i < nranlibs; i++){
+- if(ranlibs[i].ran_un.ran_strx >= (long)string_size){
++ if(ranlibs[i].ran_un.ran_strx >= string_size){
+ error("malformed table of contents in: %s (ranlib struct %lu "
+ "has bad string index, can't load from it)", file_name,i);
+ return;
+@@ -1383,7 +1469,7 @@
+ print("loaded because of -ObjC flag to get symbol: %s\n",
+ bsearch_strings + ranlibs[i].ran_un.ran_strx);
+ }
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, force_weak);
+ }
+ free(loaded_offsets);
+ }
+@@ -1515,7 +1601,7 @@
+ undefined->merged_symbol->nlist.n_un.n_name);
+ }
+
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, force_weak);
+
+ /* make sure this symbol got defined */
+ if(errors == 0 &&
+@@ -1613,7 +1699,7 @@
+ merged_symbol->nlist.n_un.n_name);
+ }
+
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, force_weak);
+
+ /* make sure this symbol got defined */
+ if(errors == 0 &&
+@@ -1829,7 +1915,8 @@
+ enum bool base_name,
+ enum bool from_fat_file,
+ enum bool dylib_only,
+-enum bool bundle_loader)
++enum bool bundle_loader,
++enum bool force_weak)
+ {
+ #ifdef __MWERKS__
+ enum bool dummy;
+@@ -1855,7 +1942,7 @@
+ base_obj = cur_obj;
+ #endif /* !defined(RLD) */
+
+- merge(dylib_only, bundle_loader);
++ merge(dylib_only, bundle_loader, force_weak);
+
+ #ifndef RLD
+ /*
+@@ -2349,6 +2436,18 @@
+ undefined->merged_symbol->nlist.n_desc);
+ if(library_ordinal == SELF_LIBRARY_ORDINAL)
+ p = undefined->merged_symbol->referencing_library;
++ /*
++ * Note that if library_ordinal was DYNAMIC_LOOKUP_ORDINAL then
++ * merge_dylib_module_symbols() in symbols.c would not have
++ * set the twolevel_reference field to TRUE in the merged_symbol
++ * and if we get here it with this it is an internal error.
++ */
++ else if(library_ordinal == DYNAMIC_LOOKUP_ORDINAL)
++ fatal("internal error: search_dynamic_libs() with a "
++ "merged_symbol (%s) on the undefined list with "
++ "twolevel_reference == TRUE and library_ordinal == "
++ "DYNAMIC_LOOKUP_ORDINAL", undefined->merged_symbol->
++ nlist.n_un.n_name);
+ else
+ p = undefined->merged_symbol->referencing_library->
+ dependent_images[library_ordinal - 1];
+@@ -2615,7 +2714,7 @@
+ undefined->merged_symbol->nlist.n_un.n_name);
+ }
+
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, FALSE);
+
+ /* make sure this symbol got defined */
+ if(errors == 0 &&
+@@ -2688,7 +2787,7 @@
+ undefined->merged_symbol->nlist.n_un.n_name);
+ }
+
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, FALSE);
+
+ /* make sure this symbol got defined */
+ if(errors == 0 &&
+@@ -3464,11 +3563,12 @@
+ if(fat_header->magic == SWAP_LONG(FAT_MAGIC))
+ #endif /* __LITTLE_ENDIAN__ */
+ {
+- pass1_fat(file_name, file_addr, file_size, FALSE, TRUE, FALSE);
++ pass1_fat(file_name, file_addr, file_size, FALSE, TRUE, FALSE,
++ FALSE);
+ }
+ else{
+ pass1_object(file_name, file_addr, file_size, FALSE, FALSE, TRUE,
+- FALSE);
++ FALSE, FALSE);
+ }
+ if(errors)
+ return(FALSE);
+@@ -3800,7 +3900,8 @@
+ void
+ merge(
+ enum bool dylib_only,
+-enum bool bundle_loader)
++enum bool bundle_loader,
++enum bool force_weak)
+ {
+ unsigned long previous_errors;
+
+@@ -3857,7 +3958,7 @@
+ /* if this object has any dynamic shared library stuff merge it */
+ if(cur_obj->dylib_stuff){
+ #ifndef RLD
+- merge_dylibs();
++ merge_dylibs(force_weak);
+ if(errors)
+ goto merge_return;
+ if(cur_obj->dylib)
+@@ -3898,9 +3999,9 @@
+ * the dysymtab field, the section_maps and nsection_maps fields (this routine
+ * allocates the section_map structures and fills them in too), the fvmlib_
+ * stuff field is set if any SG_FVMLIB segments or LC_LOADFVMLIB commands are
+- * seen and the dylib_stuff field is set if the file is a MH_DYLIB type and
+- * has a LC_ID_DYLIB command or a LC_LOAD_DYLIB or LC_LOAD_WEAK_DLIB command is
+- * seen.
++ * seen and the dylib_stuff field is set if the file is a MH_DYLIB or
++ * MH_DYLIB_STUB type and has a LC_ID_DYLIB command or a LC_LOAD_DYLIB or
++ * LC_LOAD_WEAK_DLIB command is seen.
+ */
+ static
+ void
+@@ -4161,17 +4262,20 @@
+ return;
+ }
+ if((mh->flags & MH_DYLDLINK) != 0 &&
+- (mh->filetype != MH_DYLIB && mh->filetype != MH_DYLINKER) &&
++ (mh->filetype != MH_DYLIB &&
++ mh->filetype != MH_DYLIB_STUB &&
++ mh->filetype != MH_DYLINKER) &&
+ bundle_loader == FALSE){
+ error_with_cur_obj("is input for the dynamic link editor, is not "
+ "relocatable by the static link editor again");
+ return;
+ }
+ /*
+- * If this is a MH_DYLIB file then a single LC_ID_DYLIB command must be
+- * seen to identify the library.
++ * If this is a MH_DYLIB or MH_DYLIB_STUB file then a single LC_ID_DYLIB
++ * command must be seen to identify the library.
+ */
+- cur_obj->dylib = (enum bool)(mh->filetype == MH_DYLIB);
++ cur_obj->dylib = (enum bool)(mh->filetype == MH_DYLIB ||
++ mh->filetype == MH_DYLIB_STUB);
+ dlid = NULL;
+ dylib_id_name = NULL;
+ if(cur_obj->dylib == TRUE && dynamic == FALSE){
+@@ -4348,7 +4452,8 @@
+ return;
+ }
+ /* check the size and offset of the contents if it has any*/
+- if(section_type != S_ZEROFILL){
++ if(mh->filetype != MH_DYLIB_STUB &&
++ section_type != S_ZEROFILL){
+ check_size_offset_sect(s->size, s->offset, sizeof(char),
+ "size", "offset", i, j, s->segname, s->sectname);
+ if(errors)
+@@ -4569,14 +4674,16 @@
+ filetype == MH_FVMLIB ? "MH_FVMLIB" : "MH_DYLINKER");
+ return;
+ }
+- if(mh->filetype != MH_DYLIB){
++ if(mh->filetype != MH_DYLIB && mh->filetype != MH_DYLIB_STUB){
+ error_with_cur_obj("LC_ID_DYLIB load command in non-"
+- "MH_DYLIB filetype");
++ "%s filetype", mh->filetype == MH_DYLIB ? "MH_DYLIB" :
++ "MH_DYLIB_STUB");
+ return;
+ }
+ if(dlid != NULL){
+ error_with_cur_obj("malformed object (more than one "
+- "LC_ID_DYLIB load command in MH_DYLIB file)");
++ "LC_ID_DYLIB load command in %s file)", mh->filetype ==
++ MH_DYLIB ? "MH_DYLIB" : "MH_DYLIB_STUB");
+ return;
+ }
+ dl = (struct dylib_command *)lc;
+@@ -4655,14 +4762,17 @@
+ filetype == MH_FVMLIB ? "MH_FVMLIB" : "MH_DYLINKER");
+ return;
+ }
+- if(mh->filetype != MH_DYLIB){
++ if(mh->filetype != MH_DYLIB && mh->filetype != MH_DYLIB_STUB){
+ error_with_cur_obj("LC_SUB_FRAMEWORK load command in non-"
+- "MH_DYLIB filetype");
++ "%s filetype", mh->filetype == MH_DYLIB ? "MH_DYLIB" :
++ "MH_DYLIB_STUB");
+ return;
+ }
+ if(sub != NULL){
+ error_with_cur_obj("malformed object (more than one "
+- "LC_SUB_FRAMEWORK load command in MH_DYLIB file)");
++ "LC_SUB_FRAMEWORK load command in %s file)",
++ mh->filetype == MH_DYLIB ? "MH_DYLIB" :
++ "MH_DYLIB_STUB");
+ return;
+ }
+ sub = (struct sub_framework_command *)lc;
+@@ -4699,9 +4809,10 @@
+ filetype == MH_FVMLIB ? "MH_FVMLIB" : "MH_DYLINKER");
+ return;
+ }
+- if(mh->filetype != MH_DYLIB){
++ if(mh->filetype != MH_DYLIB && mh->filetype != MH_DYLIB_STUB){
+ error_with_cur_obj("LC_SUB_UMBRELLA load command in non-"
+- "MH_DYLIB filetype");
++ "%s filetype", mh->filetype == MH_DYLIB ? "MH_DYLIB" :
++ "MH_DYLIB_STUB");
+ return;
+ }
+ usub = (struct sub_umbrella_command *)lc;
+@@ -4738,9 +4849,10 @@
+ filetype == MH_FVMLIB ? "MH_FVMLIB" : "MH_DYLINKER");
+ return;
+ }
+- if(mh->filetype != MH_DYLIB){
++ if(mh->filetype != MH_DYLIB && mh->filetype != MH_DYLIB_STUB){
+ error_with_cur_obj("LC_SUB_LIBRARY load command in non-"
+- "MH_DYLIB filetype");
++ "%s filetype", mh->filetype == MH_DYLIB ? "MH_DYLIB" :
++ "MH_DYLIB_STUB");
+ return;
+ }
+ lsub = (struct sub_library_command *)lc;
+@@ -4777,9 +4889,10 @@
+ filetype == MH_FVMLIB ? "MH_FVMLIB" : "MH_DYLINKER");
+ return;
+ }
+- if(mh->filetype != MH_DYLIB){
++ if(mh->filetype != MH_DYLIB && mh->filetype != MH_DYLIB_STUB){
+ error_with_cur_obj("LC_SUB_CLIENT load command in non-"
+- "MH_DYLIB filetype");
++ "%s filetype", mh->filetype == MH_DYLIB ? "MH_DYLIB" :
++ "MH_DYLIB_STUB");
+ return;
+ }
+ csub = (struct sub_client_command *)lc;
+@@ -5092,12 +5205,14 @@
+ }
+ }
+ /*
+- * If this is a MH_DYLIB file then a single LC_ID_DYLIB command must be
+- * seen to identify the library.
++ * If this is a MH_DYLIB or MH_DYLIB_STUB file then a single
++ * LC_ID_DYLIB command must be seen to identify the library.
+ */
+- if(mh->filetype == MH_DYLIB && dlid == NULL){
++ if((mh->filetype == MH_DYLIB || mh->filetype == MH_DYLIB_STUB) &&
++ dlid == NULL){
+ error_with_cur_obj("malformed object (no LC_ID_DYLIB load command "
+- "in MH_DYLIB file)");
++ "in %s file)", mh->filetype == MH_DYLIB ?
++ "MH_DYLIB" : "MH_DYLIB_STUB");
+ return;
+ }
+ /*
+diff -ubr ld/pass1.h ld/pass1.h
+--- ld/pass1.h Tue Jan 14 23:35:25 2003
++++ ld/pass1.h Mon Aug 25 12:12:29 2003
+@@ -33,6 +33,9 @@
+ */
+
+ #ifndef RLD
++/* TRUE if -search_paths_first was specified */
++__private_extern__ enum bool search_paths_first;
++
+ /* the user specified directories to search for -lx filenames, and the number
+ of them */
+ __private_extern__ char **search_dirs;
+@@ -84,6 +87,7 @@
+ enum bool indirect_twolevel_ref_flagged;
+ enum bool some_non_weak_refs;
+ enum bool some_symbols_referenced;
++ enum bool force_weak_dylib;
+ struct object_file *definition_obj;
+ char *dylib_file; /* argument to -dylib_file "install_name:file_name" */
+ struct dylib_table_of_contents *tocs;
+@@ -125,10 +129,12 @@
+ enum bool lname,
+ enum bool base_name,
+ enum bool framework_name,
+- enum bool bundle_loader);
++ enum bool bundle_loader,
++ enum bool force_weak);
+ __private_extern__ void merge(
+ enum bool dylib_only,
+- enum bool bundle_loader);
++ enum bool bundle_loader,
++ enum bool force_weak);
+ __private_extern__ void check_fat(
+ char *file_name,
+ unsigned long file_size,
+diff -ubr ld/pass2.c ld/pass2.c
+--- ld/pass2.c Tue Jan 14 23:35:25 2003
++++ ld/pass2.c Mon Aug 25 22:11:47 2003
+@@ -336,7 +336,7 @@
+ /*
+ * Write the entire object file.
+ */
+- if(write(fd, output_addr, output_size) != output_size)
++ if(write(fd, output_addr, output_size) != (int)output_size)
+ system_fatal("can't write output file");
+
+ if((r = vm_deallocate(mach_task_self(), (vm_address_t)output_addr,
+@@ -858,7 +858,8 @@
+ write_offset, write_size);
+ #endif /* DEBUG */
+ lseek(fd, write_offset, L_SET);
+- if(write(fd, output_addr + write_offset, write_size) != write_size)
++ if(write(fd, output_addr + write_offset, write_size) !=
++ (int)write_size)
+ system_fatal("can't write to output file");
+ if((r = vm_deallocate(mach_task_self(), (vm_address_t)(output_addr +
+ write_offset), write_size)) != KERN_SUCCESS)
+@@ -919,7 +920,8 @@
+ write_offset, write_size);
+ #endif /* DEBUG */
+ lseek(fd, write_offset, L_SET);
+- if(write(fd, output_addr + write_offset, write_size) != write_size)
++ if(write(fd, output_addr + write_offset, write_size) !=
++ (int)write_size)
+ system_fatal("can't write to output file");
+ if((r = vm_deallocate(mach_task_self(), (vm_address_t)(output_addr +
+ write_offset), write_size)) != KERN_SUCCESS)
+diff -ubr ld/ppc_reloc.c ld/ppc_reloc.c
+--- ld/ppc_reloc.c Tue Jan 14 23:35:25 2003
++++ ld/ppc_reloc.c Mon Aug 25 22:11:47 2003
+@@ -242,6 +242,7 @@
+ else if(r_type == PPC_RELOC_SECTDIFF ||
+ r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
++ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF){
+ if(r_scattered != 1){
+ error_with_cur_obj("relocation entry (%lu) in section "
+@@ -390,13 +391,13 @@
+ /*
+ * If the symbol is undefined (or common) or a global coalesced
+ * symbol where we need to force an external relocation entry
+- * and we are not prebinding no relocation is done.
+- * Or if the output file is MH_DYLIB no relocation is done
++ * and we are not prebinding no relocation is done. Or if the
++ * output file is a multi module MH_DYLIB no relocation is done
+ * unless the symbol is a private extern or we are prebinding.
+ */
+ if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) ||
+ (force_extern_reloc == TRUE && prebinding == FALSE) ||
+- (filetype == MH_DYLIB &&
++ ((filetype == MH_DYLIB && multi_module_dylib == TRUE) &&
+ (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) &&
+ prebinding == FALSE) ) )
+ value = 0;
+@@ -512,6 +513,7 @@
+ if(r_type == PPC_RELOC_SECTDIFF ||
+ r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
++ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF){
+ pair_local_map =
+ &(cur_obj->section_maps[pair_r_symbolnum - 1]);
+@@ -523,6 +525,7 @@
+ if(r_type == PPC_RELOC_SECTDIFF ||
+ r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
++ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF){
+ value = - local_map->s->addr
+ + (local_map->output_section->s.addr +
+@@ -609,6 +612,7 @@
+ other_half;
+ break;
+ case PPC_RELOC_LO14:
++ case PPC_RELOC_LO14_SECTDIFF:
+ value = (other_half << 16) |
+ (instruction & 0xfffc);
+ break;
+@@ -634,6 +638,7 @@
+ if(r_type == PPC_RELOC_SECTDIFF ||
+ r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
++ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF){
+ /*
+ * For PPC_RELOC_SECTDIFF's the item to be
+@@ -788,6 +793,7 @@
+ ((value >> 16) & 0xffff);
+ break;
+ case PPC_RELOC_LO14:
++ case PPC_RELOC_LO14_SECTDIFF:
+ if((value & 0x3) != 0)
+ error_with_cur_obj("relocation error "
+ "for relocation entry %lu in section "
+@@ -808,8 +814,8 @@
+ "multiple of 4 bytes)", i,
+ section_map->s->segname,
+ section_map->s->sectname);
+- if((value & 0xfffe0000) != 0xfffe0000 &&
+- (value & 0xfffe0000) != 0x00000000)
++ if((value & 0xffff8000) != 0xffff8000 &&
++ (value & 0xffff8000) != 0x00000000)
+ error_with_cur_obj("relocation overflow "
+ "for relocation entry %lu in section "
+ "(%.16s,%.16s) (displacement too large)"
+@@ -817,6 +823,19 @@
+ section_map->s->sectname);
+ instruction = (instruction & 0xffff0003) |
+ (value & 0xfffc);
++ /*
++ * If this is a predicted branch conditional
++ * (r_length is 3) where the branch condition
++ * is not branch always and the sign of the
++ * displacement is different after relocation
++ * then flip the Y-bit to preserve the sense of
++ * the branch prediction.
++ */
++ if(r_length == 3 &&
++ (instruction & 0xfc000000) == 0x40000000 &&
++ (instruction & 0x03e00000) != 0x02800000 &&
++ (instruction & 0x00008000) != br14_disp_sign)
++ instruction ^= (1 << 21);
+ break;
+ case PPC_RELOC_BR24:
+ if((value & 0x3) != 0)
+@@ -847,7 +866,9 @@
+ + fine_reloc_output_offset(
+ section_map, r_address);
+ if(save_reloc == 0 &&
+- (filetype != MH_DYLIB || (r_extern == 1 &&
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
++ (r_extern == 1 &&
+ (merged_symbol->nlist.n_type & N_PEXT) ==
+ N_PEXT)) &&
+ (output_for_dyld == FALSE || r_extern == 0 ||
+@@ -968,6 +989,7 @@
+ other_half = immediate & 0xffff;
+ break;
+ case PPC_RELOC_LO14:
++ case PPC_RELOC_LO14_SECTDIFF:
+ immediate = (other_half << 16) |
+ (instruction & 0xfffc);
+ immediate += value;
+@@ -991,14 +1013,28 @@
+ "entry %lu in section (%.16s,%.16s) (displacement "
+ "not a multiple of 4 bytes)", i,
+ section_map->s->segname, section_map->s->sectname);
+- if((immediate & 0xfffe0000) != 0xfffe0000 &&
+- (immediate & 0xfffe0000) != 0x00000000)
++ if((immediate & 0xffff8000) != 0xffff8000 &&
++ (immediate & 0xffff8000) != 0x00000000)
+ error_with_cur_obj("relocation overflow for relocation "
+ "entry %lu in section (%.16s,%.16s) (displacement "
+ "too large)", i, section_map->s->segname,
+ section_map->s->sectname);
+ instruction = (instruction & 0xffff0003) |
+ (immediate & 0xfffc);
++ /*
++ * If this is a predicted branch conditional
++ * (r_length is 3) where the branch condition
++ * is not branch always and the sign of the
++ * displacement is different after relocation
++ * then flip the Y-bit to preserve the sense of
++ * the branch prediction.
++ */
++ if(r_length == 3 &&
++ (instruction & 0xfc000000) == 0x40000000 &&
++ (instruction & 0x03e00000) != 0x02800000 &&
++ (instruction & 0x00008000) != br14_disp_sign)
++ instruction ^= (1 << 21);
++ break;
+ break;
+ case PPC_RELOC_BR24:
+ immediate = instruction & 0x03fffffc;
+@@ -1020,14 +1056,8 @@
+ (immediate & 0x03fffffc);
+ break;
+ case PPC_RELOC_JBSR:
+- if(r_extern){
+- value += offset;
+- other_half = value;
+- }
+- else{
+ value += other_half;
+ other_half = value;
+- }
+ if(section_map->nfine_relocs == 0)
+ value += - (section_map->output_section->s.addr +
+ section_map->offset + r_address);
+@@ -1036,7 +1066,8 @@
+ fine_reloc_output_offset(section_map,
+ r_address));
+ if(save_reloc == 0 &&
+- (filetype != MH_DYLIB || (r_extern == 1 &&
++ ((filetype != MH_DYLIB || multi_module_dylib == FALSE) ||
++ (r_extern == 1 &&
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)) &&
+ (output_for_dyld == FALSE || r_extern == 0 ||
+ (merged_symbol->nlist.n_type & N_TYPE) != N_UNDF) &&
+@@ -1087,18 +1118,19 @@
+ * For external relocation entries that the symbol is
+ * defined (not undefined or common) but not when we are
+ * forcing an external relocation entry for a global
+- * coalesced symbol and if the output file is not MH_DYLIB
+- * or the symbol is a private extern it is changed to a
+- * local relocation entry using the section that symbol is
+- * defined in. If still undefined or forcing an external
+- * relocation entry for a global coalesced symbol then the
+- * index of the symbol in the output file is set into
+- * r_symbolnum.
++ * coalesced symbol and if the output file is not a multi
++ * module MH_DYLIB or the symbol is a private extern, it is
++ * changed to a local relocation entry using the section
++ * that symbol is defined in. If still undefined or forcing
++ * an external relocation entry for a global coalesced
++ * symbol, then the index of the symbol in the output file
++ * is set into r_symbolnum.
+ */
+ else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF &&
+ (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD &&
+ force_extern_reloc == FALSE &&
+- (filetype != MH_DYLIB ||
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){
+ reloc->r_extern = 0;
+ /*
+@@ -1251,6 +1283,7 @@
+ if(r_type == PPC_RELOC_SECTDIFF ||
+ r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
++ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF){
+ /*
+ * For PPC_RELOC_SECTDIFF relocation entries (which
+@@ -1269,6 +1302,7 @@
+ pair_local_map->output_section->s.addr);
+ if(r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
++ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF)
+ spair_reloc->r_address = other_half;
+ }
+diff -ubr ld/rld.c ld/rld.c
+--- ld/rld.c Tue Jan 14 23:35:25 2003
++++ ld/rld.c Mon Aug 25 22:11:47 2003
+@@ -56,11 +56,13 @@
+ #include "stuff/openstep_mach.h"
+ #include <mach-o/fat.h>
+ #include <mach-o/nlist.h>
+-#ifdef KLD
++//~ #ifdef KLD
+ #include <mach-o/kld.h>
+-#else /* !defined(KLD) */
++#ifndef KLD
++//~ #else /* !defined(KLD) */
++typedef void NXStream;
+ #include <mach-o/rld.h>
+-#include <streams/streams.h>
++//~ #include <streams/streams.h>
+ #include <objc/zone.h>
+ #endif /* KLD */
+ #include <mach-o/rld_state.h>
+@@ -104,6 +106,9 @@
+ unsigned long (*address_func)(unsigned long size, unsigned long headers_size) =
+ NULL;
+
++static
++enum strip_levels kld_requested_strip_level = STRIP_ALL;
++
+ #if !defined(SA_RLD) && !(defined(KLD) && defined(__STATIC__))
+ /*
+ * The function pointer passed to moninitrld() to do profiling of rld loaded
+@@ -198,12 +203,12 @@
+ long base_size);
+ #endif /* !defined(SA_RLD) && !defined(KLD) */
+
+-#if defined(KLD) && !defined(__STATIC__)
++#if defined(KLD)
+ static long internal_kld_load_basefile(
+ const char *base_filename,
+ char *base_addr,
+ long base_size);
+-#endif /* defined(KLD) && !defined(__STATIC__) */
++#endif /* defined(KLD) */
+
+ #if !defined(SA_RLD) && !defined(KLD)
+ /*
+@@ -413,7 +418,7 @@
+ if(output_filename != NULL)
+ strip_level = STRIP_NONE;
+ else
+- strip_level = STRIP_ALL;
++ strip_level = kld_requested_strip_level;
+
+ /* This must be cleared for each call to rld() */
+ errors = 0;
+@@ -522,7 +527,8 @@
+ #if !defined(SA_RLD) && !(defined(KLD) && defined(__STATIC__))
+ if(file_name == NULL){
+ for(i = 0; object_filenames[i] != NULL; i++)
+- pass1((char *)object_filenames[i], FALSE, FALSE, FALSE, FALSE);
++ pass1((char *)object_filenames[i], FALSE, FALSE, FALSE, FALSE,
++ FALSE);
+ }
+ else
+ #endif /* !defined(SA_RLD) && !(defined(KLD) && defined(__STATIC__)) */
+@@ -533,7 +539,7 @@
+ cur_obj->user_obj_addr = TRUE;
+ cur_obj->obj_addr = (char *)obj_addr;
+ cur_obj->obj_size = obj_size;
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, FALSE);
+ }
+
+ if(errors){
+@@ -612,7 +618,7 @@
+ * Write the entire output file.
+ */
+ if(write(fd, output_addr, output_size + symbol_size) !=
+- output_size + symbol_size){
++ (int)(output_size + symbol_size)){
+ system_error("can't write output file: %s",output_filename);
+ #ifdef KLD
+ internal_kld_unload(TRUE);
+@@ -635,8 +641,14 @@
+ * Deallocate the pages of memory for the symbol table if there are
+ * any whole pages.
+ */
++ if (strip_level == STRIP_ALL)
+ deallocate_size = round(output_size + symbol_size, host_pagesize) -
+ round(output_size, host_pagesize);
++ else {
++ deallocate_size = 0;
++ sets[cur_set].output_size += symbol_size;
++ }
++
+ if(deallocate_size > 0){
+ if((r = vm_deallocate(mach_task_self(),
+ (vm_address_t)(output_addr +
+@@ -777,18 +789,20 @@
+ return(1);
+ }
+
+-#if !defined(SA_RLD) && !(defined(KLD) && defined(__STATIC__))
++#if !defined(SA_RLD)
+ /*
+ * rld_load_basefile() loads a base file from an object file rather than just
+ * picking up the link edit segment from this program.
+ */
+ #if defined(KLD)
++#if !defined(__STATIC__)
+ long
+ kld_load_basefile(
+ const char *base_filename)
+ {
+ return(internal_kld_load_basefile(base_filename, NULL, 0));
+ }
++#endif /* !defined(__STATIC__) */
+
+ long
+ kld_load_basefile_from_memory(
+@@ -824,7 +838,8 @@
+ char *base_addr,
+ long base_size)
+ {
+- long size;
++#if !(defined(KLD) && defined(__STATIC__))
++ unsigned long size;
+ char *addr;
+ int fd;
+ struct stat stat_buf;
+@@ -834,13 +849,14 @@
+ struct fat_header struct_fat_header;
+ #endif /* __LITTLE_ENDIAN__ */
+ struct fat_arch *fat_archs, *best_fat_arch;
+-#if !(defined(KLD) && defined(__STATIC__))
+ struct arch_flag host_arch_flag;
+-#endif /* !(defined(KLD) && defined(__STATIC__)) */
+ enum bool from_fat_file;
+
+ size = 0;
+ from_fat_file = FALSE;
++
++#endif /* !(defined(KLD) && defined(__STATIC__)) */
++
+ #ifndef KLD
+ error_stream = stream;
+ #endif /* !defined(KLD) */
+@@ -898,6 +914,8 @@
+ base_name = allocate(strlen(base_filename) + 1);
+ strcpy(base_name, base_filename);
+
++#if !(defined(KLD) && defined(__STATIC__))
++
+ /*
+ * If there is to be an output file then save the symbols. Only the
+ * symbols from the current set will be placed in the output file. The
+@@ -976,7 +994,7 @@
+ #endif /* __LITTLE_ENDIAN__ */
+
+ if(sizeof(struct fat_header) + fat_header->nfat_arch *
+- sizeof(struct fat_arch) > size){
++ sizeof(struct fat_arch) > (unsigned long)size){
+ error("fat file: %s truncated or malformed (fat_arch "
+ "structs would extend past the end of the file)",
+ base_name);
+@@ -1042,7 +1060,9 @@
+ base_obj = cur_obj;
+ }
+ }
+- else{
++ else
++#endif /* !(defined(KLD) && defined(__STATIC__)) */
++ {
+ cur_obj = new_object_file();
+ cur_obj->file_name = base_name;
+ cur_obj->obj_addr = base_addr;
+@@ -1054,7 +1074,7 @@
+ /*
+ * Now that the file is mapped in merge it as the base file.
+ */
+- merge(FALSE, FALSE);
++ merge(FALSE, FALSE, FALSE);
+
+ if(errors){
+ #ifdef KLD
+@@ -1071,6 +1091,7 @@
+ */
+ clean_objects();
+ clean_archives_and_fats();
++#if !(defined(KLD) && defined(__STATIC__))
+ if(from_fat_file == TRUE){
+ if((r = vm_deallocate(mach_task_self(), (vm_address_t)addr,
+ (vm_size_t)size)) != KERN_SUCCESS)
+@@ -1088,8 +1109,11 @@
+ */
+ rld_maintain_states = FALSE;
+
++#endif /* !(defined(KLD) && defined(__STATIC__)) */
++
+ return(1);
+
++#if !(defined(KLD) && defined(__STATIC__))
+ rld_load_basefile_error_return:
+ if((r = vm_deallocate(mach_task_self(), (vm_address_t)addr,
+ (vm_size_t)size)) != KERN_SUCCESS)
+@@ -1106,6 +1130,7 @@
+ free(fat_archs);
+ #endif /* __LITTLE_ENDIAN__ */
+ return(0);
++#endif /* !(defined(KLD) && defined(__STATIC__)) */
+ }
+
+ #ifndef KLD
+@@ -1638,7 +1663,7 @@
+ * Write the entire output file.
+ */
+ if(write(fd, output_addr, output_size + symbol_size) !=
+- output_size + symbol_size){
++ (int)(output_size + symbol_size)){
+ system_error("can't write output file: %s",output_filename);
+ (void)unlink(output_filename);
+ return_value = 0;
+@@ -1768,6 +1793,23 @@
+ {
+ address_func = func;
+ }
++
++/*
++ * kld_set_link_options() .
++ */
++void
++#ifdef KLD
++kld_set_link_options(
++#else /* !defined(KLD) */
++rld_set_link_options(
++#endif /* KLD */
++unsigned long link_options)
++{
++ if(KLD_STRIP_NONE & link_options)
++ kld_requested_strip_level = STRIP_NONE;
++ else
++ kld_requested_strip_level = STRIP_ALL;
++}
+ #endif /* !defined(SA_RLD) */
+
+ /*
+@@ -1793,6 +1835,7 @@
+ {
+ if(error_stream != NULL)
+ NXVPrintf(error_stream, format, ap);
++NXVPrintf(error_stream, format, ap);
+ }
+ #endif /* !defined(SA_RLD) && !defined(KLD) */
+
+diff -ubr ld/sections.c ld/sections.c
+--- ld/sections.c Tue Jan 14 23:35:25 2003
++++ ld/sections.c Mon Aug 25 22:11:47 2003
+@@ -324,6 +324,13 @@
+ error_with_cur_obj("literal section (%.16s,%.16s) "
+ "not allowed in I860 cputype objects",
+ ms->s.segname, ms->s.sectname);
++#ifdef KLD
++ /*
++ * For KLD the section's alignment from the base file is NOT
++ * picked up.
++ */
++ if(cur_obj != base_obj)
++#endif /* KLD */
+ if(s->align > ms->s.align)
+ ms->s.align = s->align;
+ if(dynamic != TRUE)
+@@ -2724,16 +2731,16 @@
+ /*
+ * It is an error if one of these types of merged sections
+ * has an external relocation entry and the output is a
+- * dynamic library. As no library module will "own" it and
+- * it will never get used by the dynamic linker and the
+- * item relocated.
++ * multi module dynamic library. As in a multi module dylib
++ * no library module will "own" it and it will never get
++ * used by the dynamic linker and the item relocated.
+ */
+ if(ms->nextrel != 0){
+- if(filetype == MH_DYLIB)
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE)
+ fatal("internal error: layout_relocs_for_dyld() "
+ "called with external relocation entries for "
+- "merged section (%.16s,%.16s) for MH_DYLIB "
+- "output", ms->s.segname, ms->s.sectname);
++ "merged section (%.16s,%.16s) for multi module "
++ "MH_DYLIB output", ms->s.segname, ms->s.sectname);
+ /* TODO: can this ever get here? even if not MH_DYLIB? */
+ ms->iextrel = nextrel;
+ nextrel += ms->nextrel;
+@@ -3036,18 +3043,19 @@
+ /*
+ * The number of relocation entries in the output file is based on
+ * one of three different cases:
+- * The output file is a dynamic shared library file
++ * The output file is a multi module dynamic shared library
+ * The output file has a dynamic linker load command
+ * The output does not have a dynamic linker load command
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /*
+- * For dynamic shared library files all external relocations are
+- * kept as external relocation entries except for references to
+- * private externs (which are kept as locals) and all non-
+- * position-independent local relocation entries are kept.
+- * Modules of dylibs are not linked together and can only be
+- * slid keeping all sections relative to each other the same.
++ * For multi module dynamic shared library files all external
++ * relocations are kept as external relocation entries except
++ * for references to private externs (which are kept as locals)
++ * and all non-position-independent local relocation entries
++ * are kept. Modules of multi module dylibs are not linked
++ * together and can only be slid keeping all sections relative
++ * to each other the same.
+ */
+ if(r_extern && (merged_symbol->nlist.n_type & N_PEXT) == 0){
+ (*nextrel) += 1 + pair;
+@@ -3953,19 +3961,19 @@
+ /*
+ * The relocation entries in the output file is based on one of
+ * three different cases:
+- * The output file is a dynamic shared library file
++ * The output file is a multi module dynamic shared library
+ * The output file has a dynamic linker load command
+ * The output does not have a dynamic linker load command
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /*
+- * For dynamic shared library files all external relocations are
+- * kept as external relocation entries except for references to
+- * private externs (which are have been turned into locals and
+- * kept as locals) and all non-position-independent local
+- * relocation entrie are kept. Modules of dylibs are not linked
+- * together and can only be slid keeping all sections relative
+- * to each other the same.
++ * For multi module dynamic shared library files all external
++ * relocations are kept as external relocation entries except
++ * for references to private externs (which are have been turned
++ * into locals and kept as locals) and all non-position-
++ * independent local relocation entrie are kept. Modules of
++ * multi module dylibs are not linked together and can only be
++ * slid keeping all sections relative to each other the same.
+ */
+ if(r_extern){
+ reloc->r_address += addr_adjust;
+diff -ubr ld/sets.c ld/sets.c
+--- ld/sets.c Tue Jan 14 23:35:25 2003
++++ ld/sets.c Mon Aug 25 22:11:47 2003
+@@ -134,7 +134,7 @@
+ clean_archives_and_fats(void)
+ {
+ #ifndef SA_RLD
+- long i;
++ unsigned long i;
+ kern_return_t r;
+ char *file_addr, *file_name;
+ long file_size;
+diff -ubr ld/sparc_reloc.c ld/sparc_reloc.c
+--- ld/sparc_reloc.c Tue Jan 14 23:35:25 2003
++++ ld/sparc_reloc.c Mon Aug 25 22:11:47 2003
+@@ -385,13 +385,13 @@
+ /*
+ * If the symbol is undefined (or common) or a global coalesced
+ * symbol where we need to force an external relocation entry
+- * and we are not prebinding no relocation is done.
+- * Or if the output file is MH_DYLIB no relocation is done
++ * and we are not prebinding no relocation is done. Or if the
++ * output file is a multi module MH_DYLIB no relocation is done
+ * unless the symbol is a private extern or we are prebinding.
+ */
+ if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) ||
+ (force_extern_reloc == TRUE && prebinding == FALSE) ||
+- (filetype == MH_DYLIB &&
++ ((filetype == MH_DYLIB && multi_module_dylib == TRUE) &&
+ (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) &&
+ prebinding == FALSE) ) )
+ value = 0;
+@@ -915,18 +915,19 @@
+ * For external relocation entries that the symbol is
+ * defined (not undefined or common) but not when we are
+ * forcing an external relocation entry for a global
+- * coalesced symbol and if the output file is not MH_DYLIB
+- * or the symbol is a private extern it is changed to a
+- * local relocation entry using the section that symbol is
+- * defined in. If still undefined or forcing an external
+- * relocation entry for a global coalesced symbol then the
+- * index of the symbol in the output file is set into
+- * r_symbolnum.
++ * coalesced symbol and if the output file is not a multi
++ * module MH_DYLIB or the symbol is a private extern, it is
++ * changed to a local relocation entry using the section
++ * that symbol is defined in. If still undefined or forcing
++ * an external relocation entry for a global coalesced
++ * symbol, then the index of the symbol in the output file
++ * is set into r_symbolnum.
+ */
+ else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF &&
+ (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD &&
+ force_extern_reloc == FALSE &&
+- (filetype != MH_DYLIB ||
++ ((filetype != MH_DYLIB ||
++ multi_module_dylib == FALSE) ||
+ (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){
+ reloc->r_extern = 0;
+ /*
+diff -ubr ld/symbols.c ld/symbols.c
+--- ld/symbols.c Tue Jan 14 23:35:25 2003
++++ ld/symbols.c Mon Aug 25 22:11:47 2003
+@@ -47,6 +47,9 @@
+ #include "stuff/bool.h"
+ #include "stuff/bytesex.h"
+ #include "stuff/macosx_deployment_target.h"
++#ifndef RLD
++#include "stuff/symbol_list.h"
++#endif
+
+ #include "ld.h"
+ #include "specs.h"
+@@ -59,6 +62,7 @@
+ #include "sets.h"
+ #include "hash_string.h"
+ #include "dylibs.h"
++#include "mod_sections.h"
+
+ #ifdef RLD
+ __private_extern__ char *base_name;
+@@ -77,6 +81,12 @@
+ __private_extern__ unsigned long nmerged_symbols_referenced_only_from_dylibs =0;
+
+ /*
++ * nstripped_merged_symbols is set to the number of merged symbol being stripped
++ * out when the strip_level is STRIP_DYNAMIC_EXECUTABLE.
++ */
++__private_extern__ unsigned long nstripped_merged_symbols = 0;
++
++/*
+ * This is set by lookup_symbol() and used by enter_symbol(). When a symbol
+ * is not found in the symbol_list by lookup_symbol() it returns a pointer
+ * to a hash_table entry in a merged_symbol_list. The merged_symbol_list that
+@@ -205,6 +215,10 @@
+ static struct object_file *link_edit_symbols_object = NULL;
+ static void setup_link_edit_symbols_object(
+ void);
++
++static void exports_list_processing(
++ char *symbol_name,
++ struct nlist *symbol);
+ #endif /* !defined(RLD) */
+
+ /*
+@@ -263,9 +277,6 @@
+ #endif /* !defined(RLD) */
+
+ __private_extern__
+-#if defined(RLD) && !defined(__DYNAMIC__)
+-const
+-#endif
+ struct object_file link_edit_common_object = {
+ "\"link editor\"", /* file_name */
+ 0, /* obj_addr */
+@@ -408,7 +419,7 @@
+
+ /* check the n_strx field of this symbol */
+ if(symbol->n_un.n_strx < 0 ||
+- symbol->n_un.n_strx >= (long)(cur_obj->symtab->strsize)){
++ (unsigned long)symbol->n_un.n_strx >= cur_obj->symtab->strsize){
+ error_with_cur_obj("bad string table index (%ld) for symbol %lu",
+ symbol->n_un.n_strx, index);
+ return;
+@@ -440,6 +451,8 @@
+ ((struct mach_header *)(cur_obj->obj_addr))->filetype !=
+ MH_BUNDLE) ||
+ (library_ordinal != SELF_LIBRARY_ORDINAL &&
++ (library_ordinal != DYNAMIC_LOOKUP_ORDINAL ||
++ cur_obj->nload_dylibs != DYNAMIC_LOOKUP_ORDINAL) &&
+ library_ordinal-1 >= cur_obj->nload_dylibs) ){
+ error_with_cur_obj("undefined symbol %lu (%s) has bad "
+ "library oridinal %lu", index,
+@@ -835,7 +848,9 @@
+ cur_obj->symtab->symoff);
+ object_strings = (char *)(cur_obj->obj_addr + cur_obj->symtab->stroff);
+ if(cur_obj->swapped &&
+- ((struct mach_header *)cur_obj->obj_addr)->filetype != MH_DYLIB)
++ (((struct mach_header *)cur_obj->obj_addr)->filetype != MH_DYLIB ||
++ ((struct mach_header *)cur_obj->obj_addr)->filetype !=
++ MH_DYLIB_STUB))
+ swap_nlist(object_symbols, cur_obj->symtab->nsyms, host_byte_sex);
+
+
+@@ -867,6 +882,18 @@
+ object_undefineds++;
+ /* TODO coalesce symbols may need to be accounted for depending on how they are
+ referenced */
++#ifndef RLD
++ /*
++ * If we have an -export_symbols_list or -unexport_symbol_list
++ * option set the private extern bit on symbols that are not to
++ * be exported for global symbols that are not undefined.
++ */
++ if((object_symbols[i].n_type & N_EXT) == N_EXT &&
++ object_symbols[i].n_type != (N_EXT | N_UNDF))
++ exports_list_processing(object_strings +
++ object_symbols[i].n_un.n_strx,
++ object_symbols + i);
++#endif /* !defined(RLD) */
+ /*
+ * If this is a private external increment the count of
+ * private exterals for this object and the total in the
+@@ -887,12 +914,12 @@
+
+ #ifndef RLD
+ /*
+- * If the output file type is a dynamic shared library then count the
+- * number of defined externals. And using this count, the count of
+- * undefined symbols and the count of private externs the reference map,
+- * to build the reference table, is allocated.
++ * If the output file type is a multi module dynamic shared library then
++ * count the number of defined externals. And using this count, the
++ * count of undefined symbols and the count of private externs then
++ * reference map, to build the reference table, is allocated.
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ /* TODO coalesce symbols that are discarded need to be accounted for as
+ undefined references */
+ for(i = 0; i < cur_obj->symtab->nsyms; i++){
+@@ -1205,11 +1232,12 @@
+ }
+ #ifndef RLD
+ /*
+- * If the output file is a MH_DYLIB type reset the
+- * reference map for the merged external symbol that
+- * is being discarded.
++ * If the output file is a multi module MH_DYLIB type
++ * reset the reference map for the merged external
++ * symbol that is being discarded.
+ */
+ if(filetype == MH_DYLIB &&
++ multi_module_dylib == TRUE &&
+ merged_symbol->defined_in_dylib == FALSE){
+ /*
+ * Discared coalesced symbols are referenced as
+@@ -1292,9 +1320,24 @@
+ printf("symbol: %s is coalesced\n", merged_symbol->nlist.n_un.n_name);
+ #endif
+ }
+- else
++ else{
+ multiply_defined(merged_symbol, &(object_symbols[i]),
+ object_strings);
++ if(allow_multiply_defined_symbols == TRUE){
++ /*
++ * If this is a private external then decrement
++ * the previous incremented the count of private
++ * exterals for this object and the total in the
++ * output file since we are going to ignore this
++ * this multiply defined symbol.
++ */
++ if((object_symbols[i].n_type & N_EXT) &&
++ (object_symbols[i].n_type & N_PEXT)){
++ cur_obj->nprivatesym--;
++ nmerged_private_symbols--;
++ }
++ }
++ }
+ }
+ /*
+ * If this symbol was undefined or a common in this object
+@@ -1313,10 +1356,10 @@
+ }
+ #ifndef RLD
+ /*
+- * If the output file is a MH_DYLIB type set the reference map
+- * for this external symbol.
++ * If the output file is a multi module MH_DYLIB type set the
++ * reference map for this external symbol.
+ */
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ cur_obj->reference_maps[nrefsym].merged_symbol =
+ merged_symbol;
+ /*
+@@ -1353,6 +1396,7 @@
+ }
+ else if(strip_level != STRIP_DUP_INCLS &&
+ is_output_local_symbol(object_symbols[i].n_type,
++ object_symbols[i].n_sect, cur_obj,
+ object_symbols[i].n_un.n_strx == 0 ? "" :
+ object_strings + object_symbols[i].n_un.n_strx)){
+ cur_obj->nlocalsym++;
+@@ -1427,6 +1471,10 @@
+ localsym_block->index = i;
+ localsym_block->state = PARSE_SYMBOLS;
+ localsym_block->count = 1;
++ localsym_block->input_N_BINCL_n_value =
++ object_symbols[i].n_value;
++ if(localsym_block->input_N_BINCL_n_value != 0)
++ sum = localsym_block->input_N_BINCL_n_value;
+
+ /* insert the first block in the list */
+ localsym_block->next = *next_localsym_block;
+@@ -1506,7 +1554,8 @@
+ if((object_symbols[j].n_type & N_STAB) != 0){
+ cur_localsym_block->count++;
+
+- if(object_symbols[j].n_un.n_strx != 0){
++ if(localsym_block->input_N_BINCL_n_value == 0 &&
++ object_symbols[j].n_un.n_strx != 0){
+ stab_string = object_strings +
+ object_symbols[j].n_un.n_strx;
+ for( ; *stab_string != '\0'; stab_string++){
+@@ -1687,6 +1736,55 @@
+
+ #ifndef RLD
+ /*
++ * exports_list_processing() takes a symbol_name and a defined symbol from an
++ * object file and sets the private extern bit is it is not to be exported. And
++ * also marks the symbol in the list as seen.
++ */
++static
++void
++exports_list_processing(
++char *symbol_name,
++struct nlist *symbol)
++{
++ struct symbol_list *sp;
++
++ if(save_symbols != NULL){
++ sp = bsearch(symbol_name, save_symbols, nsave_symbols,
++ sizeof(struct symbol_list),
++ (int (*)(const void *, const void *))
++ symbol_list_bsearch);
++ if(sp != NULL){
++ sp->seen = TRUE;
++ }
++ else{
++ if(symbol->n_desc & REFERENCED_DYNAMICALLY){
++ warning("symbol: %s referenced dynamically and must be "
++ "exported", symbol_name);
++ }
++ else{
++ symbol->n_type |= N_PEXT;
++ }
++ }
++ }
++ if(remove_symbols != NULL){
++ sp = bsearch(symbol_name, remove_symbols, nremove_symbols,
++ sizeof(struct symbol_list),
++ (int (*)(const void *, const void *))
++ symbol_list_bsearch);
++ if(sp != NULL){
++ sp->seen = TRUE;
++ if(symbol->n_desc & REFERENCED_DYNAMICALLY){
++ warning("symbol: %s referenced dynamically and must be "
++ "exported", symbol_name);
++ }
++ else{
++ symbol->n_type |= N_PEXT;
++ }
++ }
++ }
++}
++
++/*
+ * command_line_symbol() looks up a symbol name that comes from a command line
+ * argument (like -u symbol_name) and returns a pointer to the merged symbol
+ * table entry for it. If the symbol doesn't exist it enters an undefined
+@@ -1725,7 +1823,7 @@
+ */
+ merged_symbol = enter_symbol(hash_pointer, &(undefined_symbol),
+ symbol_name, command_line_object);
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ command_line_object->reference_maps =
+ reallocate(command_line_object->reference_maps,
+ (command_line_object->nrefsym + 1) *
+@@ -1910,7 +2008,7 @@
+ }
+ merged_symbol->nlist.n_value = (unsigned long)merged_indr_symbol;
+
+- if(filetype == MH_DYLIB){
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE){
+ command_line_object->nextdefsym = 1;
+ command_line_object->reference_maps =
+ reallocate(command_line_object->reference_maps,
+@@ -1951,7 +2049,7 @@
+ struct nlist *symbols, *fake_trace_symbol;
+ struct dylib_reference *refs;
+ unsigned long flags;
+- enum bool was_traced;
++ enum bool was_traced, resolve_flat;
+ struct merged_symbol **hash_pointer, *merged_symbol;
+ struct object_file *obj;
+ struct dylib_table_of_contents *toc;
+@@ -2031,11 +2129,12 @@
+ }
+ }
+ /*
+- * If the output file is a MH_DYLIB type reset the
+- * reference map for the merged external symbol that
++ * If the output file is a multi module MH_DYLIB type reset
++ * the reference map for the merged external symbol that
+ * is being discarded.
+ */
+ if(filetype == MH_DYLIB &&
++ multi_module_dylib == TRUE &&
+ merged_symbol->defined_in_dylib == FALSE){
+ /*
+ * Discared coalesced symbols are referenced as
+@@ -2208,6 +2307,13 @@
+ merged_symbol->defined_in_dylib = TRUE;
+ merged_symbol->definition_library = dynamic_library;
+ /*
++ * If this shared library is being forced to be weak linked then
++ * set N_WEAK_REF to make this symbol a weak reference.
++ */
++ if(dynamic_library->force_weak_dylib &&
++ merged_symbol->referenced_in_non_dylib == TRUE)
++ merged_symbol->nlist.n_desc |= N_WEAK_REF;
++ /*
+ * If the merged symbol we are resolving is not a weak reference
+ * and it is referenced from a non-dylib then set
+ * some_non_weak_refs to TRUE.
+@@ -2215,6 +2321,7 @@
+ if((merged_symbol->nlist.n_desc & N_WEAK_REF) == 0 &&
+ merged_symbol->referenced_in_non_dylib == TRUE)
+ dynamic_library->some_non_weak_refs = TRUE;
++ if(merged_symbol->referenced_in_non_dylib == TRUE)
+ dynamic_library->some_symbols_referenced = TRUE;
+ if((symbols[j].n_type & N_TYPE) == N_INDR){
+ merged_symbol->nlist.n_type = N_INDR | N_EXT;
+@@ -2295,7 +2402,8 @@
+ print_obj_name(cur_obj);
+ library_ordinal = GET_LIBRARY_ORDINAL(symbols[
+ refs[j].isym].n_desc);
+- if(library_ordinal != 0){
++ if(library_ordinal != 0 &&
++ library_ordinal != DYNAMIC_LOOKUP_ORDINAL){
+ dep = dynamic_library->dependent_images[
+ library_ordinal - 1];
+ if(dep->umbrella_name != NULL)
+@@ -2316,13 +2424,32 @@
+ }
+ }
+ /*
+- * If -force_flat_namespace is TRUE or this dylib is not a
+- * two-level namespace dylib then use flat semantics to resolve
+- * the undefined symbols from this dylib module.
++ * Determine how this reference will be resolved. If
++ * -force_flat_namespace is TRUE it will be resolved flat.
++ * If this dylib is not a two-level namespace dylib it will
++ * also be resolved flat. It it is a two-level dylib then
++ * if the library_ordinal is DYNAMIC_LOOKUP_ORDINAL it will be
++ * resolved flat. If it is a two-level namespace dylib and
++ * the library_ordinal is not DYNAMIC_LOOKUP_ORDINAL it will
++ * be resolved with two-level namespace semantics.
+ */
+- if(force_flat_namespace == TRUE ||
+- (((struct mach_header *)(cur_obj->obj_addr))->flags &
+- MH_TWOLEVEL) != MH_TWOLEVEL){
++ if(force_flat_namespace == TRUE)
++ resolve_flat = TRUE;
++ else{
++ if((((struct mach_header *)(cur_obj->obj_addr))->
++ flags & MH_TWOLEVEL) == MH_TWOLEVEL){
++ library_ordinal = GET_LIBRARY_ORDINAL(
++ symbols[refs[j].isym].n_desc);
++ if(library_ordinal == DYNAMIC_LOOKUP_ORDINAL)
++ resolve_flat = TRUE;
++ else
++ resolve_flat = FALSE;
++ }
++ else{
++ resolve_flat = TRUE;
++ }
++ }
++ if(resolve_flat == TRUE){
+ /* lookup the symbol and see if it has already been seen */
+ hash_pointer = lookup_symbol(symbol_name);
+ if(*hash_pointer == NULL){
+@@ -2505,11 +2632,12 @@
+ }
+ }
+ /*
+- * If the output file is a MH_DYLIB type reset the
+- * reference map for the merged external symbol that
++ * If the output file is a multi module MH_DYLIB type reset
++ * the reference map for the merged external symbol that
+ * is being discarded.
+ */
+ if(filetype == MH_DYLIB &&
++ multi_module_dylib == TRUE &&
+ merged_symbol->defined_in_dylib == FALSE){
+ /*
+ * Discared coalesced symbols are referenced as
+@@ -2686,13 +2814,17 @@
+
+ /*
+ * is_output_local_symbol() returns TRUE or FALSE depending if the local symbol
+- * type and name passed to it will be in the output file's symbol table based
+- * on the level of symbol stripping.
++ * type, section, object and name passed to it will be in the output file's
++ * symbol table based on the level of symbol stripping. The obj passed must be
++ * be the object this symbol came from so that the the section can be checked
++ * for the S_ATTR_STRIP_STATIC_SYMS attribute flag.
+ */
+ __private_extern__
+ enum bool
+ is_output_local_symbol(
+ unsigned char n_type,
++unsigned char n_sect,
++struct object_file *obj,
+ char *symbol_name)
+ {
+ switch(strip_level){
+@@ -2700,14 +2832,15 @@
+ case STRIP_DUP_INCLS:
+ return(TRUE);
+ case STRIP_ALL:
+- return(FALSE);
++ case STRIP_DYNAMIC_EXECUTABLE:
+ case STRIP_NONGLOBALS:
+- if(n_type & N_PEXT)
+- return(TRUE);
+ return(FALSE);
+ case STRIP_DEBUG:
+ if(n_type & N_STAB ||
+- (*symbol_name == 'L' && (n_type & N_STAB) == 0))
++ (*symbol_name == 'L' && (n_type & N_STAB) == 0) ||
++ ((n_type & N_TYPE) == N_SECT &&
++ (obj->section_maps[n_sect - 1].s->flags &
++ S_ATTR_STRIP_STATIC_SYMS) == S_ATTR_STRIP_STATIC_SYMS))
+ return(FALSE);
+ else
+ return(TRUE);
+@@ -3340,13 +3473,12 @@
+ error("common symbols not allowed with MH_FVMLIB "
+ "output format");
+ /*
+- * If the output format is MH_DYLIB then commons are not
+- * allowed because each symbol can only be defined in at
+- * most one module.
++ * If the output format is multi module MH_DYLIB then * commons are not allowed because each symbol can only be
++ * defined in at most one module.
+ */
+- if(filetype == MH_DYLIB)
++ if(filetype == MH_DYLIB && multi_module_dylib == TRUE)
+ error("common symbols not allowed with MH_DYLIB "
+- "output format");
++ "output format with the -multi_module option");
+ commons_exist = TRUE;
+ #ifndef RLD
+ if(sect_spec != NULL && sect_spec->order_filename != NULL){
+@@ -3461,7 +3593,8 @@
+ * formats so trace each one. An error message for this
+ * has been printed above.
+ */
+- if(filetype == MH_FVMLIB || filetype == MH_DYLIB)
++ if(filetype == MH_FVMLIB ||
++ (filetype == MH_DYLIB && multi_module_dylib == TRUE))
+ trace_merged_symbol(merged_symbol);
+ /* determine the alignment of this symbol */
+ common_size = merged_symbol->nlist.n_value;
+@@ -3497,6 +3630,22 @@
+ &link_edit_common_object;
+ /* Create the space for this symbol */
+ link_edit_common_section.size += common_size;
++ /*
++ * If we have an -export_symbols_list or
++ * -unexport_symbol_list option set the private extern bit
++ * on the symbol if it is not to be exported.
++ */
++ exports_list_processing(merged_symbol->nlist.n_un.n_name,
++ &(merged_symbol->nlist));
++ /*
++ * If this common symbol got made into a private extern with
++ * the processing of the exports list increment the count of
++ * private exterals.
++ */
++ if((merged_symbol->nlist.n_type & N_PEXT) == N_PEXT){
++ link_edit_common_object.nprivatesym++;
++ nmerged_private_symbols++;
++ }
+ #endif /* RLD */
+ /*
+ * Do the trace of this symbol if specified now that it has
+@@ -3557,6 +3706,58 @@
+ }
+
+ #ifndef RLD
++/*
++ * define_undefined_symbols_a_way() is called to setup defining all remaining
++ * undefined symbols as private externs. Their final value gets set by
++ * define_link_editor_dylib_symbols().
++ */
++__private_extern__
++void
++define_undefined_symbols_a_way(
++void)
++{
++ unsigned long i;
++ struct merged_symbol_list **p, *merged_symbol_list;
++ struct merged_symbol *merged_symbol;
++
++ for(p = &merged_symbol_lists; *p; p = &(merged_symbol_list->next)){
++ merged_symbol_list = *p;
++ for(i = 0; i < merged_symbol_list->used; i++){
++ merged_symbol = &(merged_symbol_list->merged_symbols[i]);
++ if(merged_symbol->nlist.n_type == (N_EXT | N_UNDF) &&
++ merged_symbol->nlist.n_value == 0){
++ if(dynamic == TRUE &&
++ filetype != MH_EXECUTE &&
++ merged_segments != NULL){
++ define_link_editor_symbol(
++ merged_symbol->nlist.n_un.n_name,
++ N_SECT | N_PEXT | N_EXT, /* n_type */
++ 1, /* n_sect */
++ 0, /* n_desc */
++ 0); /* n_value */
++ }
++ else{
++ define_link_editor_symbol(
++ merged_symbol->nlist.n_un.n_name,
++ N_ABS | N_PEXT | N_EXT, /* n_type */
++ NO_SECT, /* n_sect */
++ 0, /* n_desc */
++ 0); /* n_value */
++ }
++ /*
++ * This symbol got made into a private extern so increment
++ * the count of private exterals.
++ */
++ if((merged_symbol->nlist.n_type & N_PEXT) == N_PEXT){
++ link_edit_symbols_object->nprivatesym++;
++ nmerged_private_symbols++;
++ }
++ merged_symbol->define_a_way = 1;
++ }
++ }
++ }
++}
++
+ static
+ void
+ setup_link_edit_symbols_object(
+@@ -3741,6 +3942,8 @@
+ {
+ char *symbol_name;
+ struct merged_symbol *merged_symbol;
++ struct merged_symbol_list **p, *merged_symbol_list;
++ unsigned long i;
+
+ if(filetype == MH_BUNDLE)
+ symbol_name = _MH_BUNDLE_SYM;
+@@ -3762,6 +3965,24 @@
+ else
+ merged_symbol->nlist.n_value = header_address -
+ link_edit_symbols_object->section_maps[0].output_section->s.addr;
++
++ /* set the correct values of the undefined symbols defined a way */
++ if(undefined_flag == UNDEFINED_DEFINE_A_WAY){
++ for(p = &merged_symbol_lists; *p; p = &(merged_symbol_list->next)){
++ merged_symbol_list = *p;
++ for(i = 0; i < merged_symbol_list->used; i++){
++ merged_symbol = &(merged_symbol_list->merged_symbols[i]);
++ if(merged_symbol->define_a_way == 1){
++ if(merged_symbol->nlist.n_sect == NO_SECT)
++ merged_symbol->nlist.n_value = header_address;
++ else
++ merged_symbol->nlist.n_value = header_address -
++ link_edit_symbols_object->section_maps[0].
++ output_section->s.addr;
++ }
++ }
++ }
++ }
+ }
+ #endif /* !defined(RLD) */
+
+@@ -3942,6 +4163,16 @@
+ merged_symbol->nlist.n_value = value;
+ merged_symbol->definition_object = link_edit_symbols_object;
+
++#ifndef RLD
++ /*
++ * If we have an -export_symbols_list or
++ * -unexport_symbol_list option set the private extern bit
++ * on the symbol if it is not to be exported.
++ */
++ exports_list_processing(merged_symbol->nlist.n_un.n_name,
++ &(merged_symbol->nlist));
++#endif
++
+ /*
+ * Do the trace of this symbol if specified now that it has
+ * been defined.
+@@ -4057,6 +4288,16 @@
+ for(j = 0; j < indr_depth; j++){
+ indr_symbols[j]->nlist.n_value =
+ (unsigned long)indr_symbol;
++ /*
++ * If this indirect symbol is pointing to a
++ * private extern then increment the count of
++ * private exterals.
++ */
++ if((indr_symbol->nlist.n_type & N_PEXT) == N_PEXT){
++ indr_symbols[j]->definition_object->
++ nprivatesym++;
++ nmerged_private_symbols++;
++ }
+ }
+ }
+ }
+@@ -4142,6 +4383,7 @@
+ object_symbols[i].n_sect == nsect &&
+ (strip_level == STRIP_NONE ||
+ is_output_local_symbol(object_symbols[i].n_type,
++ object_symbols[i].n_sect, cur_obj,
+ object_symbols[i].n_un.n_strx == 0 ? "" :
+ object_strings +
+ object_symbols[i].n_un.n_strx))){
+@@ -4383,6 +4625,7 @@
+ if((object_symbols[i].n_type & N_EXT) == 0 &&
+ (strip_level == STRIP_NONE || strip_level == STRIP_DUP_INCLS ||
+ is_output_local_symbol(object_symbols[i].n_type,
++ object_symbols[i].n_sect, cur_obj,
+ object_symbols[i].n_un.n_strx == 0 ? "" :
+ object_strings + object_symbols[i].n_un.n_strx))){
+
+@@ -4433,11 +4676,11 @@
+ cur_obj->symtab->strsize);
+ output_symtab_info.output_local_strsize += cur_obj->symtab->strsize;
+ }
+-#ifndef RLD
+ if(host_byte_sex != target_byte_sex){
+ nlist = (struct nlist *)(output_addr + flush_symbol_offset);
+ swap_nlist(nlist, output_nsyms, target_byte_sex);
+ }
++#ifndef RLD
+ output_flush(flush_symbol_offset, output_nsyms * sizeof(struct nlist));
+ output_flush(flush_string_offset, output_symtab_info.
+ output_local_strsize -
+@@ -4503,6 +4746,7 @@
+ if((object_symbols[i].n_type & N_EXT) == 0 &&
+ (strip_level == STRIP_NONE ||
+ is_output_local_symbol(object_symbols[i].n_type,
++ object_symbols[i].n_sect, obj,
+ object_symbols[i].n_un.n_strx == 0 ? "" :
+ object_strings + object_symbols[i].n_un.n_strx))){
+
+@@ -4609,6 +4853,7 @@
+ if(indr_symbol->nlist.n_type != (N_EXT | N_UNDF) &&
+ indr_symbol->nlist.n_type != (N_EXT | N_PBUD) &&
+ (filetype != MH_DYLIB ||
++ (filetype == MH_DYLIB && multi_module_dylib == FALSE) ||
+ merged_symbol->definition_object ==
+ indr_symbol->definition_object)){
+ merged_symbol->nlist.n_type = indr_symbol->nlist.n_type;
+@@ -4640,7 +4885,10 @@
+ * the output file is the private externs if they are not to be kept
+ * (that is they are to be made static and not kept as global symbols).
+ */
+- if(nmerged_private_symbols != 0 && keep_private_externs == FALSE){
++ if(nmerged_private_symbols != 0 &&
++ keep_private_externs == FALSE &&
++ (strip_level != STRIP_NONGLOBALS ||
++ (filetype == MH_DYLIB && multi_module_dylib == TRUE)) ){
+ for(p = &merged_symbol_lists; *p; p = &(merged_symbol_list->next)){
+ merged_symbol_list = *p;
+ for(i = 0; i < merged_symbol_list->used; i++){
+@@ -4654,6 +4902,11 @@
+ if(merged_symbol->definition_object->set_num != cur_set)
+ continue;
+ #endif /* RLD */
++ if(strip_level == STRIP_DYNAMIC_EXECUTABLE &&
++ (merged_symbol->nlist.n_desc & REFERENCED_DYNAMICALLY) !=
++ REFERENCED_DYNAMICALLY)
++ continue;
++
+ if(merged_symbol->nlist.n_type & N_PEXT){
+ /*
+ * Place this symbol with the local symbols for the
+@@ -5020,7 +5273,8 @@
+ if(allowed_undef == FALSE)
+ noundefs = FALSE;
+ if(save_reloc == FALSE &&
+- undefined_flag != UNDEFINED_SUPPRESS){
++ (undefined_flag == UNDEFINED_ERROR ||
++ undefined_flag == UNDEFINED_WARNING)){
+ if(allowed_undef == FALSE || prebound_undef == TRUE){
+ if(printed_undef == FALSE){
+ if(undefined_flag == UNDEFINED_WARNING)
+@@ -5047,6 +5301,12 @@
+ print("%s\n", merged_symbol->nlist.n_un.n_name);
+ }
+ }
++ else if(save_reloc == FALSE &&
++ undefined_flag == UNDEFINED_DYNAMIC_LOOKUP &&
++ twolevel_namespace == TRUE){
++ SET_LIBRARY_ORDINAL(merged_symbol->nlist.n_desc,
++ DYNAMIC_LOOKUP_ORDINAL);
++ }
+ }
+ #ifndef RLD
+ else {
+@@ -5177,6 +5437,8 @@
+ }
+
+ #ifndef RLD
++ lib = NULL;
++ prev_lib = NULL;
+ /*
+ * There can be two-level references left on the undefined list. These
+ * are "fake" merged symbols as they are not entered in the symbol
+@@ -5198,6 +5460,18 @@
+ undefined->merged_symbol->nlist.n_desc);
+ if(library_ordinal == SELF_LIBRARY_ORDINAL)
+ lib = undefined->merged_symbol->referencing_library;
++ /*
++ * Note that if library_ordinal was DYNAMIC_LOOKUP_ORDINAL then
++ * merge_dylib_module_symbols() in symbols.c would not have
++ * set the twolevel_reference field to TRUE in the merged_symbol
++ * and if we get here it with this it is an internal error.
++ */
++ else if(library_ordinal == DYNAMIC_LOOKUP_ORDINAL)
++ fatal("internal error: process_undefineds() 1 with a "
++ "merged_symbol (%s) on the undefined list with "
++ "twolevel_reference == TRUE and library_ordinal == "
++ "DYNAMIC_LOOKUP_ORDINAL", undefined->merged_symbol->
++ nlist.n_un.n_name);
+ else
+ lib = undefined->merged_symbol->referencing_library->
+ dependent_images[library_ordinal - 1];
+@@ -5205,10 +5479,25 @@
+ for(prevs = undefined_list.next;
+ prevs != undefined;
+ prevs = prevs->next){
++ if(prevs->merged_symbol->twolevel_reference == FALSE)
++ continue;
+ library_ordinal = GET_LIBRARY_ORDINAL(
+ prevs->merged_symbol->nlist.n_desc);
+ if(library_ordinal == SELF_LIBRARY_ORDINAL)
+ prev_lib = prevs->merged_symbol->referencing_library;
++ /*
++ * Note that if library_ordinal was DYNAMIC_LOOKUP_ORDINAL
++ * then merge_dylib_module_symbols() in symbols.c would not
++ * have set the twolevel_reference field to TRUE in the
++ * merged_symbol and if we get here it with this it is an
++ * internal error.
++ */
++ else if(library_ordinal == DYNAMIC_LOOKUP_ORDINAL)
++ fatal("internal error: process_undefineds() 2 with a "
++ "merged_symbol (%s) on the undefined list with "
++ "twolevel_reference == TRUE and library_ordinal "
++ "== DYNAMIC_LOOKUP_ORDINAL",
++ prevs->merged_symbol->nlist.n_un.n_name);
+ else
+ prev_lib = prevs->merged_symbol->referencing_library->
+ dependent_images[library_ordinal - 1];
+@@ -5277,9 +5566,10 @@
+ "weak " : "",
+ merged_symbol->nlist.n_un.n_name);
+ #ifndef RLD
+- if(merged_symbol->twolevel_reference == TRUE){
+ library_ordinal = GET_LIBRARY_ORDINAL(
+ merged_symbol->nlist.n_desc);
++ if(merged_symbol->twolevel_reference == TRUE &&
++ library_ordinal != DYNAMIC_LOOKUP_ORDINAL){
+ if(library_ordinal == SELF_LIBRARY_ORDINAL)
+ lib = merged_symbol->referencing_library;
+ else
+@@ -5419,13 +5709,54 @@
+ assign_output_symbol_indexes(
+ void)
+ {
+- unsigned long index, i, nextdefsym, nundefsym;
++ unsigned long index, i, nextdefsym, nundefsym, n_pext;
+ struct merged_symbol_list **p, *merged_symbol_list;
+- struct merged_symbol *merged_symbol;
++ struct merged_symbol *merged_symbol, *indr_symbol;
+ struct object_list *object_list, **q;
++ struct object_file *last_object;
++ enum bool rebuild_merged_string_table;
+
+- if(strip_level == STRIP_ALL)
++ rebuild_merged_string_table = FALSE;
++ if(strip_level == STRIP_ALL){
++ if(has_dynamic_linker_command){
++ strip_level = STRIP_DYNAMIC_EXECUTABLE;
++ /*
++ * In order to not put out strings for merged symbols that will
++ * be discared we need to rebuild the merged string table for
++ * only the symbols not stripped.
++ */
++ merged_string_blocks = NULL;
++ merged_string_size = 0;
++ rebuild_merged_string_table = TRUE;
++ }
++ else{
++ seglinkedit = FALSE;
+ return;
++ }
++ }
++ /*
++ * If we are stripping non-globals and we are not keeping private
++ * externs and we have some private externs in the merged symbol table,
++ * and the output is not a multi-module dylib, then in order to not put
++ * out strings for them we also need to rebuild the merged string table
++ * without these symbols.
++ */
++ else if(strip_level == STRIP_NONGLOBALS &&
++ keep_private_externs == FALSE &&
++ nmerged_private_symbols != 0 &&
++ (filetype != MH_DYLIB || multi_module_dylib == FALSE)){
++ merged_string_blocks = NULL;
++ merged_string_size = 0;
++ rebuild_merged_string_table = TRUE;
++ }
++
++ /*
++ * Add a copy of the object file for the common symbols that the link
++ * editor allocated into the object file list. Since it is possible
++ * that some of the common symbols are not on the export list they could
++ * have been made into private externs.
++ */
++ last_object = add_last_object_file(&link_edit_common_object);
+
+ /*
+ * Private exterals are always kept when any symbols are kept. The
+@@ -5467,7 +5798,12 @@
+ if(keep_private_externs == FALSE){
+ cur_obj->iprivatesym = index;
+ cur_obj->cprivatesym = index;
++ if(strip_level != STRIP_DYNAMIC_EXECUTABLE &&
++ (strip_level != STRIP_NONGLOBALS ||
++ (filetype == MH_DYLIB && multi_module_dylib == TRUE)))
+ index += cur_obj->nprivatesym;
++ else
++ nstripped_merged_symbols += cur_obj->nprivatesym;
+ }
+ }
+ }
+@@ -5476,12 +5812,21 @@
+ */
+ if((keep_private_externs == TRUE && index != nlocal_symbols) ||
+ (keep_private_externs == FALSE && index != nlocal_symbols +
+- nmerged_private_symbols))
++ nmerged_private_symbols - nstripped_merged_symbols))
+ fatal("internal error: assign_output_symbol_indexes() "
+ "inconsistent local symbol counts");
+ output_dysymtab_info.dysymtab_command.nlocalsym = index;
+
+ /*
++ * Copy the values that got set in the above loop back into the
++ * object file for the the common symbols. Then remove the copy of
++ * the object file from the object file list.
++ */
++ link_edit_common_object = *last_object;
++ remove_last_object_file(last_object);
++
++
++ /*
+ * Count the number of undefined symbols and defined external symbols.
+ * Private exterals are counted as defined externals if
+ * keep_private_externs is TRUE.
+@@ -5504,11 +5849,36 @@
+ if(merged_symbol->nlist.n_type == (N_EXT | N_UNDF) ||
+ merged_symbol->nlist.n_type == (N_EXT | N_PBUD) ||
+ (merged_symbol->nlist.n_type == (N_EXT | N_INDR) &&
+- merged_symbol->defined_in_dylib == TRUE))
++ merged_symbol->defined_in_dylib == TRUE)){
+ nundefsym++;
+- else if(keep_private_externs == TRUE ||
+- (merged_symbol->nlist.n_type & N_PEXT) == 0)
++ if(rebuild_merged_string_table == TRUE)
++ merged_symbol->nlist.n_un.n_name =
++ enter_string(merged_symbol->nlist.n_un.n_name);
++ }
++ else{
++ if(merged_symbol->nlist.n_type == (N_EXT | N_INDR)){
++ indr_symbol = (struct merged_symbol *)
++ (merged_symbol->nlist.n_value);
++ n_pext = indr_symbol->nlist.n_type & N_PEXT;
++ }
++ else{
++ n_pext = merged_symbol->nlist.n_type & N_PEXT;
++ }
++ if(keep_private_externs == TRUE || n_pext == 0){
++ if(strip_level != STRIP_DYNAMIC_EXECUTABLE ||
++ (merged_symbol->nlist.n_desc &
++ REFERENCED_DYNAMICALLY) == REFERENCED_DYNAMICALLY){
+ nextdefsym++;
++ if(rebuild_merged_string_table == TRUE)
++ merged_symbol->nlist.n_un.n_name =
++ enter_string(merged_symbol->
++ nlist.n_un.n_name);
++ }
++ else{
++ nstripped_merged_symbols++;
++ }
++ }
++ }
+ }
+ }
+
+@@ -5543,11 +5913,25 @@
+ (merged_symbol->nlist.n_type == (N_EXT | N_INDR) &&
+ merged_symbol->defined_in_dylib == TRUE))
+ undefsyms_order[nundefsym++] = merged_symbol;
+- else if(keep_private_externs == TRUE ||
+- (merged_symbol->nlist.n_type & N_PEXT) == 0)
++ else{
++ if(merged_symbol->nlist.n_type == (N_EXT | N_INDR)){
++ indr_symbol = (struct merged_symbol *)
++ (merged_symbol->nlist.n_value);
++ n_pext = indr_symbol->nlist.n_type & N_PEXT;
++ }
++ else{
++ n_pext = merged_symbol->nlist.n_type & N_PEXT;
++ }
++ if(keep_private_externs == TRUE || n_pext == 0){
++ if(strip_level != STRIP_DYNAMIC_EXECUTABLE ||
++ (merged_symbol->nlist.n_desc &
++ REFERENCED_DYNAMICALLY) == REFERENCED_DYNAMICALLY){
+ extdefsyms_order[nextdefsym++] = merged_symbol;
+ }
+ }
++ }
++ }
++ }
+ #ifndef SA_RLD
+ /*
+ * Sort the defined symbols by module for MH_DYLIB formats and by
+@@ -5688,6 +6072,12 @@
+
+ #ifndef RLD
+ /*
++ * This is a pointer to the module name saved in the merged string table for
++ * the one module table entry for a single module dylib.
++ */
++char *dylib_single_module_name;
++
++/*
+ * layout_dylib_tables() sizes and readys the tables for a dynamic library file.
+ * The merged symbol indexes have already been assigned before this is called.
+ * There are three tables:
+@@ -5705,10 +6095,12 @@
+ struct object_list *object_list, **q;
+ char *p;
+
++ if(multi_module_dylib == TRUE){
+ /*
+- * The reference table was sized as the symbols were merged. All that
+- * is left to do for the reference table is to adjust the flags for
+- * undefined references that ended up referencing private externs.
++ * For multi module dylibs the reference table was sized as the
++ * symbols were merged. All that is left to do for the reference
++ * table is to adjust the flags for undefined references that ended
++ * up referencing private externs.
+ */
+ for(q = &objects; *q; q = &(object_list->next)){
+ object_list = *q;
+@@ -5721,7 +6113,8 @@
+ if(cur_obj->dylinker)
+ continue;
+ for(j = 0; j < cur_obj->nrefsym; j++){
+- merged_symbol = cur_obj->reference_maps[j].merged_symbol;
++ merged_symbol =
++ cur_obj->reference_maps[j].merged_symbol;
+ if(merged_symbol->nlist.n_type & N_PEXT){
+ flags = cur_obj->reference_maps[j].flags;
+ if(flags == REFERENCE_FLAG_UNDEFINED_NON_LAZY)
+@@ -5735,27 +6128,43 @@
+ /*
+ * The merged symbol is not a private extern. So it
+ * might be a non-weak symbol that is being used and
+- * some weak private externs refs were discarded. If
+- * so we need to make the refs non-weak.
++ * some weak private externs refs were discarded.
++ * If so we need to make the refs non-weak.
+ */
+ flags = cur_obj->reference_maps[j].flags;
+- if(flags == REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
++ if(flags ==
++ REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
+ cur_obj->reference_maps[j].flags =
+ REFERENCE_FLAG_UNDEFINED_NON_LAZY;
+- else if(flags == REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)
++ else if(flags ==
++ REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)
+ cur_obj->reference_maps[j].flags =
+ REFERENCE_FLAG_UNDEFINED_LAZY;
+ }
+ }
+ }
+ }
+-
++ }
++ else{
+ /*
+- * The module table is sized from the number of modules loaded. The
+- * module_name of each module in the dynamic shared library is set from
+- * base name or archive member name of the object loaded. The string
+- * for the module_name is then saved with the merged strings so that it
+- * can be converted to a string table index on output.
++ * For single module dylibs the reference table size is reset here
++ * from the defined and undefined merged symbols. The contents of
++ * the reference table for single module dylibs will be filled in
++ * output_dylib_tables() from the merged symbol table.
++ */
++ output_dysymtab_info.dysymtab_command.nextrefsyms =
++ output_dysymtab_info.dysymtab_command.nextdefsym +
++ output_dysymtab_info.dysymtab_command.nundefsym;
++ }
++
++ if(multi_module_dylib == TRUE){
++ /*
++ * For multi module dylibs the module table is sized from the number
++ * of modules loaded. The module_name of each module in the dynamic
++ * shared library is set from base name or archive member name of
++ * the object loaded. The string for the module_name is then saved
++ * with the merged strings so that it can be converted to a string
++ * table index on output.
+ */
+ output_dysymtab_info.dysymtab_command.nmodtab = 0;
+ for(q = &objects; *q; q = &(object_list->next)){
+@@ -5786,6 +6195,17 @@
+ }
+ }
+ }
++ }
++ else{
++ /*
++ * For single module dylibs there is one module table entry.
++ * The module_name is set to "single module". The string for the
++ * module_name is then saved with the merged strings so that it can
++ * be converted to a string table index on output.
++ */
++ output_dysymtab_info.dysymtab_command.nmodtab = 1;
++ dylib_single_module_name = enter_string("single module");
++ }
+
+ /*
+ * The table of contents is sized from the number of defined external
+@@ -5815,6 +6235,7 @@
+ struct merged_symbol_list **p, *merged_symbol_list;
+ struct merged_symbol *merged_symbol;
+ struct dylib_table_of_contents *tocs, *toc;
++ struct merged_section *ms;
+
+ /*
+ * Output the reference table.
+@@ -5822,6 +6243,11 @@
+ flush_offset = output_dysymtab_info.dysymtab_command.extrefsymoff;
+ refs = (struct dylib_reference *)(output_addr + flush_offset);
+ ref = refs;
++ if(multi_module_dylib == TRUE){
++ /*
++ * For multi module dylibs there is a reference table for each
++ * object loaded built from the reference_maps.
++ */
+ for(q = &objects; *q; q = &(object_list->next)){
+ object_list = *q;
+ for(i = 0; i < object_list->used; i++){
+@@ -5840,6 +6266,35 @@
+ }
+ }
+ }
++ }
++ else{
++ /*
++ * For single module dylibs there is one reference table and it is
++ * built from the merged symbol table.
++ */
++ for(p = &merged_symbol_lists; *p; p = &(merged_symbol_list->next)){
++ merged_symbol_list = *p;
++ for(i = 0; i < merged_symbol_list->used; i++){
++ merged_symbol = &(merged_symbol_list->merged_symbols[i]);
++ if(merged_symbol->referenced_in_non_dylib == FALSE)
++ continue;
++ if(merged_symbol->nlist.n_type == (N_EXT | N_UNDF) ||
++ merged_symbol->nlist.n_type == (N_EXT | N_PBUD) ||
++ (merged_symbol->nlist.n_type == (N_EXT | N_INDR) &&
++ merged_symbol->defined_in_dylib == TRUE)){
++ ref->isym = merged_symbol_output_index(merged_symbol);
++ ref->flags = merged_symbol->nlist.n_desc &
++ REFERENCE_TYPE;
++ ref++;
++ }
++ else if((merged_symbol->nlist.n_type & N_PEXT) == 0){
++ ref->isym = merged_symbol_output_index(merged_symbol);
++ ref->flags = REFERENCE_FLAG_DEFINED;
++ ref++;
++ }
++ }
++ }
++ }
+ if(host_byte_sex != target_byte_sex){
+ swap_dylib_reference(refs,
+ output_dysymtab_info.dysymtab_command.nextrefsyms,
+@@ -5855,6 +6310,11 @@
+ flush_offset = output_dysymtab_info.dysymtab_command.modtaboff;
+ mods = (struct dylib_module *)(output_addr + flush_offset);
+ mod = mods;
++ if(multi_module_dylib == TRUE){
++ /*
++ * For multi module dylibs there is a module table for each
++ * object loaded built from the info saved in the object struct.
++ */
+ for(q = &objects; *q; q = &(object_list->next)){
+ object_list = *q;
+ for(i = 0; i < object_list->used; i++){
+@@ -5873,7 +6333,7 @@
+ mod->nlocalsym = cur_obj->nlocalsym + cur_obj->nprivatesym;
+ mod->iextrel = cur_obj->iextrel;
+ mod->nextrel = cur_obj->nextrel;
+- mod->iinit_iterm = (cur_obj->iterm << 16) | cur_obj->iinit ;
++ mod->iinit_iterm = (cur_obj->iterm << 16) | cur_obj->iinit;
+ mod->ninit_nterm = (cur_obj->nterm << 16) | cur_obj->ninit;
+ if(cur_obj->objc_module_info != NULL){
+ mod->objc_module_info_addr =
+@@ -5887,6 +6347,39 @@
+ mod->objc_module_info_size = 0;
+ }
+ mod++;
++ }
++ }
++ }
++ else{
++ /*
++ * For single module dylibs there is one module table entry.
++ */
++ mod->module_name = STRING_SIZE_OFFSET +
++ merged_symbol_string_index(dylib_single_module_name);
++ mod->iextdefsym =
++ output_dysymtab_info.dysymtab_command.iextdefsym;
++ mod->nextdefsym =
++ output_dysymtab_info.dysymtab_command.nextdefsym;
++ mod->irefsym = 0;
++ mod->nrefsym =
++ output_dysymtab_info.dysymtab_command.nextrefsyms;
++ mod->ilocalsym =
++ output_dysymtab_info.dysymtab_command.ilocalsym;
++ mod->nlocalsym =
++ output_dysymtab_info.dysymtab_command.nlocalsym;
++ mod->iextrel = 0;
++ mod->nextrel =
++ output_dysymtab_info.dysymtab_command.nextrel;
++ mod->iinit_iterm = 0;
++ mod->ninit_nterm = (nterm << 16) | ninit;
++ ms = lookup_merged_section(SEG_OBJC, SECT_OBJC_MODULES);
++ if(ms != NULL){
++ mod->objc_module_info_addr = ms->s.addr;
++ mod->objc_module_info_size = ms->s.size;
++ }
++ else{
++ mod->objc_module_info_addr = 0;
++ mod->objc_module_info_size = 0;
+ }
+ }
+ if(host_byte_sex != target_byte_sex){
+diff -ubr ld/symbols.h ld/symbols.h
+--- ld/symbols.h Tue Jan 14 23:35:25 2003
++++ ld/symbols.h Mon Aug 25 12:12:29 2003
+@@ -78,7 +78,8 @@
+ /* only in the undefined list as a two- */
+ /* level namespace reference from a dylib.*/
+ weak_reference_mismatch:1, /* seen both a weak and non-weak reference */
+- reserved:1,
++ define_a_way:1, /* set if this symbol was defined as a */
++ /* result of -undefined define_a_way */
+ output_index:23; /* the symbol table index this symbol will */
+ /* have in the output file. */
+ int undef_order; /* if the symbol was undefined the order it */
+@@ -184,6 +185,12 @@
+ __private_extern__ unsigned long nmerged_symbols_referenced_only_from_dylibs;
+
+ /*
++ * nstripped_merged_symbols is set to the number of merged symbol being stripped
++ * out when the strip_level is STRIP_DYNAMIC_EXECUTABLE.
++ */
++__private_extern__ unsigned long nstripped_merged_symbols;
++
++/*
+ * The head of the list of the blocks that store the strings for the merged
+ * symbols and the total size of all the strings. The size of the strings for
+ * the private externals is included in the the merge string size.
+@@ -210,9 +217,6 @@
+ * The object file that is created for the common symbols to be allocated in.
+ */
+ __private_extern__
+-#if defined(RLD) && !defined(__DYNAMIC__)
+-const
+-#endif
+ struct object_file link_edit_common_object;
+
+ /*
+@@ -255,6 +259,7 @@
+ unsigned long index;
+ unsigned long count;
+ enum localsym_block_state state;
++ unsigned long input_N_BINCL_n_value;
+ unsigned long sum;
+ struct localsym_block *next;
+ };
+@@ -323,6 +328,8 @@
+ void);
+ __private_extern__ void define_common_symbols(
+ void);
++__private_extern__ void define_undefined_symbols_a_way(
++ void);
+ __private_extern__ void define_link_editor_execute_symbols(
+ unsigned long header_address);
+ __private_extern__ void setup_link_editor_symbols(
+@@ -369,6 +376,8 @@
+ #endif /* defined(RLD) && !defined(SA_RLD) */
+ __private_extern__ enum bool is_output_local_symbol(
+ unsigned char n_type,
++ unsigned char n_sect,
++ struct object_file *obj,
+ char *symbol_name);
+ __private_extern__ unsigned long merged_symbol_output_index(
+ struct merged_symbol *merged_symbol);