]> git.saurik.com Git - apple/ld64.git/commitdiff
ld64-62.1.tar.gz developer-tools-241 developer-tools-25 v62.1
authorApple <opensource@apple.com>
Fri, 21 Mar 2008 02:13:50 +0000 (02:13 +0000)
committerApple <opensource@apple.com>
Fri, 21 Mar 2008 02:13:50 +0000 (02:13 +0000)
29 files changed:
ChangeLog
doc/man/man1/ld.1 [new file with mode: 0644]
ld64.xcodeproj/project.pbxproj
src/MachOReaderDylib.hpp
src/MachOReaderRelocatable.hpp
src/MachOWriterExecutable.hpp
src/ObjectDump.cpp
src/ObjectFile.h
src/Options.cpp
src/Options.h
src/SectCreate.cpp
src/ld.cpp
src/machochecker.cpp
src/rebase.cpp
unit-tests/test-cases/align-modulus/Makefile [new file with mode: 0644]
unit-tests/test-cases/align-modulus/align.s [new file with mode: 0644]
unit-tests/test-cases/align-modulus/foo.c [new file with mode: 0644]
unit-tests/test-cases/align-modulus/foo.exp [new file with mode: 0644]
unit-tests/test-cases/dead_strip-archive/Makefile [new file with mode: 0644]
unit-tests/test-cases/dead_strip-archive/foo.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip-archive/main.c [new file with mode: 0644]
unit-tests/test-cases/dwarf-debug-notes-r/Makefile
unit-tests/test-cases/dwarf-debug-notes-r/expected-stabs
unit-tests/test-cases/indirect-dylib/Makefile [new file with mode: 0644]
unit-tests/test-cases/indirect-dylib/bar.c [new file with mode: 0644]
unit-tests/test-cases/indirect-dylib/foo.c [new file with mode: 0644]
unit-tests/test-cases/indirect-dylib/main.c [new file with mode: 0644]
unit-tests/test-cases/relocs-asm/relocs-asm.s
unit-tests/test-cases/relocs-objc/test.m

index 7436b2b688ce6a840cbd9df757ae392c09502b4d..ce470b099478b0df82881abeb3b35bc899771038 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
 
------ Tagged ld64-59.4
+2006-09-22      Nick Kledzik    <kledzik@apple.com>
+
+       ld64.xcodeproj/project.pbxproj: change install name back to ld64
+       src/Options.cpp: remove support for rolling over to ld_classic
+       src/ld.cpp: remove support for rolling over to ld_classic
+
+
+----- Tagged ld64-62
+
+2006-08-15      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4681062> wrong error message when symbol is found in unused indirect library
+       src/ld.cpp: remove indirect libraries if they are not re-exported
+       unit-tests/test-cases/indirect-dylib: added test case
+
+
+2006-08-15      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/3930461> alignment needs to be richer
+       src/ObjectFile.h: define ObjectFile::Alignment class for tracking rich alignment info
+       src/ld.cpp: modify SymbolTable::add() to work with new Alignment type
+       src/MachOReaderRelocatable.hpp: use new Alignment type. Remove alignAtLeast() and handleAnonymousNonLazyPointers()
+       src/MachOWriterExecutable.hpp: update for new Alignment type, use modulus when calculating layout address
+       src/ObjectDump.cpp: print richer Alignment info
+       unit-tests/test-cases/align-modulus: added test case
+       
+
+2006-08-11      Nick Kledzik    <kledzik@apple.com>
+
+       remove OPEN_SOURCE conditionals around x86_64 support
+
+
+2006-07-31      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4654131> ld64 while linking cc1 [ when dead_strip is ON]
+       src/ld.cpp: Add ivar fAtomsWithUnresolvedReferences to track atoms not initially resolvable
+       unit-tests/test-cases/dead_strip-archive: added test case
+       
+
+2006-07-31      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4656617> x86_64: instructions with immediate and rip-relative operands need to use new relocation types
+       src/MachOWriterExecutable.hpp: generate new reloc types in -r mode      
+       src/MachOReaderRelocatable.hpp: parse new reloc types
+       unit-tests/test-cases/relocs-asm/relocs-asm.s: add test cases for new reloc type
+       
+
+2006-07-18      Nick Kledzik    <kledzik@apple.com>
+
+       src/MachOReaderRelocatable.hpp: suppress warning about dwarf info parsing for one benign no-op case
+       the compiler emits when there are not functions in the __text section
+       
+
+2006-07-17      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4634840> faster debug note generateion
+       src/ld.cpp: rework collectDebugInfo() to produce all debug notes in one pass, intead of a 
+       pass per .o file. Added timing info for collectDebugInfo() to -print_statistics
+       unit-tests/test-cases/dwarf-debug-notes-r/Makefile: add expliced -arch to ld -r 
+       unit-tests/test-cases/dwarf-debug-notes-r/expected-stabs: alter for new debug notes order
+       
+
+2006-07-17      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4623994> ld64 VSIZE is 1.18GB when building Finder ppc64
+       src/ld.cpp: fixed typo in createReader() that prevented dylibs from being unmapped
+
+----- Tagged ld64-61.1
 
 2006-07-11      Nick Kledzik    <kledzik@apple.com>
 
 2006-07-11      Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/4622049> ld64-61: gcc DejaGnu tests failing due to -arch followed by unknown architecture name
+       src/Options.cpp: map ppc750, ppc7400, ppc7450, and ppc970 to ppc. Improve error message
 
 
-       remove conditionals around x86_64 support
+2006-07-11      Nick Kledzik    <kledzik@apple.com>
 
 
------ Tagged ld64-59.3
+       <rdar://problem/4622769> If -arch is missing, rollover to ld_classic does not happen
+       src/Options.h: make gotoClassicLinker() public
+       src/ld.cpp: call gotoClassicLinker() if the inferred architecture is ppc or i386
 
 
-2006-07-02      Nick Kledzik    <kledzik@apple.com>
+----- Tagged ld64-61
 
 
-       <rdar://problem/4664607> x86_64: instructions with immediate and rip-relative operands need to use new relocation types
-       back port fix for 4656617 to Inca branch
+2006-06-29      Nick Kledzik    <kledzik@apple.com>
 
 
------ Tagged ld64-59.2
+       <rdar://problem/4606628> ld64 should be renamed to ld
+       src/Options.cpp: exec() ld_classic if -arch ppc or -arch i386 is seen
+       src/ld.cpp: alter version string
+       ld64.xcodeproj/project.pbxproj: change install location to /usr/bin/ld, add symlink from /usr/bin/ld64
+       doc/man/man1/ld.1: added
+       
+----- Tagged ld64-60
+
+2006-06-28      Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/4604539> Can't link large ppc64 program: ld64 says "bl out of range"
+       MachOWriterExecutable.hpp: fix branch island generation to work for weak_import functions
+       and properly chain together branch islands
+       MachOReaderRelocatable.hpp: improve performance of huge .o file reading by sorted references
+       only when done
 
 2006-06-28      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4603454> MySQL-36 fails to build with ld64-59
 
 2006-06-28      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4603454> MySQL-36 fails to build with ld64-59
-       back port fix to Inca branch
+       src/MachOReaderRelocatable.hpp: back out fix for 4585335
+       src/MachOWriterExecutable.hpp: back out fix for 4585335
+
+2006-06-27      Nick Kledzik    <kledzik@apple.com>
+
+       src/MachOReaderRelocatable.hpp: handle N_GSYM without ending :G() since that is how 
+       dwarf debug notes are formed. 
+
+2006-06-23      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4599239 objc class with no superclass causes bad undefined symbol
+       src/MachOReaderRelocatable.hpp: handle NULL superclass in objc_class
+       unit-tests/test-cases/relocs-objc/test.m: add case with no super class
+       
+
+2006-06-23      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4313369> ld64 doesn't support variant linking -framework fw,_debug
+       src/Options.cpp: enhance findFramework() to support suffixes
 
 ----- Tagged ld64-59
 
 2006-06-22      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4596726> ld64 lost DWARF debug notes
 
 ----- Tagged ld64-59
 
 2006-06-22      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4596726> ld64 lost DWARF debug notes
-       MachOReaderRelocatable.hpp: add fHasUUID so kDebugInfoStabsUUID can be set later
+       src/MachOReaderRelocatable.hpp: add fHasUUID so kDebugInfoStabsUUID can be set later
        unit-tests/test-cases/dwarf-debug-notes-r: added test case
        
 2006-06-21      Nick Kledzik    <kledzik@apple.com>
        unit-tests/test-cases/dwarf-debug-notes-r: added test case
        
 2006-06-21      Nick Kledzik    <kledzik@apple.com>
 2006-06-21      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4535036> ld64 seems to offset things incorrectly when using -r
 2006-06-21      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4535036> ld64 seems to offset things incorrectly when using -r
-       src/MachOWriterExecutable.hpp: in -r mode, virtual sections don't increment address
+       src/MachOWriterExecutable.hpp: in -r mode, virtual sections should not increment address
 
 
 ----- Tagged ld64-58
 
 
 ----- Tagged ld64-58
 2006-06-15      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4569407> ld64 bogus duplicate symbol name linking GNU libobjc
 2006-06-15      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4569407> ld64 bogus duplicate symbol name linking GNU libobjc
-       src/MachOReaderRelocatable.hpp: only special case Apple's objc runtime objc classes
+       src/MachOReaderRelocatable.hpp: only special case Apple objc runtime objc classes
 
 2006-06-15      Nick Kledzik    <kledzik@apple.com>
 
 
 2006-06-15      Nick Kledzik    <kledzik@apple.com>
 
 
        <rdar://problem/4585335> jump table into middle of weak symbol causes error
        src/MachOReaderRelocatable.hpp: create direct references to the interior of weak symbols
 
        <rdar://problem/4585335> jump table into middle of weak symbol causes error
        src/MachOReaderRelocatable.hpp: create direct references to the interior of weak symbols
-       src/MachOWriterExecutable.hpp: don't error on absolute references to interior of weak symbols
+       src/MachOWriterExecutable.hpp: do not error on absolute references to interior of weak symbols
 
 2006-06-13      Nick Kledzik    <kledzik@apple.com>
 
 
 2006-06-13      Nick Kledzik    <kledzik@apple.com>
 
        * src/MachOReaderRelocatable.cpp: mark non-lazy-pointer atoms as scopeTranslationUnit if targetting a static symbol
 
 
        * src/MachOReaderRelocatable.cpp: mark non-lazy-pointer atoms as scopeTranslationUnit if targetting a static symbol
 
 
-2006-04-27      Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4498971> dyld crashes ungracefully on x86_64 when there is an internal exception
-       * src/MachOWriterExecutable.cpp: allow non-zero PCRELGOT addends (used by C++ eh frames)
 
 2006-04-21      Nick Kledzik    <kledzik@apple.com>
 
 
 2006-04-21      Nick Kledzik    <kledzik@apple.com>
 
 
 ----- Tagged ld64-50
 
 
 ----- Tagged ld64-50
 
-2006-03-29      Nick Kledzik    <kledzik@apple.com>
-
-       * src/MachOWriterExecutable.hpp: fix x86_64 addends when -multi_module forces an external relocation
 
 2006-03-29      Nick Kledzik    <kledzik@apple.com>
 
 
 2006-03-29      Nick Kledzik    <kledzik@apple.com>
 
        * src/Options.cpp: setup ReaderOptions.fForFinalLinkedImage
        * src/MachOReaderRelocatable.hpp: mark .eh symbols kSymbolTableNotIn when building final linked image
 
        * src/Options.cpp: setup ReaderOptions.fForFinalLinkedImage
        * src/MachOReaderRelocatable.hpp: mark .eh symbols kSymbolTableNotIn when building final linked image
 
-2006-03-21     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4475928> Inca ld64-45 fatal error with C++ and asm() renaming
-       * src/MachOReaderRelocatable.hpp: fix Reader<x86_64>::makeReferenceToEH(() to walk relocations to find
-       target of eh symbol, rather assume target name is eh symbol name less .eh
-
 2006-03-21     Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4473742> ld64 does not parse optional second argument to -filelist
        * unit-tests/test-cases/filelist: added
        * src/Options.cpp: in Options::loadFileList() handle comma option
 
 2006-03-21     Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4473742> ld64 does not parse optional second argument to -filelist
        * unit-tests/test-cases/filelist: added
        * src/Options.cpp: in Options::loadFileList() handle comma option
 
-2006-03-21     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4483625> 32-bit pointer difference out of range for cxx eh frame
-       * src/MachOReaderRelocatable.hpp: x86_64 doesn't have anonymous non-lazy-pointers
-       * src/machochecker.cpp: fix validFile() for x86_64
-       * unit-tests/run-all-unit-tests: add x86_64
-       * unit-tests/include/common.makefile: don't add -g to all compilers
-       * unit-tests/test-cases/relocs-asm/relocs-asm.s: add x86_64 test cases
-       * unit-tests/test-cases/relocs-c/Makefile: fix to work with x86_64
-       * src/ld.cpp: add hack to use i386 dylibs if x86_64 don't exist
-
-2006-03-19     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4483330> ld64 crashes whenever I try to link with dylib1.o
-       * src/MachOReaderRelocatable.hpp: in Reader<x86_64>::addRelocReference() fix local relocations
 
 ----- Tagged ld64-47.1
 
 
 ----- Tagged ld64-47.1
 
-2006-03-16     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4459633> ld64-41 in Leopard doesn't have x86_64 support
-       * ld64.xcodeproj/project.pbxproj: enable x86_64 for Leopard
 
 ----- Tagged ld64-47
 
 
 ----- Tagged ld64-47
 
-2006-03-14     Nick Kledzik    <kledzik@apple.com>
-
-       * src/Architectures.hpp: redo x86_64 relocation types
-       * src/MachOReaderRelocatable.hpp: redo x86_64 relocation types, make some section type illegal for x86_64
-       * src/MachOWriterExecutable.hpp: redo x86_64 relocation types
-
-2006-03-13     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4467122> ld64 -r does not handle internal relocations for x86_64
-       * src/MachOWriterExecutable.hpp: handle internal relocations in Writer<x86_64>::fixUpReferenceRelocatable()
-         and Writer<x86_64>::addObjectRelocs().
 
 ----- Tagged ld64-46
 
 
 ----- Tagged ld64-46
 
 
 ----- Tagged ld64-45
 
 
 ----- Tagged ld64-45
 
-2006-03-06     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4466930> <rdar://problem/4467982> ld64 failed: rel32 out of range when linking a dylib
-       * src/MachOWriterExecutable.cpp: in  Writer<x86_64>::fixUpReferenceFinal add (int32_t) cast
 
 2006-03-06     Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4466930> LP64/9A122: ld64: hang when trying to link DiscRecording framework
        * src/Options.cpp: addSectionAlignment, warn on zero.  Use log2() for alignment conversion
 
 
 2006-03-06     Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4466930> LP64/9A122: ld64: hang when trying to link DiscRecording framework
        * src/Options.cpp: addSectionAlignment, warn on zero.  Use log2() for alignment conversion
 
-2006-03-06     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4457818> x86_THREAD_STATE64_COUNT will change, ld64 must adapt
-       * src/MachOWriterExecutable.hpp: update ThreadsLoadCommandsAtom<x86_64> for new thread status layout
 
 ----- Tagged ld64-44
 
 
 ----- Tagged ld64-44
 
 
 ----- Tagged ld64-43
 
 
 ----- Tagged ld64-43
 
-2006-03-03     Nick Kledzik    <kledzik@apple.com>
-
-       <rdar://problem/4465443> RIP-relative offsets aren't handled properly when the instruction has immediate operands
-       * src/Architectures.hpp: add x86_64::kPCRel32_*
-       * src/MachOReaderRelocatable.hpp: generate x86_64::kPCRel32_*
-       * src/MachOWriterExecutable.hpp: process x86_64::kPCRel32_*
 
 2006-03-02     Nick Kledzik    <kledzik@apple.com>
 
 
 2006-03-02     Nick Kledzik    <kledzik@apple.com>
 
diff --git a/doc/man/man1/ld.1 b/doc/man/man1/ld.1
new file mode 100644 (file)
index 0000000..835e69e
--- /dev/null
@@ -0,0 +1,1842 @@
+.TH LD 1 "March 18, 2006" "Apple Computer, Inc."
+.SH NAME
+ld \- Mach object file link editor
+.SH SYNOPSIS
+.B ld
+[
+.I "option \&..."
+] [
+.I "file \&..."
+]
+.SH DESCRIPTION
+The
+.I ld
+command combines several Mach-O (Mach object) files into one by combining like sections
+in like segments from all the object files, resolving external references, and
+searching libraries.  In the simplest case several object
+.I files
+are given, and
+.I ld
+combines them, producing an object file which can either be executed or
+become the input for a further
+.I ld
+run.  (In the latter case, the
+.B \-r
+option must be given to preserve the relocation information.)  Unless an output
+file is specified,
+.I ld
+produces a file named
+.BR a.out .
+This file is made executable only if no errors occurred during the link editing
+and there are no undefined symbols.
+.SH "UNIVERSAL FILE SUPPORT"
+The link editor accepts ``universal'' (multiple-architecture) input files, but
+always creates a ``thin'' (single-architecture), standard Mach-O output file.
+The architecture is specified using the
+.B \-arch
+.I " arch_type"
+option.  If this option is not used,
+.IR ld (1)
+attempts to determine the output architecture by examining the first object
+file encountered on the command line.  If it is a ``thin''
+file, its architecture determines that of the output file.  If the first input
+file is a ``universal'' file, the ``best'' architecture for the host is used.
+(See the explanation of the
+.B \-arch
+option, below.)
+.PP
+The compiler driver
+.IR cc (1)
+handles creating universal executables by calling
+.IR ld (1)
+multiple times and using
+.IR lipo (1)
+to create a ``universal'' file from the results of the
+.IR ld (1)
+executions.
+.SH "OUTPUT FILE LAYOUT"
+.PP
+The object files are loaded in the order in which they are specified on the
+command line.  The segments and the
+sections in those segments will appear in the output file in the order they are
+encountered in the object files being linked.  All zero fill sections will appear
+after all non-zero fill sections in their segments.
+.PP
+Sections created from files with the
+.B \-sectcreate
+option will appear in the output file last.  Section names for sections created
+from files are not allowed to overlap with a section name in the same segment
+as a section coming from an object file.  Sections created from files may be in
+a segment which has sections from object files and if so will be loaded at the
+end of the non-zero fill sections for that segment.
+.PP
+If the option
+.B \-seglinkedit
+is specified, the segment it creates is the last segment in the output file.
+.PP
+The address of each segment can be specified with
+.B \-segaddr,
+which takes the segment's name as an argument.
+The address of the first segment can alternatively be specified using
+.B \-seg1addr,
+in which case a segment name is not used.
+Segments that do not have a specified
+address will be assigned addresses in the order in which they appear
+in the output file.  A segment's address will be assigned
+based on the ending address of the previous segment.
+If the address of the
+first segment has not been specified by name,
+its assigned address will be
+the specified (via
+.BR \-seg1addr )
+or default first segment address.
+If neither flag is used to specify the first segment's address, its
+default address is zero
+for all formats except the demand-paged executable format
+.SM (MH_EXECUTE),
+in which case the default first address is the value of the segment alignment.
+.PP
+For demand-paged executable format
+.SM (MH_EXECUTE)
+output files,
+if none of the segments' addresses covers address zero through
+the value of the segment alignment, a segment with no access protection
+will be created to cover those addresses.  This segment, named
+.SM "``_\|_PAGEZERO'',"
+is created so that any attempt to dereference a NULL pointer will cause a
+memory exception.
+.PP
+The entry point of the output file is the beginning of
+the first section in the first segment (unless the
+.B \-e
+option is specified).
+.SH STATIC ARCHIVE LIBRARIES
+.PP
+.I ld
+supports two types of libraries: static archive libraries and dynamic shared
+libraries.  Searching for undefined symbols is performed differently for dynamic
+shared libraries than it is for static archive libraries.  The searching of
+dynamic shared libraries is described later.
+.PP
+When a static archive library is specified as an argument to
+.IR ld ,
+it is searched exactly once, at the
+point it is encountered in the argument list.  Only those members defining an unresolved external
+reference, as defined by the static archive library's table of contents,
+are loaded.  To produce the table of contents, all static archive libraries must be processed by
+.IR ranlib (1).
+.PP
+Generally, a static archive library does not have multiple members that define
+the same symbol.  For these types of libraries, the order of the members is not important, so
+the table of contents can be sorted for faster link editing using the
+.B \-s
+option to
+.IR ranlib (1).
+The first member
+of the static archive library is named
+.SM "``\_\^\_.SYMDEF SORTED'',"
+which is understood to be a sorted table of contents.
+.PP
+If the static archive library does have multiple members that define
+the same symbol, the table of contents that
+.IR ranlib (1)
+produces can't be sorted.  Instead, it follows the order in which the members
+appear in the static archive library.  The link editor searches the table of
+contents iteratively, loading members until no further references are
+satisfied.  In the unsorted case, the first member of the static archive
+library is named
+.SM "``\_\^\_.SYMDEF'',"
+which is understood to be a table of contents in
+the order of the archive members.
+.PP
+Static archive library members can also be loaded in response to
+the
+.B \-ObjC
+and
+.B \-all_load
+flags. See their descriptions below.
+
+.SH DYNAMIC SHARED LIBRARIES
+.PP
+When a dynamic shared library or an object file that was linked against a
+dynamic shared library is specified as an argument to
+.IR ld ,
+that library is placed in the dynamic shared library search list. The order of
+the search list is always the same order the libraries were encountered on the
+command line. When linking -flat_namespace, all dynamic libraries that the
+dynamic libraries are dependent upon are added to the end of the search list.
+.PP
+Once the search list is constructed, the static link editor checks for undefined
+symbols by simulating the way the dynamic linker will search for undefined
+symbols at runtime. For each undefined symbol, the static link editor searches
+each library in the search list until it finds a module that defines the symbol.
+With each undefined symbol, the search starts with the first library in the
+list.  This is different than for static archive libraries, where each library
+is searched exactly once for all undefined symbols.
+.PP
+The static link editor simulates dynamic linking as if all the undefined
+symbols are to be bound at program launch time. The dynamic linker actually
+binds undefined symbols as they are encountered during execution instead of at
+program launch. However, the static link editor always produces the same linking
+as the dynamic linker as long as none of the dynamic shared libraries define the
+same symbol. Different linking can occur only when there is more than one
+definition of a symbol and the library modules that contain the definitions for
+that symbol do not define and reference exactly the same symbols.  In this case,
+even different executions of the same program can produce different linking
+because the dynamic linker binds undefined functions as they are called, and
+this affects the order in which undefined symbols are bound.  Because it can
+produce different dynamic linking, using dynamic shared libraries that define
+the same symbols in the same program is strongly discouraged.
+.PP
+If a static archive library appears after a dynamic shared library on the
+command line, the static library is placed in the dynamic library search list
+and is searched as a dynamic library.  In this way, when a dynamic library has
+undefined symbols, it will cause the appropriate members of the static libraries
+to be loaded into the output.  Searching static libraries as dynamic libraries
+can cause problems if the dynamic library later changes to reference symbols
+from the static library that it did not previously reference. In this case when
+the program runs, the dynamic linker will report these symbols as undefined
+because the members for these symbols were not loaded into the output.
+
+.SH TWO-LEVEL AND FLAT NAMESPACES
+.PP
+Two-level and flat namespaces refer to how references to symbols in dynamic
+libraries are resolved to a definition in specific dynamic library.  For
+two-level namespace that resolution is done at static link time when each
+image (program, bundle and shared library) is built.  When a program is using
+images built with two-level namespace there may be different global symbols
+with the same name being used by different images in the program (this is now
+the default).  When a program is using all flat namespace images then only one
+global symbol for each global symbol name is used by all images of the program
+(this was the default in MacOS X 10.0).
+.PP
+When creating an output file with the static link editor that links against
+dynamic libraries, the references to symbols in those libraries can be recorded
+at static link time to bind to a specific library definition (two-level
+namespace) or left to be bound at execution time to the first library in the
+search order of the program (flat namespace).  A program, its dynamic libraries
+and its bundles may each be either two-level or flat namespace images.  The
+dynamic linker will bind each image according to how it was built.
+.PP
+When creating an output file with the static link editor when
+.B \-twolevel_namespace
+is in effect (now the default) all undefined references must be satisfied at
+static link time.  The flags to allow undefined references,
+.BI \-U symbol_name,
+.BI \-undefined " warning"
+and
+.BI \-undefined " suppress"
+can't be used.
+When the environment variable
+.B MACOSX_DEPLOYMENT_TARGET
+is set to
+.B 10.3
+or higher then
+.BI \-undefined " dynamic_lookup"
+can also be used.  The specific library definition recorded
+for each reference is the first library that has a definition as listed on the
+link line.  Listing an umbrella framework implies all of its sub-frameworks,
+sub-umbrellas and sub-libraries.  For any reference to a definition found in
+an umbrella framework's sub-framework, sub-umbrella or sub-library will be
+recorded as coming from the umbrella framework.  Then at execution time the
+dynamic linker will search that umbrella framework's sub-frameworks,
+sub-umbrellas and sub-libraries for those references.
+Also when two-level namespace is in effect only those frameworks listed on the
+link line (and sub-frameworks, sub-umbrellas and sub-libraries of umbrella
+frameworks) are searched.  Other dependent libraries which are not
+sub-frameworks, sub-umbrellas or sub-libraries of umbrella frameworks are not
+searched.
+.RS
+.PP
+When creating bundles (MH_BUNDLE outputs) with the static link editor when
+two-level namespace is in effect (now the default) and the bundle has
+references to symbols
+expected to be defined in the program loading the bundle, then the
+.BI \-bundle_loader " executable"
+must be used.
+.PP
+When creating a output file with the static link editor when
+.B \-flat_namespace
+is in effect (the MacOS X 10.0 default) all undefined references must be
+satisfied at static link time when
+.BI \-undefined " error"
+(the default) is used.  The static
+link editor checks the undefined references by searching all the libraries
+listed on the link line then all dependent libraries.  The undefined symbols
+in the created output file are left to be resolved at execution time by the
+dynamic link editor in the dynamic libraries in the search order of the program.
+
+.SH MULTIPLY DEFINED SYMBOLS
+.PP
+If there are multiply defined symbols in the object files being linked into
+the output file being created this always results in a multiply defined
+symbol error.
+.PP
+When the static link editor links symbols in from a dynamic library that result
+in multiply defined symbols the handling depends on the type of name space of
+output file being created and possibly the type of name space of the dynamic
+library.
+.PP
+When the static link editor is creating a two-level namespace image and a
+there is a multiply defined symbol from dynamic library then that generates a
+multiply defined symbol warning (by default), where the treatment of this
+warning can be changed with the
+.B \-multiply_defined
+flag.
+.PP
+When the static link editor is creating a flat namespace image and a there is
+a multiply defined symbol from dynamic library, if the library is a flat
+namespace image then that generates a multiply defined symbol error.  If the
+library is a two-level namespace image then that generates a multiply defined
+symbol warning (by default), where the treatment of this warning can be changed
+with the
+.B \-multiply_defined
+flag.
+
+.SH "USING THE DYNAMIC LINK EDITOR AND DYNAMIC SHARED LIBRARIES"
+.PP
+The option
+.B \-dynamic
+must be specified in order to use dynamic shared libraries (and any of the features used to implement them) and/or the dynamic link editor.
+To make sure that the output is not using any features that would
+require the dynamic link editor, the flag
+.B \-static
+can be specified.
+Only one of these flags can be specified.
+
+.SH "LINK EDITOR DEFINED SYMBOLS"
+.PP
+There is a group of link editor defined symbols for the
+.SM MH_EXECUTE,
+.SM MH_DYLIB
+and
+.SM MH_PRELOAD
+file types (see the header file <mach-o/ldsyms.h>).  Link editor symbols are
+reserved; it is an error if an input object file defines such a symbol.
+Only those link editor symbols that are referenced by the object file
+appear in the output file's symbol table.
+.PP
+The link editor defined symbol `\_\^\_mh_execute_header'
+(`\_mh_execute_header' in C) is reserved when the output file format is
+.SM MH_EXECUTE.
+This symbol is the address of the Mach header in a Mach-O executable (a
+file of type
+.SM MH_EXECUTE).
+It does not appear in
+any other Mach-O file type.  It can be used to get to the addresses and
+sizes of all the segments and sections in the executable.  This can be done by parsing the headers
+and load commands (see
+.IR Mach-O (5)).
+.PP
+The link editor defined symbol `\_\^\_mh_dylib_header'
+(`\_mh_dylib_header' in C) is reserved when the output file format is
+.SM MH_DYLIB.
+This symbol is the address of the Mach header in a Mach-O dynamic shared library
+(a file of type
+.SM MH_DYLIB)
+and is a private external symbol.
+It does not appear in
+any other Mach-O file type.  It can be used to get to the addresses and
+sizes of all the segments and sections in a dynamic shared library.  The
+addresses, however, must have the value
+.IR _dyld_get_image_vmaddr_slide (3)
+added to them.
+.PP
+The
+.SM MH_PRELOAD
+file type has link editor defined symbols for the
+beginning and ending of each segment, and for the
+beginning and ending of each section within a segment.
+These names are provided for use in a Mach-O preloaded file,
+since it does not have its headers loaded as part of the first segment.
+The names of the symbols for a segment's beginning and end
+have the form: \_\^\_SEGNAME\_\^\_begin and \_\^\_SEGNAME\_\^\_end,
+where \_\^\_SEGNAME is the name of the segment.  Similarly, the symbols for
+a section have the form:
+\_\^\_SEGNAME\_\^\_sectname\_\^\_begin and \_\^\_SEGNAME\_\^\_sectname\_\^\_end,
+where \_\^\_sectname is the name of the section in the segment \_\^\_SEGNAME.
+These symbols' types are those of the section that the names refer to.
+(A symbol that refers to the end of a section actually has, as its value, the beginning address of the next section, but the symbol's type is still that of the section mentioned in the symbol's name.)
+.SH OPTIONS
+.PP
+.I Ld
+understands several options.  Filenames and
+options that refer to libraries (such as
+.B \-l
+and
+.BR \-framework ),
+as well as options that create symbols (such as
+.B \-u
+and
+.BR \-i ),
+are position-dependent: They define the load order and affect what gets
+loaded from libraries.
+Some
+.I ld
+options overlap with compiler options.  If the compiler driver
+.IR cc (1)
+is used to invoke
+.I ld ,
+it maybe necessary to pass the
+.IR ld (1)
+options to
+.IR cc (1)
+using
+.BR \-Wl,\-option,argument1,argument2 .
+
+In this release of the static link editor, 64-bit code (-arch ppc64) are processed by a separate
+tool /usr/bin/ld64.  Not all of the ld command line options are recognized by this tool.
+The options not currently support for building 64-bit binaries are flagged
+.BR "(32-bit only)" .
+
+The most common option is:
+.TP
+.BI  \-o " name"
+The output file is named
+.IR name ,
+instead of
+.BR a.out .
+
+.PP
+The following flags are related to architectures:
+.TP
+.BI \-arch " arch_type"
+Specifies the architecture,
+.I arch_type,
+for the output file. ``Universal'' input files that do not contain this
+specified architecture are ignored.  Only one
+.BI \-arch " arch_type"
+can be specified.  See
+.IR arch (3)
+for the currently known
+.IR arch_type s.
+If
+.I " arch_type"
+specifies a certain implementation of an architecture (such as
+.BI \-arch " m68040"
+or
+.BI \-arch " i486"
+), the resulting object file has that specific CPU subtype, and it is an
+error if any input file has a CPU subtype that will not combine to the CPU subtype
+for
+.IR " arch_type" .
+.IP
+The default output file architecture is determined by the first object file to
+be linked.  If it is a ``thin'' (standard Mach-O) file, or a ``universal'' file
+that contains only one architecture, the output file will have the same
+architecture.  Otherwise, if it is a ``universal'' file
+containing an architecture that would execute on the host, then the ``best''
+architecture is used, as defined by what the kernel exec(2) would select.
+Otherwise, it is an error, and a
+.BI \-arch " arch_type"
+must be specified.
+.TP
+.B \-arch_multiple
+This flag is used by the
+.IR cc (1)
+driver program when it is run with multiple
+.BI \-arch " arch_type"
+flags.  It instructs programs like
+.IR ld (1)
+to precede any displayed message with a line stating
+the program name, in this case
+.IR ld ,
+and the architecture (from the
+.BI \-arch " arch_type"
+flag).  This helps distinguish which architecture the error messages refer to.
+.TP
+.B \-force_cpusubtype_ALL
+The
+.B \-force_cpusubtype_ALL
+flag causes the CPU subtype to remain the
+.SM ALL
+CPU subtype and not to be combined or
+changed.  This flag has precedence over any
+.BI \-arch " arch_type"
+flag for a specific implementation.
+This is the default for all x86 architectures.
+.PP
+The following flags are related to using the dynamic link editor and/or
+dynamic shared libraries (and any of the features used to implement them):
+.TP
+.B \-dynamic
+Allows use of the features associated with dynamic link editor.  The default is
+.B \-dynamic.
+.TP
+.B \-static
+Causes those features associated with dynamic link editor to be treated as
+an error. (The description for the options that will cause an error if you use them in conjunction with
+.B \-static
+are marked with the statement "when
+.B \-dynamic
+ is used").
+.TP
+.BI \-read_only_relocs " treatment"
+Specifies how relocation entries in read-only sections are to be treated when
+.B \-dynamic
+is used.
+To get the best possible sharing, the read-only sections should not have any
+relocation entries.
+If they do, the dynamic linker will write on the section.
+Having relocation entries appear in read-only sections is normally avoided by compiling with the option
+.B \-dynamic.
+But in such cases non-converted assembly code
+or objects not compiled with
+.B \-dynamic
+relocation entries will appear in read-only sections.
+The
+.I treatment
+can be:
+.I error,
+.I warning,
+or
+.I suppress.
+Which cause the treatment of relocation entries in read-only sections as either,
+errors, warnings, or suppressed messages.
+The default is to treat these as errors.
+.TP
+.BI \-sect_diff_relocs " treatment"
+Specifies how section difference relocation enries are to be treated when
+.B \-dynamic
+and
+.B \-execute
+are used.
+To get the best possible code generation the compiler should not generate code
+for executables (MH_EXECUTE format outputs) that have any section difference
+relocation entries.  The
+.IR gcc (1)
+compiler has the
+.B \-mdynamic-no-pic
+flag for generating code for executables.  The default treatment is
+.I suppress,
+where no message is printed.  The other treatments are
+.I error
+or
+.I warning.
+This option can also be specified by setting the environment variable
+.SM LD_SECT_DIFF_RELOCS
+to the treatment values.
+.TP
+.BI \-weak_reference_mismatches " treatment"
+Specifies how to treat mismatches of symbol references in the the object files
+being linked. Normally the all the undefined symbol references of the object
+files being linked should be consistent for each undefined symbol.  That is all
+undefined symbols should either be weak or non-weak references. The default
+treatment is
+.I error,
+where the link fails with an error message.  The other treatments are
+.I weak
+or
+.I non-weak,
+which makes mismatched undefined symbol references either weak or non-weak
+in the output, respectively.  Care must be taken when using the treatment
+.I weak
+as the use of the non-weak symbol references in an object file may cause the
+program to crash when the symbol is not present at execution time.
+.TP
+.B \-prebind (32-bit only)
+Have the static linker,
+.IR ld (1),
+prebind an executable's or dynamic shared library's undefined symbols to the
+addresses of the dynamic libraries it is being linked with.
+This optimization can only be done if the libraries don't overlap and
+no symbols are overridden.
+When the resulting program is run and the same libraries are used to run the
+program as when the program was linked, the dynamic linker can use the prebound
+addresses.
+If not, the dynamic linker undoes the prebinding and binds normally.
+This option can also be specified by setting the environment variable
+.SM LD_PREBIND.
+If the environment variable
+.SM LD_FORCE_NO_PREBIND
+is set both the option
+.B \-prebind
+.SM LD_PREBIND
+environment variable are ignore and the output is not prebound.
+Or if the environment variable
+.B MACOSX_DEPLOYMENT_TARGET
+is set to 10.4 or greater and the output is not a split a dynamic library the
+output is not prebound.
+.TP
+.B \-noprebind (32-bit only)
+Do not have the static linker,
+.IR ld (1),
+prebind the output.  If this is specified the environment variable
+.SM LD_PREBIND
+is ignored.
+.TP
+.B \-prebind_allow_overlap (32-bit only)
+Have the static linker,
+.IR ld (1),
+prebind the output even if the addresses of the dynamic libraries it uses
+overlap.  The resulting output can then have
+.IR redo_prebinding (1)
+run on it to fix up the prebinding after the overlapping dynamic libraries
+have been rebuilt.  This option can also be specified by setting the
+environment variable
+.SM LD_PREBIND_ALLOW_OVERLAP.
+.TP
+.B \-prebind_all_twolevel_modules (32-bit only)
+Have the static linker,
+.IR ld (1),
+mark all modules from prebound two-level namespace dynamic libraries as used
+by the program even if they are not statically referenced.  This can provide
+improved launch time for programs like Objective-C programs that use symbols
+indirectly through NIB files. This option can also be specified by setting the
+environment variable
+.SM LD_PREBIND_ALL_TWOLEVEL_MODULES.
+.TP
+.B \-noprebind_all_twolevel_modules (32-bit only)
+Don't have the static linker,
+.IR ld (1),
+mark all modules from prebound two-level namespace dynamic libraries as used
+by the program.  This flag overrides the setting of the
+environment variable
+.SM LD_PREBIND_ALL_TWOLEVEL_MODULES.
+.TP
+.B \-nofixprebinding (32-bit only)
+Have the static linker,
+.IR ld (1),
+mark the executable so that the dynamic linker will never notify the prebinding
+agent if this launched and its prebinding is out of date.  This is used when
+building the prebinding agent itself.
+.PP
+The following flags are related to libraries:
+.TP
+.BI \-l x
+This
+option is an abbreviation for the library name
+.RI `lib x .a',
+where
+.I x
+is a string.
+If
+.B \-dynamic
+is specified the abbreviation for the library name is first search as
+.RI `lib x .dylib'
+and then
+.RI `lib x .a'
+is searched for.
+.I ld
+searches for libraries first in any directories
+specified with
+.B \-L
+options, then in any directories specified in the colon separated set of paths
+in the environment variable LD_LIBRARY_PATH, then the standard directories 
+.BR /lib , 
+.BR /usr/lib , 
+and
+.BR "/usr/local/lib" .
+A library is searched when its name is encountered,
+so the placement of the
+.B  \-l
+flag is significant.  If string
+.I x
+is of the form
+.IR x .o,
+then that file is searched for in the same places, but without prepending
+`lib' or appending `.a' or `.dylib' to the filename.
+.TP
+.BI \-weak-l x
+This is the same as the
+.BI \-l x
+but forces the library and all references to it to be marked as weak imports.
+Care must be taken when using this as the use of the non-weak symbol references
+in an object file may cause the program to crash when the symbol or library is
+not present at execution time.
+.TP
+.BI \-weak_library " file_name_path_to_library"
+This is the same as listing a file name path to a library on the link line
+except that it forces the library and all references to it to be marked as
+weak imports.
+Care must be taken when using this as the use of the non-weak symbol references
+in an object file may cause the program to crash when the symbol or library is
+not present at execution time.
+.TP
+.BI \-L dir
+Add
+.I dir
+to the list of directories in which to search for libraries.
+Directories specified with
+.B \-L
+are searched before the standard directories.
+.TP
+.B \-Z
+Do not search the standard directories when searching for libraries.
+.TP
+.BI "\-syslibroot " rootdir " (32-bit only)"
+Prepend
+.I rootdir
+to the standard directories when searching for libraries or frameworks.
+.TP
+.B \-search_paths_first
+By default when the
+.B \-dynamic
+flag is in effect, the
+.BI \-l x
+and
+.BI \-weak-l x
+options first search for a file of the form
+.RI `lib x .dylib'
+in each directory in the library search path, then a file of the form
+.RI `lib x .a'
+is searched for in the library search paths.
+This option changes it so that in each path
+.RI `lib x .dylib'
+is searched for then
+.RI `lib x .a'
+before the next path in the library search path is searched.
+.TP
+.BI "\-framework " name[,suffix]
+Specifies a framework to link against. Frameworks are dynamic shared libraries,
+but they are stored in different locations, and therefore must be searched for
+differently. When this option is specified,
+.I ld
+searches for framework `\fIname\fR.framework/\fIname\fR'
+first in any directories
+specified with the
+.B \-F
+option, then in the standard framework directories
+.BR /Library/Frameworks ,
+.BR /Network/Library/Frameworks ,
+and
+.BR "/System/Library/Frameworks" .
+The placement of the
+.B \-framework
+option is significant, as it determines when and how the framework is searched.
+If the optional suffix is specified the framework is first searched for the
+name with the suffix and then without.
+.TP
+.BI "\-weak_framework " name[,suffix]
+This is the same as the
+.BI "\-framework " name[,suffix]
+but forces the framework and all references to it to be marked as weak imports.
+Care must be taken when using this as the use of the non-weak symbol references
+in an object file may cause the program to crash when the symbol or framework is
+not present at execution time.
+.TP
+.BI \-F dir
+Add
+.I dir
+to the list of directories in which to search for frameworks.
+Directories specified with
+.B \-F
+are searched before the standard framework directories.
+.TP
+.B \-ObjC
+Loads all members of static archive libraries that define an Objective C class or a category. This option does not apply to dynamic shared libraries.
+.TP
+.B \-all_load
+Loads all members of static archive libraries.
+This option does not apply to dynamic shared
+libraries.
+.TP
+.BI \-dylib_file " install_name:file_name" (32-bit only)
+Specifies that a dynamic shared library is in a different location than its standard location. Use this option when you link with a library that is dependent on a dynamic library, and the dynamic library is in a location other than its default location.
+.I install_name
+specifies the path where the library normally resides.
+.I file_name
+specifies the path of the library you want to use instead.
+For example, if you link to a library that depends upon the dynamic library libsys and you have libsys installed in a nondefault location, you would use this option:
+\fB\-dylib_file /lib/libsys_s.A.dylib:/me/lib/libsys_s.A.dylib\fR.
+.TP
+.BI \-executable_path " path_name" (32-bit only)
+Specifies that
+.I path_name
+is used to replace
+.I @executable_path
+for dependent libraries.
+
+.PP
+The following options specify the output file format (the file type):
+.TP
+.B "\-execute"
+Produce a Mach-O demand-paged executable format file.  The headers are placed
+in the first segment, and all segments are padded to the segment alignment.
+This has a file type of
+.SM MH_EXECUTE.
+This is the default.  If no segment address is specified at address zero, a
+segment with no protection (no read, write, or execute permission) is created
+at address zero.
+This segment, whose size is that of the segment
+alignment, is named
+.SM ``_\|_PAGEZERO''.
+This option was previously named
+.BR "\-Mach" ,
+which will continue to be recognized.
+.TP
+.B \-object (32-bit only)
+Produce a Mach-O file in the relocatable object file format that is
+intended for execution.  This differs from using the
+.B \-r
+option in that it defines common symbols, does not allow undefined symbols and
+does not preserve relocation entries.  This has a file type of
+.SM MH_OBJECT.
+In this format all sections are placed in one unnamed segment with all
+protections (read, write, execute) allowed on that segment.  This is intended
+for extremely small programs that would otherwise be large due to segment
+padding.  In this format, and all
+.SM non-MH_EXECUTE
+formats, the link editor
+defined symbol ``\_\^\_mh_execute_header'' is not defined since the headers are
+not part of the segment.  This format file can't be used with the dynamic
+linker.
+.TP
+.B \-preload (32-bit only)
+Produce a Mach-O preloaded executable format file.  The headers are not placed
+in any segment.  All sections are placed in their proper segments and they are
+padded to the segment alignment.  This has a file type of
+.SM MH_PRELOAD.
+This option was previously
+.BR "\-p" ,
+which will continue to be recognized.
+.TP
+.B "\-dylib"
+Produce a Mach-O dynamically linked shared library format file.  The headers are
+placed in the first segment.  All sections are placed in their proper segments
+and they are padded to the segment alignment.  This has a file type of
+.SM MH_DYLIB.
+This option is used by
+.IR libtool (1)
+when its
+.B \-dynamic
+option is specified.
+.TP
+.B "\-bundle"
+Produce a Mach-O bundle format file.  The headers are placed in the first
+segment.  All sections are placed in their proper segments
+and they are padded to the segment alignment.  This has a file type of
+.SM MH_BUNDLE.
+.TP
+.B "\-dylinker"
+Produces a Mach-O dynamic link editor format file.  The headers are placed in the
+first segment.  All sections are placed in their proper segments, and they are
+padded to the segment alignment.  This has a file type of
+.SM MH_DYLINKER.
+.TP
+.B \-fvmlib (32-bit only)
+Produce a Mach-O fixed VM shared library format file.  The headers are placed
+in the first segment but the first section in that segment will be placed on
+the next segment alignment boundary in that segment.  All sections are placed
+in their proper segments and they are padded to the segment alignment.
+This has a file type of
+.SM MH_FVMLIB.
+
+.PP
+The following flags affect the contents of the output file:
+.TP
+.B  \-r
+Save the relocation information in the output file
+so that it can be the subject of another
+.I ld
+run.  The resulting file type is a Mach-O relocatable file
+.SM (MH_OBJECT)
+if not otherwise specified.
+This flag also prevents final definitions from being
+given to common symbols,
+and suppresses the `undefined symbol' diagnostics.
+.TP
+.B  \-d (32-bit only)
+Force definition of common storage even if the
+.B \-r
+option is present.  This option also forces link editor defined symbols to be defined.
+This option is assumed when there is a dynamic link editor load command in the input
+and
+.B \-r
+is not specified.
+
+.PP
+The following flags support segment specifications:
+.TP
+.BI "\-segalign" " value" " (32-bit only)"
+Specifies the segment alignment.
+.I value
+is a hexadecimal number that must be an integral power of 2.
+The default is the target pagesize (currently 1000 hex for the PowerPC and
+i386).
+.TP
+.BI "\-seg1addr" " addr"
+Specifies the starting address of the first segment in the output file.
+.I addr
+is a hexadecimal number and must be a multiple of the segment alignment.
+This option can also be specified as
+.B "\-image_base."
+.TP
+.BI "\-segaddr" " name addr" " (32-bit only)"
+Specifies the starting address of the segment named
+.I name
+to be
+.I addr.
+The address must be a hexadecimal number that is a multiple of the segment alignment.
+.TP
+.BI "\-segs_read_only_addr" " addr" " (32-bit only)"
+Specifies the starting address of the read-only segments in a dynamic shared
+library.  When this option is used the dynamic shared library is built such
+that the read-only and read-write segments are split into separate address
+ranges.  By default the read-write segments are 256meg (0x10000000) after
+the read-only segments.
+.I addr
+is a hexadecimal number and must be a multiple of the segment alignment.
+.TP
+.BI "\-segs_read_write_addr" " addr" " (32-bit only)"
+Specifies the starting address of the read-write segments in a dynamic shared
+library.  When this option is used the
+.B \-segs_read_only_addr
+must also be used (see above).
+.I addr
+is a hexadecimal number and must be a multiple of the segment alignment.
+.TP
+.BI "\-seg_addr_table" " filename" " (32-bit only)"
+For dynamic shared libraries the
+.B "\-seg1addr"
+or the pair of
+.B "\-segs_read_only_addr"
+and
+.B "\-segs_read_write_addr"
+are specified by an entry in the segment address table in
+.I filename
+that matches the install name of the library.
+The entries in the table are lines containing either a single hex address and an
+install name or two hex addresses and an install name.  In the first form the
+single hex address is used as the
+.B "\-seg1addr".
+In the second form the first address is used as the
+.B "\-segs_read_only_addr"
+address and the second address is used as the
+.B "\-segs_read_write_addr"
+address.
+This option can also be specified by setting the environment variable
+.SM LD_SEG_ADDR_TABLE.
+If the environment variable is set then any
+.BR "\-seg1addr" ,
+.BR "\-segs_read_only_addr" ,
+.B "\-segs_read_write_addr"
+and
+.B "\-seg_addr_table"
+options are ignored and a warning is printed.
+.TP
+.BI "\-seg_addr_table_filename" " pathname" " (32-bit only)"
+Use
+.B pathname
+instead of the install name of the library for matching an entry in the segment
+address table.
+.TP
+.BI "\-segprot" " name max init" " (32-bit only)"
+Specifies the maximum and initial virtual memory protection of the named
+segment,
+.I name,
+to be
+.I max
+and
+.I init
+,respectively.  The values for
+.I max
+and
+.I init
+are any combination of the characters `r' (for read), `w' (for write),
+`x' (for execute) and '\-' (no access).  The default is `rwx' for the maximum
+protection for all segments for PowerPC architecures and `rw` for the all Intel
+architecures.
+The default for the initial protection for all segments is `rw' unless the
+segment contains a section which contains some machine instructions, in which
+case the default for the initial protection is `rwx' (and for Intel
+architecures it also sets the maximum protection to `rwx' in this case).
+The default for the initial protection for the
+.SM "``_\|_TEXT''"
+segment is `rx' (not writable).
+.TP
+.B \-seglinkedit (32-bit only)
+Create the link edit segment, named
+.SM "``_\|_LINKEDIT''"
+(this is the default).
+This segment contains all the link edit information (relocation information,
+symbol table, string table, etc.) in the object file.  If the segment protection
+for this segment is not specified, the initial protection is not writable.
+This can only be specified when the output file type is not
+.SM MH_OBJECT
+and
+.SM MH_PRELOAD
+output file types.  To get at the contents of this section, the Mach header
+and load commands must be parsed from the link editor defined symbols like
+`\_\^\_mh_execute_header' (see
+.IR Mach-O (5)).
+.TP
+.B \-noseglinkedit (32-bit only)
+Do not create the link edit segment (see
+.B \-seglinkedit
+above).
+.TP
+.BI "\-pagezero_size" " value"
+Specifies the segment size of _\|_PAGEZERO to be of size
+.IR value ,
+where
+.I value
+is a hexadecimal number rounded to the segment alignment.
+The default is the target pagesize (currently, 1000 hexadecimal for the PowerPC
+and for i386).
+.TP
+.BI "\-stack_addr" " value"
+Specifies the initial address of the stack pointer
+.IR value ,
+where
+.I value
+is a hexadecimal number rounded to the segment alignment.
+The default segment alignment is the target pagesize (currently, 1000
+hexadecimal for the PowerPC and for i386).
+If
+.B \-stack_size
+is specified and
+.B \-stack_addr
+is not, a default stack address specific for the architecture being linked will
+be used and its value printed as a warning message.
+This creates a segment named _\|_UNIXSTACK.  Note that the initial stack address
+will be either at the high address of the segment or the low address of the
+segment depending on which direction the stack grows for the architecture being
+linked.
+.TP
+.BI "\-stack_size" " value"
+Specifies the size of the stack segment
+.IR value ,
+where
+.I value
+is a hexadecimal number rounded to the segment alignment.
+The default segment alignment is the target pagesize (currently, 1000
+hexadecimal for the PowerPC and for i386).
+If
+.B \-stack_addr
+is specified and
+.B \-stack_size
+is not, a default stack size specific for the architecture being linked will be
+used and its value printed as a warning message.
+This creates a segment named _\|_UNIXSTACK .
+.TP
+.B \-allow_stack_execute
+Marks executable so that all stacks in the task will be given stack execution
+privilege.  This includes pthread stacks.
+
+.PP
+The following flags support section specifications:
+.TP
+.BI "\-sectcreate" " segname sectname file"
+The section
+.I sectname
+in the segment
+.I segname
+is created from the contents of
+.I file.
+The combination of
+.I segname
+and
+.I sectname
+must be unique; there cannot already be a section
+.I (segname,sectname)
+in any input object file.
+This option was previously called
+.BR "\-segcreate" ,
+which will continue to be recognized.
+.TP
+.BI "\-sectalign" " segname sectname value"
+The section named
+.I sectname
+in the segment
+.I segname
+will have its alignment set to
+.IR value ,
+where
+.I value
+is a hexadecimal number that must be an integral power of 2.
+This can be used to set the alignment of a section created from a file, or to
+increase the alignment of a section from an object file, or to set the maximum
+alignment of the
+.SM (_\|_DATA,_\|_common)
+section, where common symbols are defined
+by the link editor.  Setting the alignment of a literal section causes the
+individual literals to be aligned on that boundary.  If the section
+alignment is not specified by a section header in an object file or on the
+command line, it defaults to 10 (hex), indicating 16-byte alignment.
+.TP
+.BI "\-sectorder" " segname sectname orderfile" (32-bit only)
+The section
+.I sectname
+in the segment
+.I segname
+of the input files will be broken up into blocks associated with
+symbols in the section.  The output section will be created by ordering
+the blocks as specified by the lines in the
+.I orderfile.
+These blocks are aligned to the output file's section alignment for this
+section.  Any section can be ordered in the output file except symbol pointer and symbol stub sections.
+.IP
+For non-literal sections, each line of the
+.I orderfile
+contains an object name and a symbol name, separated by a single colon (':').
+Lines that start with # are ignored and treated as comments.
+If the object file is
+in an archive, the archive name, followed by a single colon, must precede the
+object file name.  The object file names and archive names should be exactly the
+names as seen by the link editor, but if not, the link editor attempts to match
+up the names the best it can.
+For non-literal sections, the easiest way to generate an order file is
+with the ``\f3\-jonls +\f2segname sectname\f1'' options to
+.IR nm (1).
+.IP
+The format of the
+.I orderfile
+for literal sections is specific to each type of literal section.  For C
+string literal sections, each line of the order file contains one literal C
+string, which may include ANSI C escape sequences.  For four-byte literal
+sections, the order file format is one 32-bit hex number with a leading 0x
+per
+line, with the rest of the line treated as a comment.  For eight-byte literal
+sections, the order file has two 32-bit hex numbers per line; each number
+has a leading 0x, the two numbers are separated by white
+space, and the rest of the line is treated as a comment.
+For literal pointer sections, the lines in the order file represent
+pointers, one per line.  A literal pointer is represented by the name of
+the segment that contains the literal being pointed to, followed by the
+section name, followed by the literal. These three strings are separated
+by colons with no extra white space.
+For all the literal sections, each line in the the order file is simply entered
+into the literal section and will appear in the output file in the same order
+as in the
+order file.  There is no check to see whether the literal is present
+in the loaded objects.
+For literal sections, the easiest way to generate an order file is with
+the ``\f3\-X \-v \-s \f2segname sectname\f1'' options to
+.IR otool (1).
+.TP
+.B \-sectorder_detail (32-bit only)
+When using the
+.B \-sectorder
+option,  any pairs of object file names and symbol names that are found in
+the loaded objects, but not specified in the
+.IR orderfile ,
+are placed last in the output file's section.   These pairs are ordered by
+object file (as the filenames appear
+on the command line), with the different symbols from a given object
+file being ordered by
+increasing symbol address (that is, the order
+in which the symbols occurred in the object file,
+not their order in the symbol table).  By default, the link editor displays a summary
+that simply shows the number
+of symbol names found in the loaded objects but not in the
+.IR orderfile ,
+as well as the number of symbol names listed in the
+.I orderfile
+but not found in the loaded objects.  (The summary is omitted if both values
+are zero.)  To instead produce a detailed list of these symbols, use the
+.B \-sectorder_detail
+flag.  If an object file-symbol name pair is listed multiple times, a
+warning is generated, and the first occurrence is used.
+.TP
+.BI "\-sectobjectsymbols" " segname sectname" " (32-bit only)"
+This causes the link editor to generate local symbols in the section
+.I sectname
+in the segment
+.IR segname .
+Each object file that has one of these sections will have a local
+symbol created
+whose name is that of the object file, or of the member of the archive.
+The symbol's value will be the first address where that object file's section
+was loaded.  The symbol has the type N_SECT and its section number is the
+the same as that of the section
+.I (segname,sectname)
+in the output file.
+This symbol will be placed in the symbol table just before all other local
+symbols
+for the object file.  This feature is typically used where the section is
+.SM (\_\^\_TEXT,\_\^\_text),
+in order to help the debugger debug object files produced by old versions of
+the compiler or by non-Apple compilers.
+
+.PP
+The following flags are related to name spaces:
+.TP
+.B \-twolevel_namespace
+Specifies the output to be built as a two-level namespace image.
+This option can also be specified by setting the environment variable
+.SM LD_TWOLEVEL_NAMESPACE.
+This is the default.
+.TP
+.B \-flat_namespace
+Specifies the output to be built as a flat namespace image.
+This is not the default (but was the default in MacOS X 10.0).
+.TP
+.B \-force_flat_namespace
+Specifies the executable output to be built and executed treating all its
+dynamic libraries as flat namespace images.  This marks the executable so that
+the dynamic link editor treats all dynamic libraries as flat namespace
+images when the program is executed.
+.TP
+.BI \-bundle_loader " executable" " (32-bit only)"
+This specifies the
+.I executable
+that will be loading the bundle output file being linked.  Undefined symbols
+from the bundle are checked against the specified executable like it was one of
+the dynamic libraries the bundle was linked with.  If the bundle being created
+with
+.B \-twolevel_namespace
+in effect then the searching of the executable for
+symbols is based on the placement of the
+.B \-bundle_loader
+flag relative to the dynamic libraries.  If the the bundle being created with
+.B \-flat_namespace
+then the searching of the executable is done before all dynamic libraries.
+.TP
+.B \-private_bundle (32-bit only)
+This allows symbols defined in the output to also be defined in executable in
+the
+.B \-bundle_loader
+argument
+when
+.B \-flat_namespace
+is in effect.
+This implies that the bundle output file being created is going to be loaded by
+the executable with the
+.B NSLINKMODULE_OPTION_PRIVATE
+option to
+.IR NSLinkModule (3).
+.TP
+.B \-twolevel_namespace_hints (32-bit only)
+Specifies to create the output with the two-level namespace hints table to be
+used by the dynamic linker.  This is the default except when the
+.B \-bundle
+flag is specified.  If this is used when the
+.B \-bundle
+flag is specified the bundle will fail to load on a MacOS X 10.0 system with a
+malformed object error.
+.TP
+.BI \-multiply_defined " treatment" " (32-bit only)"
+Specifies how multiply defined symbols in dynamic libraries when
+.B \-twolevel_namespace
+is in effect are to be treated.
+.I treatment
+can be:
+.I error,
+.I warning,
+or
+.I suppress.
+Which cause the treatment of multiply defined symbols in dynamic libraries
+as either, errors, warnings, or suppresses the checking of multiply symbols
+from dynamic libraries when
+.B \-twolevel_namespace
+is in effect.
+The default is to treat multiply defined symbols in dynamic libraries as
+warnings when
+.B \-twolevel_namespace
+is in effect.
+.TP
+.BI \-multiply_defined_unused " treatment" " (32-bit only)"
+Specifies how unused multiply defined symbols in dynamic libraries when
+.B \-twolevel_namespace
+is in effect are to be treated.
+An unused multiply defined symbol is one in which there is a symbol defined in
+the output that is also defined in the dynamic libraries the output is linked
+with but the symbol in the dynamic library is not used by any reference in the
+output.
+.I treatment
+can be:
+.I error,
+.I warning,
+or
+.I suppress.
+The default for unused multiply defined symbols is to suppress these messages.
+.TP
+.B -nomultidefs (32-bit only)
+specifying this flag marks the umbrella being created such that the dynamic
+linker is guaranteed that no multiple definitions of symbols in the umbrella's
+sub-images will ever exist.  This allows the dynamic linker to always use the
+two-level namespace lookup hints even if the timestamps of the sub-images
+do not match.  This flag implies
+.BI \-multiply_defined " error".
+
+.PP
+The following flags are related to symbols.  These flags' arguments
+are external symbols whose names have `_' prepended to the C,
+.SM FORTRAN,
+or Pascal variable name.
+.TP
+.BI \-y sym " (32-bit only)"
+Display each file in which
+.I sym
+appears, its type, and whether the file defines or references it.  Any
+multiply defined symbols are automatically
+traced.  Like most of the other symbol-related flags,
+.B \-y
+takes only one argument; the flag may be specified more than once in the
+command line to trace more than one symbol.
+.TP
+.BI \-Y " number" " (32-bit only)"
+For the first
+.I number
+undefined symbols, displays each file in which the symbol appears, its type and whether the file defines or references it (that is, the same style of output produced by the
+.B \-y
+option). To keep the output manageable, this option displays at most
+.I number
+references.
+.TP
+.B \-keep_private_externs
+Don't turn private external symbols into static symbols, but rather leave them
+as private external in the resulting output file.
+.TP
+.B \-m (32-bit only)
+Don't treat multiply defined symbols from the linked objects as a hard error;
+instead, simply print a warning.  The first linked object defining such a symbol
+is used for linking; its value is used for the symbol in the symbol table.  The
+code and data for all such symbols are copied into the output.  The duplicate
+symbols other than the first symbol may still end up being used in the resulting
+output file through local references.  This can still produce a resulting output
+file that is in error.  This flag's use is strongly discouraged!
+.TP
+.B \-whyload (32-bit only)
+Indicate why each member of a library is loaded.  In other words, indicate
+which currently undefined symbol is being resolved, causing that
+member to be loaded.  This in combination with the above
+.BI \-y sym
+flag can help determine exactly why a link edit is failing due to multiply
+defined symbols.
+.B
+.TP
+.BI  \-u " sym"
+Enter the argument
+.I sym
+into the symbol table as an undefined symbol.  This is useful
+for loading wholly from a library, since initially the symbol
+table is empty and an unresolved reference is needed
+to force the loading of the first object file.
+.TP
+.BI \-e " sym"
+The argument
+.I sym
+is taken to be the symbol name of the entry point of
+the resulting file.  By default, the entry point is the address of the
+first section in the first segment.
+.TP
+.BI \-i definition:indirect " (32-bit only)"
+Create an indirect symbol for the symbol name
+.I definition
+which is defined to be the same as the symbol name
+.I indirect
+(which is taken to be undefined).  When a definition of the symbol named
+.I indirect
+is linked, both symbols will take on the defined type and value.
+.IP
+This option overlaps with a compiler option.
+If you use the compiler driver
+.IR cc (1)
+to invoke \fIld\fR,
+invoke this option in this way:
+.BI \-Wl,\-i definition:indirect.
+
+.TP
+.BI \-undefined " treatment"
+Specifies how undefined symbols are to be treated.
+.I treatment
+can be:
+.I error,
+.I warning,
+or
+.I suppress.
+Which cause the treatment of undefined symbols as either, errors, warnings, or
+suppresses the checking of undefined symbols.
+The default is to treat undefined symbols as errors.
+When the environment variable
+.B MACOSX_DEPLOYMENT_TARGET
+is set to
+.B 10.3
+or higher then
+.BI \-undefined " dynamic_lookup"
+can also be used to allow any undefined symbols to be looked up dynamically at
+runtime.  Use of a binary built with this flag requires a system with a dynamic
+linker from Mac OS X 10.3 or later.
+The flag
+.BI \-undefined " define_a_way"
+can also be used to cause the static linker to create a private definition for
+all undefined symbols.  This flag should only be used if it is known that the
+undefined symbols are not referenced as any use of them may cause a crash.
+.TP
+.BI  \-U " sym"
+Allow the symbol
+.I sym
+to be undefined, even if the
+.B \-r
+flag is not given.  Produce an executable file if the only undefined
+symbols are those specified with
+.BR \-U.
+.IP
+This option overlaps with a compiler option.
+If you use the compiler driver
+.IR cc (1)
+to invoke \fIld\fR,
+invoke this option in this way:
+.BI \-Wl,\-U, sym.
+.TP
+.B \-bind_at_load
+Causes the output file to be marked such that the dynamic linker will bind all
+undefined references when the file is loaded or launched.
+.TP
+.BI \-commons " treatment" " (64-bit only)"
+Specifies how common symbols (tentative defintions) from object files interact with dynamic libraries.
+.I treatment
+can be:
+.I ignore_dylibs,
+.I use_dylibs,
+or
+.I error.
+The default is ignore_dylibs
+which means the static linker will use a common defintion from an object file even if a true definition
+exisits in a dynamic library.  If you want your code to use a dynamic library definition, then add
+the extern keyword to your tentative definition (e.g. change
+.I int foo;
+to
+.I extern int foo;
+).  The treatment use_dylibs means a definition form a dynamic library should override a common symbol
+in an object file. Note, the 32-bit linker always uses this treatment.
+The treatment error means the linker should abort whenever if finds a common symbol in
+an object file and an external definition with the same name in a dynamic library.
+.TP
+.B \-warn_commons (64-bit only)
+Causes the static linker to write a diagnostic line about how common symbols were processed.  This is
+useful for debugging problems with common symbols.
+
+.PP
+The following flags are related to stripping link edit information.
+This information can also be removed by
+.IR strip (1),
+which uses the same options.  (The
+exception is the
+.B \-s
+flag below, but this is the same as
+.IR strip (1)
+with no arguments.)
+The following flags are listed in decreasing level of stripping.
+.TP
+.B \-s (32-bit only)
+Completely strip the output; that is, remove the symbol table
+and relocation information.
+.TP
+.B \-x (32-bit only)
+Strips the non-global symbols; only saves external symbols.
+.IP
+This option overlaps with a compiler option.
+If you use the compiler driver
+.IR cc (1)
+to invoke \fIld\fR,
+invoke this option in this way:
+.B \-Wl,\-x.
+.TP
+.B \-S (32-bit only)
+Strip debugging symbols; only save local and global symbols.
+.TP
+.B \-X (32-bit only)
+Strip local symbols whose names begin with `L'; save all other symbols.
+(The compiler and assembler currently strip these internally-generated
+labels by default, so they generally do not appear in object files
+seen by the link editor.)
+.TP
+.B \-Sp
+Strip, edit and add debugging symbols so the debugger can used most of the
+debugging symbols from the object files.
+.TP
+.B \-Si (32-bit only)
+Strip duplicate debugging symbols from include files.  This is
+the default.
+.TP
+.B  \-b (32-bit only)
+Strip the base file's symbols from the output file.  (The base file
+is given as the argument to the
+.B \-A
+option.)
+.IP
+This option overlaps with a compiler option.
+If you use the compiler driver
+.IR cc (1)
+to invoke \fIld\fR,
+invoke this option in this way:
+.B \-Wl,\-b.
+.TP
+.B \-Sn (32-bit only)
+Don't strip any symbols.
+.TP
+.BI \-exported_symbols_list " filename"
+The specified
+.I filename
+contains lists of global symbol names that will remain as global symbols in the
+output file.  All other global symbols will be treated as if they were marked as
+.I __private_extern__
+and will not be global in the output file. The symbol names listed in
+.I filename
+must be one per line. Leading and trailing white space are not part of the
+symbol name.  Lines starting with # are ignored, as are lines with only white
+space.
+.TP
+.BI \-unexported_symbols_list " filename"
+The specified
+.I filename
+contains lists of global symbol names that will not remain as global symbols in
+the output file.  The symbols will be treated as if they were marked as
+.I __private_extern__
+and will not be global in the output file. The symbol names listed in
+.I filename
+must be one per line. Leading and trailing white space are not part of the
+symbol name.  Lines starting with # are ignored, as are lines with only white
+space.
+.TP
+.BI \-no_uuid
+Do not emit an LC_UUID load command in the linked output file.
+
+.TP
+.B -dead_strip (32-bit only)
+Remove blocks of code and data that are unreachable by the entry point or
+exported symbols.
+.TP
+.B -no_dead_strip_inits_and_terms (32-bit only)
+When specified along with
+.B -dead_strip
+cause all constructors and destructors to never be dead stripped.
+
+.PP
+The remaining options are infrequently used:
+.TP
+.B \-v
+Print the version of the linker.
+.TP
+.B \-w (32-bit only)
+Suppresses all warning messages.
+.TP
+.B \-no_arch_warnings
+Suppresses warning messages about files that have the wrong architecture for the
+.B \-arch
+flag.
+.TP
+.B \-arch_errors_fatal (32-bit only)
+Cause the errors having to do with files that have the wrong architecture to be
+fatal and stop the link editor.
+.TP
+.B \-M (32-bit only)
+Produce a load map, listing all the segments and sections.  The list
+includes the address where each input file's section appears in the
+output file, as well as the section's size.
+.IP
+This option overlaps with a compiler option.
+If you use the compiler driver
+.IR cc (1)
+to invoke \fIld\fR,
+invoke this option in this way:
+.B \-Wl,\-M.
+.TP
+.B \-whatsloaded (32-bit only)
+Display a single line listing each object file that is
+loaded.  Names of objects in archives have the form libfoo.a(bar.o).
+.TP
+.BI \-filelist " listfile[,dirname]"
+Specifies that the linker should link the files listed in
+.I listfile .
+This is an alternative to listing the files on the command line. The file names are listed one per line separated
+only by newlines. (Spaces and tabs are assumed to be part of the file name.)
+If the optional directory name,
+.I dirname
+is specified, it is prepended to each name in the list file.
+.TP
+.BI "\-headerpad" " value"
+Specifies the minimum amount of space ("padding") following
+the headers for the
+.SM MH_EXECUTE
+format and all output file types with the dynamic linker.
+.I value
+is a hexadecimal number.
+When a segment's size is rounded up to the segment alignment, there
+is extra space left over, which is placed between the headers and the sections, rather than at the end of the segment.  The
+.B headerpad
+option specifies the minimum size of this padding,
+which can be useful if the headers will be altered later.
+The default value is the larger of 2 * sizeof(struct section) so the program
+/usr/bin/objcunique can always add two section headers, or if the output is an
+MH_EXECUTE filetype and
+.B \-prebind
+is specified 3 times the size of the LC_PREBOUND_DYLIB load commands.
+The actual amount of pad will be as large as the amount of the first
+segment's round-off.
+(That is, take the total size of the first segments'
+headers and non-zerofill sections, round this size
+up to the segment alignment,
+and use the difference between the rounded
+and unrounded sizes as the minimum amount of padding.)
+.TP
+.B \-headerpad_max_install_names (32-bit only)
+Add to the header padding enough space to allow changing all dynamic shared
+library paths recorded in the output file to be changed to MAXPATHLEN in length.
+.TP
+.B \-t
+Trace the progress of the link editor; display the name of each file
+that is
+loaded as it is processed in the first and second pass of the link
+editor.
+.TP
+.BI \-A " basefile" " (32-bit only)"
+Incremental loading: linking is to be done in a manner
+that lets the resulting object be read into an already executing
+program, the
+.IR basefile .
+.I basefile
+is the name of a file whose symbol table will be taken as a basis
+on which to define additional symbols.
+Only newly linked material will be entered into the
+.BR a.out
+file, but the new symbol table will reflect
+every symbol defined in the base file and the newly linked files.
+Option(s) to specify the addresses of the segments are typically
+needed, since
+the default addresses tend to overlap with the
+.I basefile.
+The default format of the object file is
+.SM MH_OBJECT.
+Note: It is strongly recommended that this option NOT be used,
+because the dyld package described in
+.IR dyld (3)
+is a much easier alternative.
+.TP
+.BI \-dylib_install_name " name"
+For dynamic shared library files, specifies the name of the file
+the library will be installed in for programs that use it.  If this is not
+specified, the name specified in the
+.BI \-o " name"
+option will be used.
+This option is used as the
+.IR libtool (1)
+.BI \-install_name " name"
+option when its
+.B \-dynamic
+option is specified.
+.TP
+.BI \-umbrella " framework_name"
+Specifies this is a subframework where
+.I framework_name
+is the name of the umbrella framework this subframework is a part of.  Where
+.I framework_name
+is the same as the argument to the
+.BI \-framework " framework_name"
+option.  This subframework can then only be linked into the umbrella framework
+with the same
+.I framework_name
+or another subframework with the same umbrella framework name.  Any other
+attempt to statically link this subframework directly will result in an error
+stating to link with the umbrella framework instead.  When building the umbrella
+framework that uses this subframework no additional options are required.
+However the install name of the umbrella framework, required to be specified
+with
+.BR \-dylib_install_name ,
+must have the proper format for an install name of a framework for the
+.I framework_name
+of the umbrella framework to be determined.
+.TP
+.BI \-allowable_client " client_name" " (32-bit only)"
+Specifies that for this subframework the
+.I client_name
+can link with this subframework without error even though it is not part of
+the umbrella framework that this subframework is part of.  The
+.I client_name
+can be another framework name or a name used by bundles (see the
+.BI \-client_name " client_name"
+option below).
+.TP
+.BI \-client_name " client_name" " (32-bit only)"
+Specifies the
+.I client_name
+of a bundle for checking of allowable clients of subframeworks (see the
+.BI \-allowable_client " client_name"
+option above).
+.TP
+.BI \-sub_umbrella " framework_name"
+Specifies that the
+.I framework_name
+being linked by a dynamic library is to be treated as one of the
+subframeworks with respect to twolevel namespace.
+.TP
+.BI \-sub_library " library_name"
+Specifies that the
+.I library_name
+being linked by a dynamic library is to be treated as one of the
+sublibraries with respect to twolevel namespace.  For example the
+.I library_name
+for
+.I /usr/lib/libobjc_profile.A.dylib
+would be
+.I libobjc.
+.TP
+.BI \-init " sym"
+The argument
+.I sym
+is taken to be the symbol name of the dynamic shared library initialization
+routine.  If any module is used from the dynamic library the library
+initialization routine is called before any symbol is used from the library
+including C++ static initializers (and #pragma CALL_ON_LOAD routines).
+.TP
+.B \-run_init_lazily (32-bit only)
+This option is obsolete.
+.TP
+.BI \-dylib_compatibility_version " number"
+For dynamic shared library files, this specifies the compatibility version number
+of the library.  When a library is used by a program, the compatibility version is checked
+and if the program's version is greater that the library's version, it is an error.
+The format of
+.I number
+is
+.I X[.Y[.Z]]
+where
+.I X
+must be a positive non-zero number less than or equal to 65535, and
+.I .Y
+and
+.I .Z
+are optional and if present must be non-negative numbers less than or
+equal to 255.
+If the compatibility version number is not specified, it has a
+value of 0 and no checking is done when the library is used.
+This option is used as the
+.IR libtool (1)
+.BI \-compatibility_version " number"
+option
+when its
+.B \-dynamic
+option is set.
+.TP
+.BI \-dylib_current_version " number"
+For dynamic shared library files, specifies the current version number
+of the library.  The current version of the library can be obtained
+programmatically by the user of the library so it can determine exactly which version of the library it is using.
+The format of
+.I number
+is
+.I X[.Y[.Z]]
+where
+.I X
+must be a positive non-zero number less than or equal to 65535, and
+.I .Y
+and
+.I .Z
+are optional and if present must be non-negative numbers less than or
+equal to 255.
+If the version number is not specified, it has a
+value of 0.
+This option is used as the
+.IR libtool (1)
+.BI \-current_version " number"
+option when its
+.B \-dynamic
+option is set.
+.TP
+.BI \-single_module
+When building a dynamic library build the library so that it contains only
+one module.
+.TP
+.BI \-multi_module  (32-bit only)
+When building a dynamic library build the library so that it contains one
+module for each object file linked in.  This is the default.
+.TP
+.BI \-dylinker_install_name " name"
+For dynamic link editor files, specifies the name of the file
+the dynamic link editor will be installed in for programs that use it.
+.TP
+.BI \-macosx_version_min " version"
+This overrides the
+.B MACOSX_DEPLOYMENT_TARGET
+environment variable (see below).  Unlike other linker options, this one may
+be specified multiple times; only the last occurrence is effective.
+.PP
+The following environment variable is used to control the use of incompatible
+features in the output with respect to Mac OS X releases.
+.TP
+.B MACOSX_DEPLOYMENT_TARGET
+This is set to indicate the oldest Mac OS X version that that the output is to
+be used on.  When this is set to a release that is older than the current
+release features that are incompatible with that release will be disabled.  If
+a feature is seen in the input that can't be in the output due to this setting
+a warning is issued.  The current allowable values for this are
+.B 10.1,
+.B 10.2
+.B 10.3,
+and
+.B 10.4
+with the default being
+.B 10.4
+for the i386 architecture and
+.B 10.1
+for all other architectures.
+.PP
+The following environment variables are used by Apple's Build and Integration
+team:
+.TP
+.B LD_TRACE_ARCHIVES
+When this is set it causes a message of the form ``[Logging for XBS]
+Used static archive:
+.I filename''
+for each static archive that has members linked into the output.
+.TP
+.B LD_TRACE_DYLIBS
+When this is set it causes a message of the form ``[Logging for XBS]
+Used dynamic library:
+.I filename''
+for each dynamic library linked into the output.
+.TP
+.B RC_TRACE_PREBINDING_DISABLED
+When this is set it causes a message of the form ``[Logging for XBS
+prebinding disabled for
+.I filename
+because
+.I reason''.
+Where
+.I filename
+is the value of the
+.B \-final_output
+argument if specified or the value of the
+.B \-o
+argument.
+.TP
+.BI \-final_output " filename"
+The argument
+.I filename
+is used in the above message when RC_TRACE_PREBINDING_DISABLED is set.
+.TP
+.B LD_TRACE_FILE
+When this is set, messages displayed due to the
+.B LD_TRACE_ARCHIVES
+,
+.B LD_TRACE_DYLIBS
+, and
+.B LD_TRACE_PREBINDING_DISABLED
+environment variables are printed to the file whose path is specified
+by this variable instead of stdout.
+.TP
+.B LD_SPLITSEGS_NEW_LIBRARIES
+When set and
+.B MACOSX_DEPLOYMENT_TARGET
+is set to 10.4 or greater and the output is a dynamic library, and if the
+install name of the library is not listed the segment address table, and if the
+environment variable
+.B LD_UNPREBOUND_LIBRARIES
+is set with a file name with a list of library install names and the install
+name is not listed, then this is built as a split shared library.
+
+.PP
+Options available in early versions of the Mach-O link editor
+may no longer be supported.
+
+.SH FILES
+.ta \w'/Network/Library/Frameworks/*.framework/*\ \ 'u
+/lib/lib*.{a,dylib}    libraries
+.br
+/usr/lib/lib*.{a,dylib}
+.br
+/usr/local/lib/lib*.{a,dylib}
+.br
+/Library/Frameworks/*.framework/*      framework libraries
+.br
+/Network/Library/Frameworks/*.framework/*      framework libraries
+.br
+/System/Library/Frameworks/*.framework/*       framework libraries
+.br
+a.out  output file
+.SH "SEE ALSO"
+as(1), ar(1), cc(1), libtool(1), ranlib(1), nm(1), otool(1) lipo(1),
+arch(3), dyld(3), Mach-O(5), strip(1), redo_prebinding(1)
index 3475042ebe539c968378c74763866ce23f44a82e..a468b0d99935e8cf5281a71737f236bdb23313e0 100644 (file)
                F9023C4E06D5A272001BBF46 /* ld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9023C3F06D5A254001BBF46 /* ld.cpp */; };
                F933E3D9092E855B0083EAC8 /* ObjectDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F971EED706D5AD240041D381 /* ObjectDump.cpp */; };
                F97288E707D277570031794D /* SectCreate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F97288E607D277570031794D /* SectCreate.cpp */; };
                F9023C4E06D5A272001BBF46 /* ld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9023C3F06D5A254001BBF46 /* ld.cpp */; };
                F933E3D9092E855B0083EAC8 /* ObjectDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F971EED706D5AD240041D381 /* ObjectDump.cpp */; };
                F97288E707D277570031794D /* SectCreate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F97288E607D277570031794D /* SectCreate.cpp */; };
-               F97F5029070D0BB200B9FCD7 /* ld64.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = F97F5028070D0BB200B9FCD7 /* ld64.1 */; };
                F9B1A2640A3A563E00DA8FAB /* rebase.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = F9B1A2580A3A448800DA8FAB /* rebase.1 */; };
                F9C0D4BD06DD28D2001C7193 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9C0D48A06DD1E1B001C7193 /* Options.cpp */; };
                F9EA72D5097454FF008B4F1D /* machochecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9EA72D4097454FF008B4F1D /* machochecker.cpp */; };
                F9EA7584097882F3008B4F1D /* debugline.c in Sources */ = {isa = PBXBuildFile; fileRef = F9EA7582097882F3008B4F1D /* debugline.c */; };
                F9EA75BC09788857008B4F1D /* debugline.c in Sources */ = {isa = PBXBuildFile; fileRef = F9EA7582097882F3008B4F1D /* debugline.c */; };
                F9EC78060A2F8674002A3E39 /* rebase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9EC78050A2F8674002A3E39 /* rebase.cpp */; };
                F9B1A2640A3A563E00DA8FAB /* rebase.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = F9B1A2580A3A448800DA8FAB /* rebase.1 */; };
                F9C0D4BD06DD28D2001C7193 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9C0D48A06DD1E1B001C7193 /* Options.cpp */; };
                F9EA72D5097454FF008B4F1D /* machochecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9EA72D4097454FF008B4F1D /* machochecker.cpp */; };
                F9EA7584097882F3008B4F1D /* debugline.c in Sources */ = {isa = PBXBuildFile; fileRef = F9EA7582097882F3008B4F1D /* debugline.c */; };
                F9EA75BC09788857008B4F1D /* debugline.c in Sources */ = {isa = PBXBuildFile; fileRef = F9EA7582097882F3008B4F1D /* debugline.c */; };
                F9EC78060A2F8674002A3E39 /* rebase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9EC78050A2F8674002A3E39 /* rebase.cpp */; };
+               F9FCC3F20A54A75600CEB866 /* ld64.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = F9FCC3F10A54A75600CEB866 /* ld64.1 */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXBuildRule section */
 /* End PBXBuildFile section */
 
 /* Begin PBXBuildRule section */
@@ -73,7 +73,7 @@
                        isa = PBXContainerItemProxy;
                        containerPortal = F9023C3006D5A227001BBF46 /* Project object */;
                        proxyType = 1;
                        isa = PBXContainerItemProxy;
                        containerPortal = F9023C3006D5A227001BBF46 /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = F9EC77ED0A2F85F6002A3E39 /* rebase */;
+                       remoteGlobalIDString = F9EC77ED0A2F85F6002A3E39;
                        remoteInfo = rebase;
                };
                F96D5369094A275D008E9EE8 /* PBXContainerItemProxy */ = {
                        remoteInfo = rebase;
                };
                F96D5369094A275D008E9EE8 /* PBXContainerItemProxy */ = {
                        dstPath = /usr/share/man/man1;
                        dstSubfolderSpec = 0;
                        files = (
                        dstPath = /usr/share/man/man1;
                        dstSubfolderSpec = 0;
                        files = (
-                               F97F5029070D0BB200B9FCD7 /* ld64.1 in CopyFiles */,
+                               F9FCC3F20A54A75600CEB866 /* ld64.1 in CopyFiles */,
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
                F971EED706D5AD240041D381 /* ObjectDump.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectDump.cpp; path = src/ObjectDump.cpp; sourceTree = "<group>"; };
                F97288E607D277570031794D /* SectCreate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SectCreate.cpp; path = src/SectCreate.cpp; sourceTree = "<group>"; };
                F972890007D27FD00031794D /* SectCreate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SectCreate.h; path = src/SectCreate.h; sourceTree = "<group>"; };
                F971EED706D5AD240041D381 /* ObjectDump.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectDump.cpp; path = src/ObjectDump.cpp; sourceTree = "<group>"; };
                F97288E607D277570031794D /* SectCreate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SectCreate.cpp; path = src/SectCreate.cpp; sourceTree = "<group>"; };
                F972890007D27FD00031794D /* SectCreate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SectCreate.h; path = src/SectCreate.h; sourceTree = "<group>"; };
-               F97F5028070D0BB200B9FCD7 /* ld64.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = ld64.1; path = doc/man/man1/ld64.1; sourceTree = "<group>"; };
+               F97F5028070D0BB200B9FCD7 /* ld.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = ld.1; path = doc/man/man1/ld.1; sourceTree = "<group>"; };
                F9B1A2580A3A448800DA8FAB /* rebase.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = rebase.1; path = doc/man/man1/rebase.1; sourceTree = "<group>"; };
                F9C0D48A06DD1E1B001C7193 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Options.cpp; path = src/Options.cpp; sourceTree = "<group>"; };
                F9C0D48B06DD1E1B001C7193 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Options.h; path = src/Options.h; sourceTree = "<group>"; };
                F9B1A2580A3A448800DA8FAB /* rebase.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = rebase.1; path = doc/man/man1/rebase.1; sourceTree = "<group>"; };
                F9C0D48A06DD1E1B001C7193 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Options.cpp; path = src/Options.cpp; sourceTree = "<group>"; };
                F9C0D48B06DD1E1B001C7193 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Options.h; path = src/Options.h; sourceTree = "<group>"; };
                F9EA7583097882F3008B4F1D /* debugline.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = debugline.h; path = src/debugline.h; sourceTree = "<group>"; };
                F9EC77EE0A2F85F6002A3E39 /* rebase */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rebase; sourceTree = BUILT_PRODUCTS_DIR; };
                F9EC78050A2F8674002A3E39 /* rebase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = rebase.cpp; path = src/rebase.cpp; sourceTree = "<group>"; };
                F9EA7583097882F3008B4F1D /* debugline.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = debugline.h; path = src/debugline.h; sourceTree = "<group>"; };
                F9EC77EE0A2F85F6002A3E39 /* rebase */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rebase; sourceTree = BUILT_PRODUCTS_DIR; };
                F9EC78050A2F8674002A3E39 /* rebase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = rebase.cpp; path = src/rebase.cpp; sourceTree = "<group>"; };
+               F9FCC3F10A54A75600CEB866 /* ld64.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = ld64.1; path = doc/man/man1/ld64.1; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                F9EA72D4097454FF008B4F1D /* machochecker.cpp */,
                                F971EED706D5AD240041D381 /* ObjectDump.cpp */,
                                F9EC78050A2F8674002A3E39 /* rebase.cpp */,
                                F9EA72D4097454FF008B4F1D /* machochecker.cpp */,
                                F971EED706D5AD240041D381 /* ObjectDump.cpp */,
                                F9EC78050A2F8674002A3E39 /* rebase.cpp */,
-                               F97F5028070D0BB200B9FCD7 /* ld64.1 */,
+                               F97F5028070D0BB200B9FCD7 /* ld.1 */,
+                               F9FCC3F10A54A75600CEB866 /* ld64.1 */,
                                F9B1A2580A3A448800DA8FAB /* rebase.1 */,
                                F9023C3A06D5A23E001BBF46 /* Products */,
                        );
                                F9B1A2580A3A448800DA8FAB /* rebase.1 */,
                                F9023C3A06D5A23E001BBF46 /* Products */,
                        );
                F9023C3006D5A227001BBF46 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = F933D92309291AC90083EAC8 /* Build configuration list for PBXProject "ld64" */;
                F9023C3006D5A227001BBF46 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = F933D92309291AC90083EAC8 /* Build configuration list for PBXProject "ld64" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 0;
                        mainGroup = F9023C2C06D5A227001BBF46;
                        productRefGroup = F9023C3A06D5A23E001BBF46 /* Products */;
                        projectDirPath = "";
                        hasScannedForEncodings = 0;
                        mainGroup = F9023C2C06D5A227001BBF46;
                        productRefGroup = F9023C3A06D5A23E001BBF46 /* Products */;
                        projectDirPath = "";
+                       projectRoot = "";
+                       shouldCheckCompatibility = 1;
                        targets = (
                                F9B1A2670A3A567B00DA8FAB /* all */,
                                F9023C3806D5A23E001BBF46 /* ld */,
                        targets = (
                                F9B1A2670A3A567B00DA8FAB /* all */,
                                F9023C3806D5A23E001BBF46 /* ld */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/csh;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/csh;
-                       shellScript = "# Let tests set MACOSX_DEPLOYMENT_TARGET as they need\nunsetenv MACOSX_DEPLOYMENT_TARGET\n\n# make an symlink to ld64 called ld, so that gcc will use this linker for all linking\nrm -rf $BUILT_PRODUCTS_DIR/ld\nln -s $BUILT_PRODUCTS_DIR/ld64 $BUILT_PRODUCTS_DIR/ld\n\n# run full test suite\n$SRCROOT/unit-tests/run-all-unit-tests\n\nexit 0";
+                       shellScript = "# Let tests set MACOSX_DEPLOYMENT_TARGET as they need\nunsetenv MACOSX_DEPLOYMENT_TARGET\n\n# always use new linker\nsetenv LD_NO_CLASSIC_LINKER\n\n# run full test suite\n$SRCROOT/unit-tests/run-all-unit-tests\n\nexit 0";
                };
 /* End PBXShellScriptBuildPhase section */
 
                };
 /* End PBXShellScriptBuildPhase section */
 
                                INSTALL_PATH = /usr/bin;
                                OTHER_CPLUSPLUSFLAGS = "$(OTHER_CPLUSPLUSFLAGS)";
                                OTHER_LDFLAGS = "";
                                INSTALL_PATH = /usr/bin;
                                OTHER_CPLUSPLUSFLAGS = "$(OTHER_CPLUSPLUSFLAGS)";
                                OTHER_LDFLAGS = "";
+                               PREBINDING = NO;
                                PRODUCT_NAME = ld64;
                                SECTORDER_FLAGS = "";
                                VERSIONING_SYSTEM = "apple-generic";
                                PRODUCT_NAME = ld64;
                                SECTORDER_FLAGS = "";
                                VERSIONING_SYSTEM = "apple-generic";
                                INSTALL_PATH = /usr/bin;
                                OTHER_CPLUSPLUSFLAGS = "$(OTHER_CPLUSPLUSFLAGS)";
                                OTHER_LDFLAGS = "";
                                INSTALL_PATH = /usr/bin;
                                OTHER_CPLUSPLUSFLAGS = "$(OTHER_CPLUSPLUSFLAGS)";
                                OTHER_LDFLAGS = "";
+                               PREBINDING = NO;
                                PRODUCT_NAME = ld64;
                                SECTORDER_FLAGS = "";
                                VALID_ARCHS = "i386 ppc";
                                PRODUCT_NAME = ld64;
                                SECTORDER_FLAGS = "";
                                VALID_ARCHS = "i386 ppc";
index 4d1b2f051b357f47fb472f2f9be7131b1b7a9e3d..055dd4fd91fc73487596a454262695520c492fd0 100644 (file)
@@ -95,7 +95,7 @@ public:
        virtual bool                                                            requiresFollowOnAtom() const{ return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
        virtual bool                                                            requiresFollowOnAtom() const{ return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
-       virtual uint8_t                                                         getAlignment() const            { return 0; }
+       virtual ObjectFile::Alignment                           getAlignment() const            { return ObjectFile::Alignment(0); }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const  {}
 
        virtual void                                                            setScope(Scope)                         { }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const  {}
 
        virtual void                                                            setScope(Scope)                         { }
index ea6f6de2c9597558a741947c8eee06385d75516d..310b5617c2896fb37f5943ad3c83909daa0fed31 100644 (file)
@@ -66,6 +66,16 @@ namespace relocatable {
 
 
 
 
 
 
+class ReferenceSorter
+{
+public:
+       bool operator()(const ObjectFile::Reference* left, const ObjectFile::Reference* right)
+       {
+               return ( left->getFixUpOffset() < right->getFixUpOffset() );
+       }
+};
+
+
 // forward reference
 template <typename A> class Reader;
 template <typename A> class SymbolAtomSorter;
 // forward reference
 template <typename A> class Reader;
 template <typename A> class SymbolAtomSorter;
@@ -219,8 +229,8 @@ public:
 
        virtual void                                                            setSize(uint64_t size)  = 0;
        virtual void                                                            addReference(ObjectFile::Reference* ref) = 0;
 
        virtual void                                                            setSize(uint64_t size)  = 0;
        virtual void                                                            addReference(ObjectFile::Reference* ref) = 0;
+       virtual void                                                            sortReferences() = 0;
        virtual void                                                            addLineInfo(const ObjectFile::LineInfo& info) = 0;
        virtual void                                                            addLineInfo(const ObjectFile::LineInfo& info) = 0;
-       virtual void                                                            alignAtLeast(uint8_t align)     = 0;
 
        uint32_t                                                                        fStabsStartIndex;
        uint32_t                                                                        fStabsCount;
 
        uint32_t                                                                        fStabsStartIndex;
        uint32_t                                                                        fStabsCount;
@@ -255,13 +265,13 @@ public:
        virtual bool                                                            requiresFollowOnAtom() const;
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const;
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return (std::vector<ObjectFile::LineInfo>*)&fLineInfo; }
        virtual bool                                                            requiresFollowOnAtom() const;
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const;
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return (std::vector<ObjectFile::LineInfo>*)&fLineInfo; }
-       virtual uint8_t                                                         getAlignment() const                    { return fAlignment; }
+       virtual ObjectFile::Alignment                           getAlignment() const                    { return fAlignment; }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
-       virtual void                                                            setSize(uint64_t size);
-       virtual void                                                            addReference(ObjectFile::Reference* ref) { fReferences.insert(fReferences.begin(), (Reference<A>*)ref); }
+       virtual void                                                            setSize(uint64_t size)                  { fSize = size; }
+       virtual void                                                            addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
+       virtual void                                                            sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
        virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { fLineInfo.push_back(info); }
        virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { fLineInfo.push_back(info); }
-       virtual void                                                            alignAtLeast(uint8_t align)             { fAlignment = std::max(align, fAlignment); }
 
 protected:
        typedef typename A::P                                           P;
 
 protected:
        typedef typename A::P                                           P;
@@ -287,7 +297,7 @@ protected:
        std::vector<ObjectFile::LineInfo>                       fLineInfo;
        ObjectFile::Atom::Scope                                         fScope;
        SymbolTableInclusion                                            fSymbolTableInclusion;
        std::vector<ObjectFile::LineInfo>                       fLineInfo;
        ObjectFile::Atom::Scope                                         fScope;
        SymbolTableInclusion                                            fSymbolTableInclusion;
-       uint8_t                                                                         fAlignment;
+       ObjectFile::Alignment                                           fAlignment;
 };
 
 
 };
 
 
@@ -381,31 +391,8 @@ SymbolAtom<A>::SymbolAtom(Reader<A>& owner, const macho_nlist<P>* symbol, const
        else {
                fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
        }
        else {
                fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
        }
-}
-
-
-template <typename A>
-void SymbolAtom<A>::setSize(uint64_t size)
-{
-       fSize = size;
-       
-       if ( fSection->flags() & S_ATTR_SOME_INSTRUCTIONS ) {
-               // For code, the aligment is based just on the section alignment and code address
-               if ( fAddress == 0 )
-                       fAlignment = fSection->align();
-               else
-                       fAlignment = std::min((uint8_t)__builtin_ctz(fAddress), (uint8_t)fSection->align());
-       }
-       else {
-               // For data, compute the alignment base on the address aligned at in object file and the size
-               uint8_t sizeAlign = __builtin_ctz(fSize);
-               uint8_t sizeAndSectAlign = std::min((uint8_t)fSection->align(), sizeAlign);
-               // If address is zero, can't figure out better alignment than section alignment and size
-               if ( fAddress == 0 )
-                       fAlignment = sizeAndSectAlign;
-               else
-                       fAlignment = std::min((uint8_t)__builtin_ctz(fAddress), sizeAndSectAlign);
-       }
+       // compute alignment
+       fAlignment = ObjectFile::Alignment(fSection->align(), fAddress % (1 << fSection->align()));
 }
 
 
 }
 
 
@@ -461,7 +448,6 @@ void SymbolAtom<A>::copyRawContent(uint8_t buffer[]) const
        }
 }
 
        }
 }
 
-
 template <typename A>
 class SymbolAtomSorter
 {
 template <typename A>
 class SymbolAtomSorter
 {
@@ -520,13 +506,13 @@ public:
        virtual bool                                                            requiresFollowOnAtom() const    { return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const                 { return *(ObjectFile::Atom*)NULL; }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
        virtual bool                                                            requiresFollowOnAtom() const    { return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const                 { return *(ObjectFile::Atom*)NULL; }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
-       virtual uint8_t                                                         getAlignment() const;
+       virtual ObjectFile::Alignment                           getAlignment() const;
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
        virtual void                                                            setSize(uint64_t size)                  { }
        virtual void                                                            addReference(ObjectFile::Reference* ref) { throw "ld64: can't add references"; }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
        virtual void                                                            setSize(uint64_t size)                  { }
        virtual void                                                            addReference(ObjectFile::Reference* ref) { throw "ld64: can't add references"; }
+       virtual void                                                            sortReferences() { }
        virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { throw "ld64: can't add line info to tentative definition"; }
        virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { throw "ld64: can't add line info to tentative definition"; }
-       virtual void                                                            alignAtLeast(uint8_t align)             { }
 
 protected:
        typedef typename A::P                                   P;
 
 protected:
        typedef typename A::P                                   P;
@@ -569,7 +555,7 @@ TentativeAtom<A>::TentativeAtom(Reader<A>& owner, const macho_nlist<P>* symbol)
 
 
 template <typename A>
 
 
 template <typename A>
-uint8_t        TentativeAtom<A>::getAlignment() const
+ObjectFile::Alignment TentativeAtom<A>::getAlignment() const
 {
        // common symbols align to their size
        // that is, a 4-byte common aligns to 4-bytes
 {
        // common symbols align to their size
        // that is, a 4-byte common aligns to 4-bytes
@@ -577,9 +563,9 @@ uint8_t     TentativeAtom<A>::getAlignment() const
        uint8_t alignment = (uint8_t)ceil(log2(this->getSize()));
        // limit alignment of extremely large commons to 2^15 bytes (8-page)
        if ( alignment < 15 )
        uint8_t alignment = (uint8_t)ceil(log2(this->getSize()));
        // limit alignment of extremely large commons to 2^15 bytes (8-page)
        if ( alignment < 15 )
-               return alignment;
+               return ObjectFile::Alignment(alignment);
        else
        else
-               return 15;
+               return ObjectFile::Alignment(15);
 }
 
 template <typename A>
 }
 
 template <typename A>
@@ -615,13 +601,13 @@ public:
        virtual bool                                                            requiresFollowOnAtom() const;
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const;
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
        virtual bool                                                            requiresFollowOnAtom() const;
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const;
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
-       virtual uint8_t                                                         getAlignment() const;
+       virtual ObjectFile::Alignment                           getAlignment() const;
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)      { fScope = newScope; }
        virtual void                                                            setSize(uint64_t size)                  { fSize = size; }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)      { fScope = newScope; }
        virtual void                                                            setSize(uint64_t size)                  { fSize = size; }
-       virtual void                                                            addReference(ObjectFile::Reference* ref) { fReferences.insert(fReferences.begin(), (Reference<A>*)ref); }
+       virtual void                                                            addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
+       virtual void                                                            sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
        virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info) { fprintf(stderr, "ld64: can't add line info to anonymous symbol %s from %s\n", this->getDisplayName(), this->getFile()->getPath()); }
        virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info) { fprintf(stderr, "ld64: can't add line info to anonymous symbol %s from %s\n", this->getDisplayName(), this->getFile()->getPath()); }
-       virtual void                                                            alignAtLeast(uint8_t align)             { }
        BaseAtom*                                                                       redirectTo()                                    { return fRedirect; }
        bool                                                                            isWeakImportStub()                              { return fWeakImportStub; }
 
        BaseAtom*                                                                       redirectTo()                                    { return fRedirect; }
        bool                                                                            isWeakImportStub()                              { return fWeakImportStub; }
 
@@ -648,7 +634,6 @@ protected:
        BaseAtom*                                                                       fRedirect;
        bool                                                                            fDontDeadStrip;
        bool                                                                            fWeakImportStub;
        BaseAtom*                                                                       fRedirect;
        bool                                                                            fDontDeadStrip;
        bool                                                                            fWeakImportStub;
-       bool                                                                            fReallyNonLazyPointer;  // HACK until compiler stops emitting anonymous non-lazy pointers
        ObjectFile::Atom::SymbolTableInclusion          fSymbolTableInclusion;
        ObjectFile::Atom::Scope                                         fScope;
 };
        ObjectFile::Atom::SymbolTableInclusion          fSymbolTableInclusion;
        ObjectFile::Atom::Scope                                         fScope;
 };
@@ -656,7 +641,7 @@ protected:
 template <typename A>
 AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* section, uint32_t addr, uint32_t size)
  : fOwner(owner), fSynthesizedName(NULL), fSection(section), fAddress(addr), fSize(size), fSegment(NULL), fDontDeadStrip(true),
 template <typename A>
 AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* section, uint32_t addr, uint32_t size)
  : fOwner(owner), fSynthesizedName(NULL), fSection(section), fAddress(addr), fSize(size), fSegment(NULL), fDontDeadStrip(true),
-       fWeakImportStub(false), fReallyNonLazyPointer(false), fSymbolTableInclusion(ObjectFile::Atom::kSymbolTableNotIn),
+       fWeakImportStub(false), fSymbolTableInclusion(ObjectFile::Atom::kSymbolTableNotIn),
        fScope(ObjectFile::Atom::scopeTranslationUnit)
 {
        fSegment = new Segment<A>(fSection);
        fScope(ObjectFile::Atom::scopeTranslationUnit)
 {
        fSegment = new Segment<A>(fSection);
@@ -835,17 +820,12 @@ const char* AnonymousAtom<A>::getDisplayName() const
 template <typename A>
 ObjectFile::Atom::Scope AnonymousAtom<A>::getScope() const
 {
 template <typename A>
 ObjectFile::Atom::Scope AnonymousAtom<A>::getScope() const
 {
-       if ( fReallyNonLazyPointer )
-               return ObjectFile::Atom::scopeTranslationUnit;
-       else    
-               return fScope;
+       return fScope;
 }
 
 template <typename A>
 ObjectFile::Atom::DefinitionKind AnonymousAtom<A>::getDefinitionKind() const
 {
 }
 
 template <typename A>
 ObjectFile::Atom::DefinitionKind AnonymousAtom<A>::getDefinitionKind() const
 {
-       if ( fReallyNonLazyPointer )
-               return  ObjectFile::Atom::kRegularDefinition;
        // in order for literals to be coalesced they must be weak
        switch ( fSection->flags() & SECTION_TYPE ) {
                case S_CSTRING_LITERALS:
        // in order for literals to be coalesced they must be weak
        switch ( fSection->flags() & SECTION_TYPE ) {
                case S_CSTRING_LITERALS:
@@ -880,21 +860,19 @@ const char*       AnonymousAtom<A>::getSectionName() const
 }
 
 template <typename A>
 }
 
 template <typename A>
-uint8_t AnonymousAtom<A>::getAlignment() const
+ObjectFile::Alignment AnonymousAtom<A>::getAlignment() const
 {
 {
-       if ( fReallyNonLazyPointer )
-               return (uint8_t)log2(sizeof(pint_t));
        switch ( fSection->flags() & SECTION_TYPE ) {
                case S_4BYTE_LITERALS:
        switch ( fSection->flags() & SECTION_TYPE ) {
                case S_4BYTE_LITERALS:
-                       return 2;
+                       return ObjectFile::Alignment(2);
                case S_8BYTE_LITERALS:
                case S_8BYTE_LITERALS:
-                       return 3;
+                       return ObjectFile::Alignment(3);
                case S_16BYTE_LITERALS:
                case S_16BYTE_LITERALS:
-                       return 4;
+                       return ObjectFile::Alignment(4);
                case S_NON_LAZY_SYMBOL_POINTERS:
                case S_NON_LAZY_SYMBOL_POINTERS:
-                       return (uint8_t)log2(sizeof(pint_t));
+                       return ObjectFile::Alignment((uint8_t)log2(sizeof(pint_t)));
                default:
                default:
-                       return fSection->align();
+                       return ObjectFile::Alignment(fSection->align(), fAddress % (1 << fSection->align()));
        }
 }
 
        }
 }
 
@@ -985,7 +963,6 @@ private:
        Reference<A>*                                                           makeReferenceToEH(const char* ehName, pint_t ehAtomAddress, const macho_section<P>* ehSect);
        Reference<A>*                                                           makeReferenceToSymbol(Kinds kind, uint32_t atAddr, const macho_nlist<P>* toSymbol, uint32_t toOffset);
        void                                                                            validSectionType(uint8_t type);
        Reference<A>*                                                           makeReferenceToEH(const char* ehName, pint_t ehAtomAddress, const macho_section<P>* ehSect);
        Reference<A>*                                                           makeReferenceToSymbol(Kinds kind, uint32_t atAddr, const macho_nlist<P>* toSymbol, uint32_t toOffset);
        void                                                                            validSectionType(uint8_t type);
-       void                                                                            handleAnonymousNonLazyPointers(const macho_section<P>* sect);
 
        BaseAtom*                                                                       findAtomByName(const char*);
 
 
        BaseAtom*                                                                       findAtomByName(const char*);
 
@@ -1013,47 +990,6 @@ private:
        bool                                                                            fAppleObjc;
 };
 
        bool                                                                            fAppleObjc;
 };
 
-// usually do nothing
-template <typename A> void Reader<A>::handleAnonymousNonLazyPointers(const macho_section<P>* sect) {  }
-
-// HACK for ppc64, need to split of anonymous non-lazy-pointers because they must be 8-byte aligned to work with ld instruction
-template <> void 
-Reader<ppc64>::handleAnonymousNonLazyPointers(const macho_section<P>* dataSect) { 
-       if ( (dataSect->size() >= sizeof(pint_t)) 
-               && (dataSect->align() >= log2(sizeof(pint_t)))
-               && (strcmp(dataSect->sectname(), "__data") == 0)
-               && (strcmp(dataSect->segname(), "__DATA") == 0) ) {
-                       std::set<uint32_t> lo14targets;
-                       const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)fSegment + sizeof(macho_segment_command<P>));
-                       const macho_section<P>* const sectionsEnd = &sectionsStart[fSegment->nsects()];
-                       for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
-                               if ( strncmp(sect->sectname(), "__text", 6) == 0 ) {
-                                       const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fHeader) + sect->reloff());
-                                       const macho_relocation_info<P>* relocsEnd = &relocs[sect->nreloc()];
-                                       for (const macho_relocation_info<P>* r = relocs; r < relocsEnd; ++r) {  
-                                               if ( (r->r_address() & R_SCATTERED) != 0 ) {
-                                                       const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)r;
-                                                       if ( sreloc->r_type() == PPC_RELOC_LO14_SECTDIFF ) {
-                                                               lo14targets.insert(sreloc->r_value());
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-                       // walk backwards so that newly created anonymous atoms do not mask misalignmented
-                       for (std::set<uint32_t>::reverse_iterator it=lo14targets.rbegin(); it != lo14targets.rend(); it++) {
-                               uint32_t targetOfLO14 = *it;
-                               AtomAndOffset found = this->findAtomAndOffset(targetOfLO14);
-                               if ( (found.offset & 0x7) != 0 ) {
-                                       AnonymousAtom<ppc64>* newAtom = new AnonymousAtom<ppc64>(*this, dataSect, targetOfLO14, sizeof(pint_t));
-                                       newAtom->fReallyNonLazyPointer = true;
-                                       fAtoms.push_back(newAtom);
-                                       fAddrToAtom[targetOfLO14] = newAtom;
-                               }
-                       }
-       }
-}
-
 template <typename A>
 Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options)
        : fPath(strdup(path)), fModTime(modTime), fOptions(options), fHeader((const macho_header<P>*)fileContent),
 template <typename A>
 Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options)
        : fPath(strdup(path)), fModTime(modTime), fOptions(options), fHeader((const macho_header<P>*)fileContent),
@@ -1282,8 +1218,6 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                        case S_REGULAR:
                                        case S_ZEROFILL:
                                        case S_COALESCED:
                                        case S_REGULAR:
                                        case S_ZEROFILL:
                                        case S_COALESCED:
-                                               // HACK until compiler stops generated anonymous non-lazy pointers rdar://problem/4513414
-                                               handleAnonymousNonLazyPointers(sect); 
                                                // if there is not an atom already at the start of this section, add an anonymous one
                                                uint32_t previousAtomAddr = 0;
                                                BaseAtom* previousAtom = NULL;
                                                // if there is not an atom already at the start of this section, add an anonymous one
                                                uint32_t previousAtomAddr = 0;
                                                BaseAtom* previousAtom = NULL;
@@ -1369,11 +1303,13 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                uint32_t classSize = ((12 * sizeof(pint_t)) + align-1) & (-align);
                                for (uint32_t offset = 0; offset < sect->size(); offset += classSize) {
                                        // add by-name reference to super class
                                uint32_t classSize = ((12 * sizeof(pint_t)) + align-1) & (-align);
                                for (uint32_t offset = 0; offset < sect->size(); offset += classSize) {
                                        // add by-name reference to super class
-                                       uint32_t superClassNameAddr =  P::getP(*(pint_t*)(((uint8_t*)fHeader) + sect->offset() + offset + sizeof(pint_t)));
-                                       const char* superStr = (char*)(fHeader) + sect->offset() + superClassNameAddr - sect->addr();
-                                       const char* superClassName;
-                                       asprintf((char**)&superClassName, ".objc_class_name_%s", superStr);
-                                       makeByNameReference(A::kNoFixUp, sect->addr()+offset+sizeof(pint_t), superClassName, 0);
+                                       pint_t superClassNameAddr =  P::getP(*(pint_t*)(((uint8_t*)fHeader) + sect->offset() + offset + sizeof(pint_t)));
+                                       if ( superClassNameAddr != 0 ) {
+                                               const char* superStr = (char*)(fHeader) + sect->offset() + superClassNameAddr - sect->addr();
+                                               const char* superClassName;
+                                               asprintf((char**)&superClassName, ".objc_class_name_%s", superStr);
+                                               makeByNameReference(A::kNoFixUp, sect->addr()+offset+sizeof(pint_t), superClassName, 0);
+                                       }
                                }
                        }
                        else if ( (strcmp(sect->sectname(), "__cls_refs") == 0) && (strcmp(sect->segname(), "__OBJC") == 0) ) {
                                }
                        }
                        else if ( (strcmp(sect->sectname(), "__cls_refs") == 0) && (strcmp(sect->segname(), "__OBJC") == 0) ) {
@@ -1449,6 +1385,9 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                        uint32_t curAtomAddress = 0;
                                        uint32_t curAtomSize = 0;
                                        while ( line_next (lines, &result, line_stop_pc) ) {
                                        uint32_t curAtomAddress = 0;
                                        uint32_t curAtomSize = 0;
                                        while ( line_next (lines, &result, line_stop_pc) ) {
+                                               // work around weird debug line table compiler generates if no functions in __text section
+                                               if ( (curAtom == NULL) && (result.pc == 0) && result.end_of_sequence && (result.file == 1))
+                                                       continue;
                                                // for performance, see if in next pc is in current atom
                                                if ( (curAtom != NULL) && (curAtomAddress <= result.pc) && (result.pc < (curAtomAddress+curAtomSize)) ) {
                                                        curAtomOffset = result.pc - curAtomAddress;
                                                // for performance, see if in next pc is in current atom
                                                if ( (curAtom != NULL) && (curAtomAddress <= result.pc) && (result.pc < (curAtomAddress+curAtomSize)) ) {
                                                        curAtomOffset = result.pc - curAtomAddress;
@@ -1561,6 +1500,14 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                                                                stab.string = symString;
                                                                        }
                                                                }
                                                                                stab.string = symString;
                                                                        }
                                                                }
+                                                               else {
+                                                                       // might be a debug-note without trailing :G()
+                                                                       currentAtom = findAtomByName(symString);
+                                                                       if ( currentAtom != NULL ) {
+                                                                               stab.atom = currentAtom;
+                                                                               stab.string = symString;
+                                                                       }
+                                                               }
                                                                if ( stab.atom == NULL ) {
                                                                        fprintf(stderr, "can't find atom for N_GSYM stabs %s in %s\n", symString, path);
                                                                        useStab = false;
                                                                if ( stab.atom == NULL ) {
                                                                        fprintf(stderr, "can't find atom for N_GSYM stabs %s in %s\n", symString, path);
                                                                        useStab = false;
@@ -1673,7 +1620,12 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                }
        }
 
                }
        }
 
-
+       // sort references in each atom
+       for (std::vector<ObjectFile::Atom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
+               BaseAtom* atom = (BaseAtom*)(*it);
+               atom->sortReferences();
+       }
+       
 #if 0
        // special case precompiled header .o file (which has no content) to have one empty atom
        if ( fAtoms.size() == 0 ) {
 #if 0
        // special case precompiled header .o file (which has no content) to have one empty atom
        if ( fAtoms.size() == 0 ) {
@@ -2312,10 +2264,7 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                        }
                                        else {
                                                dstAddr = (nextReloc->r_address() << 16) | ((uint32_t)lowBits & 0x0000FFFF);
                                        }
                                        else {
                                                dstAddr = (nextReloc->r_address() << 16) | ((uint32_t)lowBits & 0x0000FFFF);
-                                               Reference<A>* ref = makeReference(A::kAbsLow14, srcAddr, dstAddr);
-                                               BaseAtom* target = ((BaseAtom*)&(ref->getTarget()));
-                                               if ( target != NULL )
-                                                       target->alignAtLeast(3);
+                                               makeReference(A::kAbsLow14, srcAddr, dstAddr);
                                        }
                                }
                                break;
                                        }
                                }
                                break;
@@ -2461,10 +2410,7 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                        instruction = BigEndian::get32(*fixUpPtr);
                                        lowBits = (instruction & 0xFFFC);
                                        displacement = (nextRelocAddress << 16) | ((uint32_t)lowBits & 0x0000FFFF);
                                        instruction = BigEndian::get32(*fixUpPtr);
                                        lowBits = (instruction & 0xFFFC);
                                        displacement = (nextRelocAddress << 16) | ((uint32_t)lowBits & 0x0000FFFF);
-                                       Reference<A>* ref = makeReferenceWithToBase(A::kPICBaseLow14, srcAddr, nextRelocValue, nextRelocValue + displacement, dstAddr);
-                                       BaseAtom* target = ((BaseAtom*)&(ref->getTarget()));
-                                       if ( target != NULL ) // can be NULL if target is turned into by-name reference
-                                               target->alignAtLeast(3);
+                                       makeReferenceWithToBase(A::kPICBaseLow14, srcAddr, nextRelocValue, nextRelocValue + displacement, dstAddr);
                                }
                                break;
                        case PPC_RELOC_HA16_SECTDIFF:
                                }
                                break;
                        case PPC_RELOC_HA16_SECTDIFF:
@@ -2678,7 +2624,7 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
        uint64_t dstAddr = 0;
        uint64_t addend;
        uint32_t* fixUpPtr;
        uint64_t dstAddr = 0;
        uint64_t addend;
        uint32_t* fixUpPtr;
-       x86_64::ReferenceKinds kind;
+       x86_64::ReferenceKinds kind = x86_64::kNoFixUp;
        bool result = false;
        const macho_nlist<P>* targetSymbol = NULL;
        const char* targetName = NULL;
        bool result = false;
        const macho_nlist<P>* targetSymbol = NULL;
        const char* targetName = NULL;
@@ -2706,61 +2652,66 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
                case X86_64_RELOC_SIGNED_2:
                case X86_64_RELOC_SIGNED_4:
                        if ( ! reloc->r_pcrel() )
                case X86_64_RELOC_SIGNED_2:
                case X86_64_RELOC_SIGNED_4:
                        if ( ! reloc->r_pcrel() )
-                               throw "not pcrel and X86_64_RELOC_SIGNED not supported";
+                               throw "not pcrel and X86_64_RELOC_SIGNED* not supported";
                        if ( reloc->r_length() != 2 ) 
                        if ( reloc->r_length() != 2 ) 
-                               throw "length != 2 and X86_64_RELOC_SIGNED not supported";
-                       kind = x86_64::kPCRel32;
-                       dstAddr = (int64_t)((int32_t)(E::get32(*fixUpPtr)));
-                       switch ( reloc->r_type() ) {
-                               case X86_64_RELOC_SIGNED:
-                                       if ( reloc->r_extern() ) {
-                                               // Support older relocations
-                                               if ( dstAddr == (uint64_t)(-1) ) {
+                               throw "length != 2 and X86_64_RELOC_SIGNED* not supported";
+                       addend = (int64_t)((int32_t)(E::get32(*fixUpPtr)));
+                       if ( reloc->r_extern() ) {
+                               switch ( reloc->r_type() ) {
+                                       case X86_64_RELOC_SIGNED:
+                                               kind = x86_64::kPCRel32;
+                                               // begin support for old .o files before X86_64_RELOC_SIGNED_1 was created
+                                               if ( addend == (uint64_t)(-1) ) {
+                                                       addend = 0;
                                                        kind = x86_64::kPCRel32_1;
                                                        kind = x86_64::kPCRel32_1;
-                                                       dstAddr = 0;
                                                }
                                                }
-                                               else if ( dstAddr == (uint64_t)(-2) ) {
+                                               else if ( addend == (uint64_t)(-2) ) {
+                                                       addend = 0;
                                                        kind = x86_64::kPCRel32_2;
                                                        kind = x86_64::kPCRel32_2;
-                                                       dstAddr = 0;
                                                }
                                                }
-                                               else if ( dstAddr == (uint64_t)(-4) ) {
+                                               else if ( addend == (uint64_t)(-4) ) {
+                                                       addend = 0;
                                                        kind = x86_64::kPCRel32_4;
                                                        kind = x86_64::kPCRel32_4;
-                                                       dstAddr = 0;
                                                }
                                                }
-                                       }
-                                       break;
-                               case X86_64_RELOC_SIGNED_1:
-                                       if ( reloc->r_extern() ) {
-                                               dstAddr = 0;
-                                       } else {
-                                               dstAddr += 1;
-                                       }
-                                       kind = x86_64::kPCRel32_1;
-                                       break;
-                               case X86_64_RELOC_SIGNED_2:
-                                       if ( reloc->r_extern() ) {
-                                               dstAddr = 0;
-                                       } else {
-                                               dstAddr += 2;
-                                       }
-                                       kind = x86_64::kPCRel32_2;
-                                       break;
-                               case X86_64_RELOC_SIGNED_4:
-                                       if ( reloc->r_extern() ) {
-                                               dstAddr = 0;
-                                       } else {
-                                               dstAddr += 4;
-                                       }
-                                       kind = x86_64::kPCRel32_4;
-                                       break;
-                               default:
-                                       break;
+                                               break;
+                                               // end support for old .o files before X86_64_RELOC_SIGNED_1 was created
+                                       case X86_64_RELOC_SIGNED_1:
+                                               kind = x86_64::kPCRel32_1;
+                                               addend += 1;
+                                               break;  
+                                       case X86_64_RELOC_SIGNED_2:
+                                               kind = x86_64::kPCRel32_2;
+                                               addend += 2;
+                                               break;  
+                                       case X86_64_RELOC_SIGNED_4:
+                                               kind = x86_64::kPCRel32_4;
+                                               addend += 4;
+                                               break;
+                               }
+                               makeReferenceToSymbol(kind, srcAddr, targetSymbol, addend);
                        }
                        }
-                       if ( reloc->r_extern() ) 
-                               makeReferenceToSymbol(kind, srcAddr, targetSymbol, dstAddr);
                        else {
                        else {
-                               makeReference(kind, srcAddr, srcAddr+4+dstAddr);
-                       }
+                               uint64_t ripRelativeOffset = addend;
+                               switch ( reloc->r_type() ) {
+                                       case X86_64_RELOC_SIGNED:
+                                               dstAddr = srcAddr + 4 + ripRelativeOffset;
+                                               kind = x86_64::kPCRel32;
+                                               break;
+                                       case X86_64_RELOC_SIGNED_1:
+                                               dstAddr = srcAddr + 5 + ripRelativeOffset;
+                                               kind = x86_64::kPCRel32_1;
+                                               break;  
+                                       case X86_64_RELOC_SIGNED_2:
+                                               dstAddr = srcAddr + 6 + ripRelativeOffset;
+                                               kind = x86_64::kPCRel32_2;
+                                               break;  
+                                       case X86_64_RELOC_SIGNED_4:
+                                               dstAddr = srcAddr + 8 + ripRelativeOffset;
+                                               kind = x86_64::kPCRel32_4;
+                                               break;
+                               }
+                               makeReference(kind, srcAddr, dstAddr);
+                       }       
                        break;
                case X86_64_RELOC_BRANCH:
                        if ( ! reloc->r_pcrel() )
                        break;
                case X86_64_RELOC_BRANCH:
                        if ( ! reloc->r_pcrel() )
index 0aa95b755dccbfef344d82f99ee7872077aea48e..7ac12fe90c4c7c05cc900a0d083a4b1dfb810be2 100644 (file)
@@ -169,7 +169,7 @@ private:
        void                                            partitionIntoSections();
        bool                                            addBranchIslands();
        bool                                            addPPCBranchIslands();
        void                                            partitionIntoSections();
        bool                                            addBranchIslands();
        bool                                            addPPCBranchIslands();
-       uint8_t                                         branch24Reference();
+       bool                                            isBranch24Reference(uint8_t kind);
        void                                            adjustLoadCommandsAndPadding();
        void                                            createDynamicLinkerCommand();
        void                                            createDylibCommands();
        void                                            adjustLoadCommandsAndPadding();
        void                                            createDynamicLinkerCommand();
        void                                            createDylibCommands();
@@ -357,7 +357,7 @@ public:
        virtual bool                                                    requiresFollowOnAtom() const    { return false; }
        virtual ObjectFile::Atom&                               getFollowOnAtom() const                 { return *((ObjectFile::Atom*)NULL); }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
        virtual bool                                                    requiresFollowOnAtom() const    { return false; }
        virtual ObjectFile::Atom&                               getFollowOnAtom() const                 { return *((ObjectFile::Atom*)NULL); }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
-       virtual uint8_t                                                 getAlignment() const                    { return 2; }
+       virtual ObjectFile::Alignment                   getAlignment() const                    { return ObjectFile::Alignment(2); }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const { throw "don't use copyRawContent"; }
        virtual void                                                    setScope(Scope)                                 { }
 
        virtual void                                                    copyRawContent(uint8_t buffer[]) const { throw "don't use copyRawContent"; }
        virtual void                                                    setScope(Scope)                                 { }
 
@@ -386,7 +386,7 @@ public:
        virtual bool                                                    isZeroFill() const              { return true; }
        virtual uint64_t                                                getSize() const                 { return fSize; }
        virtual const char*                                             getSectionName() const  { return "._zeropage"; }
        virtual bool                                                    isZeroFill() const              { return true; }
        virtual uint64_t                                                getSize() const                 { return fSize; }
        virtual const char*                                             getSectionName() const  { return "._zeropage"; }
-       virtual uint8_t                                                 getAlignment() const    { return 12; }
+       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(12); }
        void                                                                    setSize(uint64_t size)  { fSize = size; }
 private:
        using WriterAtom<A>::fWriter;
        void                                                                    setSize(uint64_t size)  { fSize = size; }
 private:
        using WriterAtom<A>::fWriter;
@@ -404,7 +404,7 @@ public:
        virtual ObjectFile::Atom::Scope                                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
        virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
        virtual uint64_t                                                                getSize() const                         { return 0; }
        virtual ObjectFile::Atom::Scope                                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
        virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
        virtual uint64_t                                                                getSize() const                         { return 0; }
-       virtual uint8_t                                                                 getAlignment() const            { return 12; }
+       virtual ObjectFile::Alignment                                   getAlignment() const            { return ObjectFile::Alignment(12); }
        virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
        virtual void                                                                    copyRawContent(uint8_t buffer[]) const {}
 };
        virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
        virtual void                                                                    copyRawContent(uint8_t buffer[]) const {}
 };
@@ -420,7 +420,7 @@ public:
        virtual ObjectFile::Atom::Scope                                 getScope() const;
        virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const;
        virtual uint64_t                                                                getSize() const                         { return sizeof(macho_header<typename A::P>); }
        virtual ObjectFile::Atom::Scope                                 getScope() const;
        virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const;
        virtual uint64_t                                                                getSize() const                         { return sizeof(macho_header<typename A::P>); }
-       virtual uint8_t                                                                 getAlignment() const            { return 12; }
+       virtual ObjectFile::Alignment                                   getAlignment() const            { return ObjectFile::Alignment(12); }
        virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
        virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
        virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -438,7 +438,7 @@ public:
        virtual bool                                                    isZeroFill() const              { return true; }
        virtual uint64_t                                                getSize() const                 { return fWriter.fOptions.customStackSize(); }
        virtual const char*                                             getSectionName() const  { return "._stack"; }
        virtual bool                                                    isZeroFill() const              { return true; }
        virtual uint64_t                                                getSize() const                 { return fWriter.fOptions.customStackSize(); }
        virtual const char*                                             getSectionName() const  { return "._stack"; }
-       virtual uint8_t                                                 getAlignment() const    { return 12; }
+       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(12); }
 private:
        using WriterAtom<A>::fWriter;
        typedef typename A::P                                   P;
 private:
        using WriterAtom<A>::fWriter;
        typedef typename A::P                                   P;
@@ -450,6 +450,8 @@ class LoadCommandAtom : public WriterAtom<A>
 {
 protected:
                                                                                        LoadCommandAtom(Writer<A>& writer, Segment& segment) : WriterAtom<A>(writer, segment) {}
 {
 protected:
                                                                                        LoadCommandAtom(Writer<A>& writer, Segment& segment) : WriterAtom<A>(writer, segment) {}
+       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(log2(sizeof(typename A::P::uint_t))); }
+       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        static uint64_t                                                 alignedSize(uint64_t size);
 };
 
        static uint64_t                                                 alignedSize(uint64_t size);
 };
 
@@ -463,8 +465,6 @@ public:
                                                                                                { writer.fSegmentCommands = this; }
        virtual const char*                                             getDisplayName() const  { return "segment load commands"; }
        virtual uint64_t                                                getSize() const                 { return fSize; }
                                                                                                { writer.fSegmentCommands = this; }
        virtual const char*                                             getDisplayName() const  { return "segment load commands"; }
        virtual uint64_t                                                getSize() const                 { return fSize; }
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
        void                                                                    computeSize();
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
        void                                                                    computeSize();
@@ -485,8 +485,6 @@ public:
                                                                                        SymbolTableLoadCommandsAtom(Writer<A>&);
        virtual const char*                                             getDisplayName() const { return "symbol table load commands"; }
        virtual uint64_t                                                getSize() const;
                                                                                        SymbolTableLoadCommandsAtom(Writer<A>&);
        virtual const char*                                             getDisplayName() const { return "symbol table load commands"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
        unsigned int                                                    commandCount();
 
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
        unsigned int                                                    commandCount();
 
@@ -505,8 +503,6 @@ public:
                                                                                                : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const { return "thread load commands"; }
        virtual uint64_t                                                getSize() const;
                                                                                                : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const { return "thread load commands"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -522,8 +518,6 @@ public:
                                                                                        DyldLoadCommandsAtom(Writer<A>& writer)  : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const  { return "dyld load command"; }
        virtual uint64_t                                                getSize() const;
                                                                                        DyldLoadCommandsAtom(Writer<A>& writer)  : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const  { return "dyld load command"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -538,8 +532,6 @@ public:
                LoadCommandAtom<A>(writer, Segment::fgTextSegment), clientString(client) {}
        virtual const char*                                                     getDisplayName() const  { return "allowable_client load command"; }
        virtual uint64_t                                                        getSize() const;
                LoadCommandAtom<A>(writer, Segment::fgTextSegment), clientString(client) {}
        virtual const char*                                                     getDisplayName() const  { return "allowable_client load command"; }
        virtual uint64_t                                                        getSize() const;
-       virtual uint8_t                                                         getAlignment() const    { return 2; }
-       virtual const char*                                                     getSectionName() const  { return "._load_commands"; }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -555,8 +547,6 @@ public:
                                                                                         : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fInfo(info) {}
        virtual const char*                                             getDisplayName() const  { return "dylib load command"; }
        virtual uint64_t                                                getSize() const;
                                                                                         : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fInfo(info) {}
        virtual const char*                                             getDisplayName() const  { return "dylib load command"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -571,8 +561,6 @@ public:
                                                                                        DylibIDLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const { return "dylib ID load command"; }
        virtual uint64_t                                                getSize() const;
                                                                                        DylibIDLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const { return "dylib ID load command"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -586,8 +574,6 @@ public:
                                                                                        RoutinesLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const { return "routines load command"; }
        virtual uint64_t                                                getSize() const                 { return sizeof(macho_routines_command<typename A::P>); }
                                                                                        RoutinesLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
        virtual const char*                                             getDisplayName() const { return "routines load command"; }
        virtual uint64_t                                                getSize() const                 { return sizeof(macho_routines_command<typename A::P>); }
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -602,8 +588,6 @@ public:
                                                                                         : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fName(name) {}
        virtual const char*                                             getDisplayName() const  { return "sub-umbrella load command"; }
        virtual uint64_t                                                getSize() const;
                                                                                         : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fName(name) {}
        virtual const char*                                             getDisplayName() const  { return "sub-umbrella load command"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        typedef typename A::P                                   P;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        typedef typename A::P                                   P;
@@ -618,8 +602,6 @@ public:
                                                                                                : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fNameStart(nameStart), fNameLength(nameLen) {}
        virtual const char*                                             getDisplayName() const  { return "sub-library load command"; }
        virtual uint64_t                                                getSize() const;
                                                                                                : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fNameStart(nameStart), fNameLength(nameLen) {}
        virtual const char*                                             getDisplayName() const  { return "sub-library load command"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -636,8 +618,6 @@ public:
                                                                                                        : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fName(name) {}
        virtual const char*                                             getDisplayName() const  { return "umbrella load command"; }
        virtual uint64_t                                                getSize() const;
                                                                                                        : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fName(name) {}
        virtual const char*                                             getDisplayName() const  { return "umbrella load command"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -653,8 +633,6 @@ public:
                                                                                                : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fEmit(false) { ::uuid_generate_random(fUUID);}
        virtual const char*                                             getDisplayName() const  { return "uuid load command"; }
        virtual uint64_t                                                getSize() const                 { return fEmit ? sizeof(macho_uuid_command<typename A::P>) : 0; }
                                                                                                : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fEmit(false) { ::uuid_generate_random(fUUID);}
        virtual const char*                                             getDisplayName() const  { return "uuid load command"; }
        virtual uint64_t                                                getSize() const                 { return fEmit ? sizeof(macho_uuid_command<typename A::P>) : 0; }
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
-       virtual const char*                                             getSectionName() const  { return "._load_commands"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
        virtual void                                                emit()                                      { fEmit = true; }
 private:
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
        virtual void                                                emit()                                      { fEmit = true; }
 private:
@@ -672,7 +650,6 @@ public:
                                                                                                        : WriterAtom<A>(writer, Segment::fgTextSegment), fSize(0) {}
        virtual const char*                                             getDisplayName() const  { return "header padding"; }
        virtual uint64_t                                                getSize() const                 { return fSize; }
                                                                                                        : WriterAtom<A>(writer, Segment::fgTextSegment), fSize(0) {}
        virtual const char*                                             getDisplayName() const  { return "header padding"; }
        virtual uint64_t                                                getSize() const                 { return fSize; }
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
        virtual const char*                                             getSectionName() const  { return "._load_cmds_pad"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
        virtual const char*                                             getSectionName() const  { return "._load_cmds_pad"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
@@ -700,7 +677,7 @@ public:
                                                                                        SectionRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "section relocations"; }
        virtual uint64_t                                                getSize() const;
                                                                                        SectionRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "section relocations"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 3; }
+       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(3); }
        virtual const char*                                             getSectionName() const  { return "._section_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        virtual const char*                                             getSectionName() const  { return "._section_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -715,7 +692,7 @@ public:
                                                                                        LocalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "local relocations"; }
        virtual uint64_t                                                getSize() const;
                                                                                        LocalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "local relocations"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 3; }
+       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(3); }
        virtual const char*                                             getSectionName() const  { return "._local_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        virtual const char*                                             getSectionName() const  { return "._local_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -730,7 +707,6 @@ public:
                                                                                        SymbolTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "symbol table"; }
        virtual uint64_t                                                getSize() const;
                                                                                        SymbolTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "symbol table"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
        virtual const char*                                             getSectionName() const  { return "._symbol_table"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        virtual const char*                                             getSectionName() const  { return "._symbol_table"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -745,7 +721,7 @@ public:
                                                                                        ExternalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "external relocations"; }
        virtual uint64_t                                                getSize() const;
                                                                                        ExternalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "external relocations"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 3; }
+       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(3); }
        virtual const char*                                             getSectionName() const  { return "._extern_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        virtual const char*                                             getSectionName() const  { return "._extern_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -765,7 +741,6 @@ public:
                                                                                        IndirectTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "indirect symbol table"; }
        virtual uint64_t                                                getSize() const;
                                                                                        IndirectTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "indirect symbol table"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
        virtual const char*                                             getSectionName() const  { return "._indirect_syms"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
        virtual const char*                                             getSectionName() const  { return "._indirect_syms"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
@@ -789,7 +764,6 @@ public:
                                                                                        StringsLinkEditAtom(Writer<A>& writer);
        virtual const char*                                             getDisplayName() const  { return "string pool"; }
        virtual uint64_t                                                getSize() const;
                                                                                        StringsLinkEditAtom(Writer<A>& writer);
        virtual const char*                                             getDisplayName() const  { return "string pool"; }
        virtual uint64_t                                                getSize() const;
-       virtual uint8_t                                                 getAlignment() const    { return 2; }
        virtual const char*                                             getSectionName() const  { return "._string_pool"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
        virtual const char*                                             getSectionName() const  { return "._string_pool"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
@@ -856,8 +830,8 @@ public:
                                                                                        StubAtom(Writer<A>& writer, ObjectFile::Atom& target);
        virtual const char*                                             getName() const                         { return fName; }
        virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
                                                                                        StubAtom(Writer<A>& writer, ObjectFile::Atom& target);
        virtual const char*                                             getName() const                         { return fName; }
        virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
-       virtual uint8_t                                                 getAlignment() const            { return 2; }
        virtual uint64_t                                                getSize() const;
        virtual uint64_t                                                getSize() const;
+       virtual ObjectFile::Alignment                   getAlignment() const;
        virtual const char*                                             getSectionName() const          { return "__symbol_stub1"; }
        virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
        virtual const char*                                             getSectionName() const          { return "__symbol_stub1"; }
        virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
@@ -878,7 +852,6 @@ public:
                                                                                        StubHelperAtom(Writer<A>& writer, ObjectFile::Atom& target, ObjectFile::Atom& lazyPointer);
        virtual const char*                                             getName() const                         { return fName; }
        virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
                                                                                        StubHelperAtom(Writer<A>& writer, ObjectFile::Atom& target, ObjectFile::Atom& lazyPointer);
        virtual const char*                                             getName() const                         { return fName; }
        virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
-       virtual uint8_t                                                 getAlignment() const            { return 2; }
        virtual uint64_t                                                getSize() const;
        virtual const char*                                             getSectionName() const          { return "__stub_helper"; }
        virtual std::vector<ObjectFile::Reference*>&  getReferences() const     { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
        virtual uint64_t                                                getSize() const;
        virtual const char*                                             getSectionName() const          { return "__stub_helper"; }
        virtual std::vector<ObjectFile::Reference*>&  getReferences() const     { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
@@ -989,7 +962,7 @@ struct ExportSorter
 template <typename A>
 Writer<A>::Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries)
        : ExecutableFile::Writer(dynamicLibraries), fFilePath(strdup(path)), fOptions(options), fLoadCommandsSection(NULL),
 template <typename A>
 Writer<A>::Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries)
        : ExecutableFile::Writer(dynamicLibraries), fFilePath(strdup(path)), fOptions(options), fLoadCommandsSection(NULL),
-         fLoadCommandsSegment(NULL), fPadSegmentInfo(NULL), fPageZeroAtom(NULL), fLargestAtomSize(1), 
+         fLoadCommandsSegment(NULL), fPadSegmentInfo(NULL), fPageZeroAtom(NULL), fSymbolTableCount(0), fLargestAtomSize(1), 
          fEmitVirtualSections(false), fHasWeakExports(false), fReferencesWeakImports(false),
          fSeenFollowOnReferences(false), fWritableSegmentPastFirst4GB(false), fFirstWritableSegment(NULL)
 {
          fEmitVirtualSections(false), fHasWeakExports(false), fReferencesWeakImports(false),
          fSeenFollowOnReferences(false), fWritableSegmentPastFirst4GB(false), fFirstWritableSegment(NULL)
 {
@@ -997,7 +970,7 @@ Writer<A>::Writer(const char* path, Options& options, std::vector<ExecutableFile
        if ( fOptions.outputKind() == Options::kObjectFile )
                permissions = 0666;
        // Calling unlink first assures the file is gone so that open creates it with correct permissions
        if ( fOptions.outputKind() == Options::kObjectFile )
                permissions = 0666;
        // Calling unlink first assures the file is gone so that open creates it with correct permissions
-       // It also handles the case where fFilePath file is not writeable but its directory is
+       // It also handles the case where fFilePath file is not writable but its directory is
        // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
        (void)unlink(fFilePath);
        fFileDescriptor = open(fFilePath, O_CREAT | O_WRONLY | O_TRUNC, permissions);
        // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
        (void)unlink(fFilePath);
        fFileDescriptor = open(fFilePath, O_CREAT | O_WRONLY | O_TRUNC, permissions);
@@ -3286,7 +3259,7 @@ void  Writer<ppc64>::scanForAbsoluteReferences()
                                                //fprintf(stderr, "found -mdyanmic-no-pic codegen in %s in %s\n", atom->getDisplayName(), atom->getFile()->getPath());
                                                // shrink page-zero and add pad segment to compensate
                                                fPadSegmentInfo = new SegmentInfo();
                                                //fprintf(stderr, "found -mdyanmic-no-pic codegen in %s in %s\n", atom->getDisplayName(), atom->getFile()->getPath());
                                                // shrink page-zero and add pad segment to compensate
                                                fPadSegmentInfo = new SegmentInfo();
-                                               strcpy(fPadSegmentInfo->fName, "__4BGFILL");
+                                               strcpy(fPadSegmentInfo->fName, "__4GBFILL");
                                                fPageZeroAtom->setSize(0x1000);
                                                return;
                                }
                                                fPageZeroAtom->setSize(0x1000);
                                                return;
                                }
@@ -3497,7 +3470,7 @@ void Writer<A>::partitionIntoSections()
                                currentSectionInfo = new SectionInfo();
                                strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
                                strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
                                currentSectionInfo = new SectionInfo();
                                strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
                                strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
-                               currentSectionInfo->fAlignment = atom->getAlignment();
+                               currentSectionInfo->fAlignment = atom->getAlignment().powerOf2;
                                currentSectionInfo->fAllZeroFill = atom->isZeroFill();
                                currentSectionInfo->fVirtualSection = ( (currentSectionInfo->fSectionName[0] == '.') || 
                                                (oneSegmentCommand && (atom->getDefinitionKind()==ObjectFile::Atom::kTentativeDefinition)) && !fOptions.makeTentativeDefinitionsReal() );
                                currentSectionInfo->fAllZeroFill = atom->isZeroFill();
                                currentSectionInfo->fVirtualSection = ( (currentSectionInfo->fSectionName[0] == '.') || 
                                                (oneSegmentCommand && (atom->getDefinitionKind()==ObjectFile::Atom::kTentativeDefinition)) && !fOptions.makeTentativeDefinitionsReal() );
@@ -3529,7 +3502,7 @@ void Writer<A>::partitionIntoSections()
                                currentSectionInfo->fAtoms.reserve(fAllAtoms->size()/4); // reduce reallocations by starting large
                                strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
                                strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
                                currentSectionInfo->fAtoms.reserve(fAllAtoms->size()/4); // reduce reallocations by starting large
                                strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
                                strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
-                               currentSectionInfo->fAlignment = atom->getAlignment();
+                               currentSectionInfo->fAlignment = atom->getAlignment().powerOf2;
                                // check for -sectalign override
                                std::vector<Options::SectionAlignment>& alignmentOverrides = fOptions.sectionAlignments();
                                for(std::vector<Options::SectionAlignment>::iterator it=alignmentOverrides.begin(); it != alignmentOverrides.end(); ++it) {
                                // check for -sectalign override
                                std::vector<Options::SectionAlignment>& alignmentOverrides = fOptions.sectionAlignments();
                                for(std::vector<Options::SectionAlignment>::iterator it=alignmentOverrides.begin(); it != alignmentOverrides.end(); ++it) {
@@ -3572,13 +3545,20 @@ void Writer<A>::partitionIntoSections()
                // change section object to be Writer's SectionInfo object
                atom->setSection(currentSectionInfo);
                // section alignment is that of a contained atom with the greatest alignment
                // change section object to be Writer's SectionInfo object
                atom->setSection(currentSectionInfo);
                // section alignment is that of a contained atom with the greatest alignment
-               uint8_t atomAlign = atom->getAlignment();
+               uint8_t atomAlign = atom->getAlignment().powerOf2;
                if ( currentSectionInfo->fAlignment < atomAlign )
                        currentSectionInfo->fAlignment = atomAlign;
                // calculate section offset for this atom
                uint64_t offset = currentSectionInfo->fSize;
                uint64_t alignment = 1 << atomAlign;
                if ( currentSectionInfo->fAlignment < atomAlign )
                        currentSectionInfo->fAlignment = atomAlign;
                // calculate section offset for this atom
                uint64_t offset = currentSectionInfo->fSize;
                uint64_t alignment = 1 << atomAlign;
-               offset = ( (offset+alignment-1) & (-alignment) );
+               uint64_t currentModulus = (offset % alignment);
+               uint64_t requiredModulus = atom->getAlignment().modulus;
+               if ( currentModulus != requiredModulus ) {
+                       if ( requiredModulus > currentModulus )
+                               offset += requiredModulus-currentModulus;
+                       else
+                               offset += requiredModulus+alignment-currentModulus;             
+               }
                atom->setSectionOffset(offset);
                uint64_t curAtomSize = atom->getSize();
                currentSectionInfo->fSize = offset + curAtomSize;
                atom->setSectionOffset(offset);
                uint64_t curAtomSize = atom->getSize();
                currentSectionInfo->fSize = offset + curAtomSize;
@@ -3631,15 +3611,25 @@ bool Writer<x86_64>::addBranchIslands()
 
 
 template <>
 
 
 template <>
-inline uint8_t Writer<ppc>::branch24Reference()
+bool Writer<ppc>::isBranch24Reference(uint8_t kind)
 {
 {
-       return ppc::kBranch24;
+       switch (kind) {
+               case ppc::kBranch24:
+               case ppc::kBranch24WeakImport:
+                       return true;
+       }
+       return false;
 }
 
 template <>
 }
 
 template <>
-inline uint8_t Writer<ppc64>::branch24Reference()
+bool Writer<ppc64>::isBranch24Reference(uint8_t kind)
 {
 {
-       return ppc64::kBranch24;
+       switch (kind) {
+               case ppc64::kBranch24:
+               case ppc64::kBranch24WeakImport:
+                       return true;
+       }
+       return false;
 }
 
 //
 }
 
 //
@@ -3667,16 +3657,17 @@ inline uint8_t Writer<ppc64>::branch24Reference()
 template <typename A>
 bool Writer<A>::addPPCBranchIslands()
 {
 template <typename A>
 bool Writer<A>::addPPCBranchIslands()
 {
+       bool log = false;
        bool result = false;
        // Can only possibly need branch islands if __TEXT segment > 16M
        if ( fLoadCommandsSegment->fSize > 16000000 ) {
        bool result = false;
        // Can only possibly need branch islands if __TEXT segment > 16M
        if ( fLoadCommandsSegment->fSize > 16000000 ) {
-               //fprintf(stderr, "ld64: checking for branch islands, __TEXT segment size=%llu\n", fLoadCommandsSegment->fSize);
+               if ( log) fprintf(stderr, "ld64: checking for branch islands, __TEXT segment size=%llu\n", fLoadCommandsSegment->fSize);
                const uint32_t kBetweenRegions = 15000000; // place regions of islands every 15MB in __text section
                SectionInfo* textSection = NULL;
                for (std::vector<SectionInfo*>::iterator it=fLoadCommandsSegment->fSections.begin(); it != fLoadCommandsSegment->fSections.end(); it++) {
                        if ( strcmp((*it)->fSectionName, "__text") == 0 ) {
                                textSection = *it;
                const uint32_t kBetweenRegions = 15000000; // place regions of islands every 15MB in __text section
                SectionInfo* textSection = NULL;
                for (std::vector<SectionInfo*>::iterator it=fLoadCommandsSegment->fSections.begin(); it != fLoadCommandsSegment->fSections.end(); it++) {
                        if ( strcmp((*it)->fSectionName, "__text") == 0 ) {
                                textSection = *it;
-                               //fprintf(stderr, "ld64: checking for branch islands, __text section size=%llu\n", textSection->fSize);
+                               if ( log) fprintf(stderr, "ld64: checking for branch islands, __text section size=%llu\n", textSection->fSize);
                                break;
                        }
                }
                                break;
                        }
                }
@@ -3692,33 +3683,68 @@ bool Writer<A>::addPPCBranchIslands()
                        std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
                        for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
                                ObjectFile::Reference* ref = *rit;
                        std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
                        for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
                                ObjectFile::Reference* ref = *rit;
-                               if ( ref->getKind() == this->branch24Reference() ) {
+                               if ( this->isBranch24Reference(ref->getKind()) ) {
                                        ObjectFile::Atom& target = ref->getTarget();
                                        int64_t srcAddr = atom->getAddress() + ref->getFixUpOffset();
                                        int64_t dstAddr = target.getAddress() + ref->getTargetOffset();
                                        int64_t displacement = dstAddr - srcAddr;
                                        ObjectFile::Atom& target = ref->getTarget();
                                        int64_t srcAddr = atom->getAddress() + ref->getFixUpOffset();
                                        int64_t dstAddr = target.getAddress() + ref->getTargetOffset();
                                        int64_t displacement = dstAddr - srcAddr;
+                                       TargetAndOffset finalTargetAndOffset = { &target, ref->getTargetOffset() };
                                        const int64_t kFifteenMegLimit = kBetweenRegions;
                                        const int64_t kFifteenMegLimit = kBetweenRegions;
-                                       if ( (displacement > kFifteenMegLimit) || (displacement < (-kFifteenMegLimit)) ) {
-                                               for (int i=0; i < kIslandRegionsCount; ++i) {
-                                                       AtomToIsland* region=&regionsMap[i];
+                                       if ( displacement > kFifteenMegLimit ) {
+                                               // create forward branch chain
+                                               ObjectFile::Atom* nextTarget = &target;
+                                               uint64_t nextTargetOffset = ref->getTargetOffset();
+                                               for (int i=kIslandRegionsCount-1; i >=0 ; --i) {
+                                                       AtomToIsland* region = &regionsMap[i];
                                                        int64_t islandRegionAddr = kBetweenRegions * (i+1);
                                                        int64_t islandRegionAddr = kBetweenRegions * (i+1);
-                                                       if ( ((srcAddr < islandRegionAddr) && (dstAddr > islandRegionAddr))
-                                                          ||((dstAddr < islandRegionAddr) && (srcAddr > islandRegionAddr)) ) {
-                                                               TargetAndOffset islandTarget = { &target, ref->getTargetOffset() };
-                                                               AtomToIsland::iterator pos = region->find(islandTarget);
+                                                       if ( (srcAddr < islandRegionAddr) && (islandRegionAddr <= dstAddr) ) {
+                                                               AtomToIsland::iterator pos = region->find(finalTargetAndOffset);
                                                                if ( pos == region->end() ) {
                                                                if ( pos == region->end() ) {
-                                                                       BranchIslandAtom<A>* island = new BranchIslandAtom<A>(*this, target.getDisplayName(), i, target, ref->getTargetOffset());
+                                                                       BranchIslandAtom<A>* island = new BranchIslandAtom<A>(*this, target.getDisplayName(), i, *nextTarget, nextTargetOffset);
                                                                        island->setSection(textSection);
                                                                        island->setSection(textSection);
-                                                                       (*region)[islandTarget] = island;
+                                                                       (*region)[finalTargetAndOffset] = island;
+                                                                       if (log) fprintf(stderr, "added island %s to region %d for %s\n", island->getDisplayName(), i, atom->getDisplayName());
                                                                        regionsIslands[i].push_back(island);
                                                                        ++islandCount;
                                                                        regionsIslands[i].push_back(island);
                                                                        ++islandCount;
-                                                                       ref->setTarget(*island, 0);
+                                                                       nextTarget = island;
+                                                                       nextTargetOffset = 0;
                                                                }
                                                                else {
                                                                }
                                                                else {
-                                                                       ref->setTarget(*(pos->second), 0);
+                                                                       nextTarget = pos->second;
+                                                                       nextTargetOffset = 0;
                                                                }
                                                        }
                                                }
                                                                }
                                                        }
                                                }
+                                               if (log) fprintf(stderr, "using island %s for %s\n", nextTarget->getDisplayName(), atom->getDisplayName());
+                                               ref->setTarget(*nextTarget, nextTargetOffset);
+                                       }
+                                       else if ( displacement < (-kFifteenMegLimit) ) {
+                                               // create back branching chain
+                                               ObjectFile::Atom* prevTarget = &target;
+                                               uint64_t prevTargetOffset = ref->getTargetOffset();
+                                               for (int i=0; i < kIslandRegionsCount ; ++i) {
+                                                       AtomToIsland* region = &regionsMap[i];
+                                                       int64_t islandRegionAddr = kBetweenRegions * (i+1);
+                                                       if ( (dstAddr <= islandRegionAddr) && (islandRegionAddr < srcAddr) ) {
+                                                               AtomToIsland::iterator pos = region->find(finalTargetAndOffset);
+                                                               if ( pos == region->end() ) {
+                                                                       BranchIslandAtom<A>* island = new BranchIslandAtom<A>(*this, target.getDisplayName(), i, *prevTarget, prevTargetOffset);
+                                                                       island->setSection(textSection);
+                                                                       (*region)[finalTargetAndOffset] = island;
+                                                                       if (log) fprintf(stderr, "added back island %s to region %d for %s\n", island->getDisplayName(), i, atom->getDisplayName());
+                                                                       regionsIslands[i].push_back(island);
+                                                                       ++islandCount;
+                                                                       prevTarget = island;
+                                                                       prevTargetOffset = 0;
+                                                               }
+                                                               else {
+                                                                       prevTarget = pos->second;
+                                                                       prevTargetOffset = 0;
+                                                               }
+                                                       }
+                                               }
+                                               if (log) fprintf(stderr, "using back island %s for %s\n", prevTarget->getDisplayName(), atom->getDisplayName());
+                                               ref->setTarget(*prevTarget, prevTargetOffset);
                                        }
                                }
                        }
                                        }
                                }
                        }
@@ -3726,32 +3752,36 @@ bool Writer<A>::addPPCBranchIslands()
 
                // insert islands into __text section and adjust section offsets
                if ( islandCount > 0 ) {
 
                // insert islands into __text section and adjust section offsets
                if ( islandCount > 0 ) {
-                       //fprintf(stderr, "ld64: %u branch islands required\n", islandCount);
+                       if ( log) fprintf(stderr, "ld64: %u branch islands required\n", islandCount);
                        std::vector<ObjectFile::Atom*> newAtomList;
                        newAtomList.reserve(textSection->fAtoms.size()+islandCount);
                        uint64_t islandRegionAddr = kBetweenRegions;
                        std::vector<ObjectFile::Atom*> newAtomList;
                        newAtomList.reserve(textSection->fAtoms.size()+islandCount);
                        uint64_t islandRegionAddr = kBetweenRegions;
+                       uint64_t textSectionAlignment = (1 << textSection->fAlignment);
                        int regionIndex = 0;
                        int regionIndex = 0;
+                       uint64_t atomSlide = 0;
                        uint64_t sectionOffset = 0;
                        for (std::vector<ObjectFile::Atom*>::iterator it=textSection->fAtoms.begin(); it != textSection->fAtoms.end(); it++) {
                                ObjectFile::Atom* atom = *it;
                                newAtomList.push_back(atom);
                                if ( atom->getAddress() > islandRegionAddr ) {
                        uint64_t sectionOffset = 0;
                        for (std::vector<ObjectFile::Atom*>::iterator it=textSection->fAtoms.begin(); it != textSection->fAtoms.end(); it++) {
                                ObjectFile::Atom* atom = *it;
                                newAtomList.push_back(atom);
                                if ( atom->getAddress() > islandRegionAddr ) {
+                                       uint64_t islandStartOffset = atom->getSectionOffset();
+                                       sectionOffset = islandStartOffset + atomSlide;
                                        std::vector<ObjectFile::Atom*>* regionIslands = &regionsIslands[regionIndex];
                                        for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
                                                ObjectFile::Atom* islandAtom = *rit;
                                                newAtomList.push_back(islandAtom);
                                        std::vector<ObjectFile::Atom*>* regionIslands = &regionsIslands[regionIndex];
                                        for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
                                                ObjectFile::Atom* islandAtom = *rit;
                                                newAtomList.push_back(islandAtom);
-                                               uint64_t alignment = 1 << (islandAtom->getAlignment());
+                                               uint64_t alignment = 1 << (islandAtom->getAlignment().powerOf2);
                                                sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
                                                islandAtom->setSectionOffset(sectionOffset);
                                                sectionOffset += islandAtom->getSize();
                                        }
                                        ++regionIndex;
                                        islandRegionAddr += kBetweenRegions;
                                                sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
                                                islandAtom->setSectionOffset(sectionOffset);
                                                sectionOffset += islandAtom->getSize();
                                        }
                                        ++regionIndex;
                                        islandRegionAddr += kBetweenRegions;
+                                       uint64_t islandRegionAlignmentBlocks = (sectionOffset - islandStartOffset + textSectionAlignment - 1) / textSectionAlignment;
+                                       atomSlide += (islandRegionAlignmentBlocks * textSectionAlignment);
                                }
                                }
-                               uint64_t alignment = 1 << (atom->getAlignment());
-                               sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
-                               atom->setSectionOffset(sectionOffset);
-                               sectionOffset += atom->getSize();
+                               if ( atomSlide != 0 )
+                                       atom->setSectionOffset(atom->getSectionOffset()+atomSlide);
                        }
                        // put any remaining islands at end of __text section
                        if ( regionIndex < kIslandRegionsCount ) {
                        }
                        // put any remaining islands at end of __text section
                        if ( regionIndex < kIslandRegionsCount ) {
@@ -3760,7 +3790,7 @@ bool Writer<A>::addPPCBranchIslands()
                                for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
                                        ObjectFile::Atom* islandAtom = *rit;
                                        newAtomList.push_back(islandAtom);
                                for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
                                        ObjectFile::Atom* islandAtom = *rit;
                                        newAtomList.push_back(islandAtom);
-                                       uint64_t alignment = 1 << (islandAtom->getAlignment());
+                                       uint64_t alignment = 1 << (islandAtom->getAlignment().powerOf2);
                                        sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
                                        islandAtom->setSectionOffset(sectionOffset);
                                        sectionOffset += islandAtom->getSize();
                                        sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
                                        islandAtom->setSectionOffset(sectionOffset);
                                        sectionOffset += islandAtom->getSize();
@@ -3788,7 +3818,7 @@ void Writer<A>::adjustLoadCommandsAndPadding()
        const unsigned int atomCount = loadCommandAtoms.size();
        for (unsigned int i=0; i < atomCount; ++i) {
                ObjectFile::Atom* atom = loadCommandAtoms[i];
        const unsigned int atomCount = loadCommandAtoms.size();
        for (unsigned int i=0; i < atomCount; ++i) {
                ObjectFile::Atom* atom = loadCommandAtoms[i];
-               uint64_t alignment = 1 << atom->getAlignment();
+               uint64_t alignment = 1 << atom->getAlignment().powerOf2;
                offset = ( (offset+alignment-1) & (-alignment) );
                atom->setSectionOffset(offset);
                uint32_t atomSize = atom->getSize();
                offset = ( (offset+alignment-1) & (-alignment) );
                atom->setSectionOffset(offset);
                uint32_t atomSize = atom->getSize();
@@ -4005,7 +4035,7 @@ void Writer<A>::adjustLinkEditSections()
                lastSeg->fSections[i]->setBaseAddress(address);
                for (unsigned int j=0; j < atomCount; ++j) {
                        ObjectFile::Atom* atom = atoms[j];
                lastSeg->fSections[i]->setBaseAddress(address);
                for (unsigned int j=0; j < atomCount; ++j) {
                        ObjectFile::Atom* atom = atoms[j];
-                       uint64_t alignment = 1 << atom->getAlignment();
+                       uint64_t alignment = 1 << atom->getAlignment().powerOf2;
                        sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
                        atom->setSectionOffset(sectionOffset);
                        uint64_t size = atom->getSize();
                        sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
                        atom->setSectionOffset(sectionOffset);
                        uint64_t size = atom->getSize();
@@ -4981,6 +5011,17 @@ bool StubAtom<ppc>::pic() const
        return ( fWriter.fOptions.outputKind() != Options::kDynamicExecutable );
 }
 
        return ( fWriter.fOptions.outputKind() != Options::kDynamicExecutable );
 }
 
+template <>
+ObjectFile::Alignment StubAtom<ppc>::getAlignment() const
+{
+       return 2;
+}
+
+template <>
+ObjectFile::Alignment StubAtom<ppc64>::getAlignment() const
+{
+       return 2;
+}
 
 template <>
 StubAtom<ppc>::StubAtom(Writer<ppc>& writer, ObjectFile::Atom& target)
 
 template <>
 StubAtom<ppc>::StubAtom(Writer<ppc>& writer, ObjectFile::Atom& target)
@@ -5069,7 +5110,7 @@ uint64_t StubAtom<x86_64>::getSize() const
 }
 
 template <>
 }
 
 template <>
-uint8_t StubAtom<x86>::getAlignment() const
+ObjectFile::Alignment StubAtom<x86>::getAlignment() const
 {
        // special case x86 fast stubs to be byte aligned
        return 0;
 {
        // special case x86 fast stubs to be byte aligned
        return 0;
@@ -5140,7 +5181,7 @@ void StubAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
 // x86_64 stubs are 7 bytes and need no alignment
 template <>
 
 // x86_64 stubs are 7 bytes and need no alignment
 template <>
-uint8_t StubAtom<x86_64>::getAlignment() const
+ObjectFile::Alignment StubAtom<x86_64>::getAlignment() const
 {
        return 0;
 }
 {
        return 0;
 }
index 4150fdae309e09a964c43d54d94e2974f5c89ec0..accdf559ee4d041609af7c45478fafad6008a277 100644 (file)
@@ -208,7 +208,7 @@ static void dumpAtom(ObjectFile::Atom* atom)
        printf("size:    0x%012llX\n", atom->getSize());
        
        // alignment
        printf("size:    0x%012llX\n", atom->getSize());
        
        // alignment
-       printf("align:    %d\n", atom->getAlignment());
+       printf("align:    %u mod %u\n", atom->getAlignment().modulus, (1 << atom->getAlignment().powerOf2) );
 
        // content
        if ( sDumpContent ) { 
 
        // content
        if ( sDumpContent ) { 
index 98e59f4862d569a5c7c53d752da999dd43fa41a0..69aeac62f871d0c09a31f16ee2ef8e18cacf4214 100644 (file)
@@ -154,6 +154,13 @@ protected:
 };
 
 
 };
 
 
+struct Alignment 
+{ 
+                               Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {}
+       uint8_t         leadingZeros() const { return (modulus==0) ? powerOf2 : __builtin_clz(modulus); }
+       uint16_t        powerOf2;  
+       uint16_t        modulus; 
+};
 
 //
 // An atom is the fundamental unit of linking.  A C function or global variable is an atom.
 
 //
 // An atom is the fundamental unit of linking.  A C function or global variable is an atom.
@@ -212,7 +219,7 @@ public:
        virtual bool                                                    requiresFollowOnAtom() const = 0;
        virtual Atom&                                                   getFollowOnAtom() const = 0;
        virtual std::vector<LineInfo>*                  getLineInfo() const = 0;
        virtual bool                                                    requiresFollowOnAtom() const = 0;
        virtual Atom&                                                   getFollowOnAtom() const = 0;
        virtual std::vector<LineInfo>*                  getLineInfo() const = 0;
-       virtual uint8_t                                                 getAlignment() const = 0;
+       virtual Alignment                                               getAlignment() const = 0;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const = 0;
        virtual void                                                    setScope(Scope) = 0;
 
        virtual void                                                    copyRawContent(uint8_t buffer[]) const = 0;
        virtual void                                                    setScope(Scope) = 0;
 
index 8b56436c115dbeb53f5253d8786d7cb968099bec..1eb135b0d219cb0480fe591fb0dc6baf6cbee305 100644 (file)
@@ -374,8 +374,14 @@ void Options::parseArch(const char* architecture)
                fArchitecture = CPU_TYPE_I386;
        else if ( strcmp(architecture, "x86_64") == 0 )
                fArchitecture = CPU_TYPE_X86_64;
                fArchitecture = CPU_TYPE_I386;
        else if ( strcmp(architecture, "x86_64") == 0 )
                fArchitecture = CPU_TYPE_X86_64;
+       // compatibility support for cpu-sub-types
+       else if ( (strcmp(architecture, "ppc750") == 0)
+                       || (strcmp(architecture, "ppc7400") == 0)
+                       || (strcmp(architecture, "ppc7450") == 0)
+                       || (strcmp(architecture, "ppc970") == 0) )
+               fArchitecture = CPU_TYPE_POWERPC;
        else
        else
-               throw "-arch followed by unknown architecture name";
+               throwf(" unknown/unsupported architecture name for: -arch %s", architecture);
 }
 
 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result)
 }
 
 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result)
@@ -451,23 +457,45 @@ Options::FileInfo Options::findLibrary(const char* rootName)
        throwf("library not found for -l%s", rootName);
 }
 
        throwf("library not found for -l%s", rootName);
 }
 
+Options::FileInfo Options::findFramework(const char* frameworkName)
+{
+       if ( frameworkName == NULL )
+               throw "-frameowrk missing next argument";
+       char temp[strlen(frameworkName)+1];
+       strcpy(temp, frameworkName);
+       const char* name = temp;
+       const char* suffix = NULL;
+       char* comma = strchr(temp, ',');
+       if ( comma != NULL ) {
+               *comma = '\0';
+               suffix = &comma[1];
+       }
+       return findFramework(name, suffix);
+}
 
 
-Options::FileInfo Options::findFramework(const char* rootName)
+Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
 {
        struct stat statBuffer;
 {
        struct stat statBuffer;
-       const int rootNameLen = strlen(rootName);
        for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
                 it != fFrameworkSearchPaths.end();
                 it++) {
                // ??? Shouldn't we be using String here and just initializing it?
                // ??? Use str.c_str () to pull out the string for the stat call.
                const char* dir = *it;
        for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
                 it != fFrameworkSearchPaths.end();
                 it++) {
                // ??? Shouldn't we be using String here and just initializing it?
                // ??? Use str.c_str () to pull out the string for the stat call.
                const char* dir = *it;
-               char possiblePath[strlen(dir)+2*rootNameLen+20];
+               char possiblePath[PATH_MAX];
                strcpy(possiblePath, dir);
                strcat(possiblePath, "/");
                strcat(possiblePath, rootName);
                strcat(possiblePath, ".framework/");
                strcat(possiblePath, rootName);
                strcpy(possiblePath, dir);
                strcat(possiblePath, "/");
                strcat(possiblePath, rootName);
                strcat(possiblePath, ".framework/");
                strcat(possiblePath, rootName);
+               if ( suffix != NULL ) {
+                       char realPath[PATH_MAX];
+                       // no symlink in framework to suffix variants, so follow main symlink
+                       if ( realpath(possiblePath, realPath) != NULL ) {
+                               strcpy(possiblePath, realPath);
+                               strcat(possiblePath, suffix);
+                       }
+               }
                bool found = (stat(possiblePath, &statBuffer) == 0);
                if ( fTraceDylibSearching )
                        printf("[Logging for XBS]%sfound framework: '%s'\n",
                bool found = (stat(possiblePath, &statBuffer) == 0);
                if ( fTraceDylibSearching )
                        printf("[Logging for XBS]%sfound framework: '%s'\n",
@@ -480,7 +508,11 @@ Options::FileInfo Options::findFramework(const char* rootName)
                        return result;
                }
        }
                        return result;
                }
        }
-       throwf("framework not found %s", rootName);
+       // try without suffix
+       if ( suffix != NULL ) 
+               return findFramework(rootName, NULL);
+       else
+               throwf("framework not found %s", rootName);
 }
 
 Options::FileInfo Options::findFile(const char* path)
 }
 
 Options::FileInfo Options::findFile(const char* path)
@@ -1815,3 +1847,7 @@ void Options::checkIllegalOptionCombinations()
                throw "-r and -dead_strip cannot be used together\n";
 
 }
                throw "-r and -dead_strip cannot be used together\n";
 
 }
+
+
+
+
index dcedf8e76942b5942e069aa0654f2c0dc1b36147..ad2e45b2eb3aedce7558336b8fb926210feccc05 100644 (file)
@@ -172,7 +172,8 @@ private:
        void                                            buildSearchPaths(int argc, const char* argv[]);
        void                                            parseArch(const char* architecture);
        FileInfo                                        findLibrary(const char* rootName);
        void                                            buildSearchPaths(int argc, const char* argv[]);
        void                                            parseArch(const char* architecture);
        FileInfo                                        findLibrary(const char* rootName);
-       FileInfo                                        findFramework(const char* rootName);
+       FileInfo                                        findFramework(const char* frameworkName);
+       FileInfo                                        findFramework(const char* rootName, const char* suffix);
        bool                                            checkForFile(const char* format, const char* dir, const char* rootName,
                                                                                         FileInfo& result);
        uint32_t                                        parseVersionNumber(const char*);
        bool                                            checkForFile(const char* format, const char* dir, const char* rootName,
                                                                                         FileInfo& result);
        uint32_t                                        parseVersionNumber(const char*);
@@ -194,7 +195,6 @@ private:
        void                                            reconfigureDefaults();
 
 
        void                                            reconfigureDefaults();
 
 
-
        ObjectFile::ReaderOptions                       fReaderOptions;
        const char*                                                     fOutputFile;
        std::vector<Options::FileInfo>          fInputFiles;
        ObjectFile::ReaderOptions                       fReaderOptions;
        const char*                                                     fOutputFile;
        std::vector<Options::FileInfo>          fInputFiles;
index a77a78746b179be87e60808f9b3740b2a2d4bcf6..5677c324fd70a8327172a3075354b83fab2585b1 100644 (file)
@@ -80,7 +80,7 @@ public:
        virtual bool                                                            requiresFollowOnAtom() const{ return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
        virtual bool                                                            requiresFollowOnAtom() const{ return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
-       virtual uint8_t                                                         getAlignment() const            { return 4; }
+       virtual ObjectFile::Alignment                           getAlignment() const            { return ObjectFile::Alignment(4); }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
 
        virtual void                                                            setScope(Scope)                         { }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
 
        virtual void                                                            setScope(Scope)                         { }
index e26c58162a260caa0d48706955287ae37536ec90..d088f9a4f52c654d43c208a4b287d99c8553574c 100644 (file)
@@ -38,6 +38,7 @@
 
 
 #include <string>
 
 
 #include <string>
+#include <map>
 #include <set>
 #include <string>
 #include <vector>
 #include <set>
 #include <string>
 #include <vector>
@@ -318,14 +319,14 @@ private:
        void                            writeDotOutput();
        static bool                     minimizeStab(ObjectFile::Reader::Stab& stab);
        static const char*      truncateStabString(const char* str);
        void                            writeDotOutput();
        static bool                     minimizeStab(ObjectFile::Reader::Stab& stab);
        static const char*      truncateStabString(const char* str);
-       void                            collectStabs();
+       void                            collectDebugInfo();
        void                            writeOutput();
        ObjectFile::Atom*       entryPoint();
        ObjectFile::Atom*       dyldHelper();
        const char*                     assureFullPath(const char* path);
        void                            markLive(ObjectFile::Atom& atom, Linker::WhyLiveBackChain* previous);
        void                            writeOutput();
        ObjectFile::Atom*       entryPoint();
        ObjectFile::Atom*       dyldHelper();
        const char*                     assureFullPath(const char* path);
        void                            markLive(ObjectFile::Atom& atom, Linker::WhyLiveBackChain* previous);
-       void                            collectStabs(ObjectFile::Reader* reader, std::map<class ObjectFile::Atom*, uint32_t>& atomOrdinals);
-       void                            synthesizeStabs(ObjectFile::Reader* reader);
+       void                            collectStabs(ObjectFile::Reader* reader, std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals);
+       void                            synthesizeDebugNotes(std::vector<class ObjectFile::Atom*>& allAtomsByReader);
        void                            printStatistics();
        void                            printTime(const char* msg, uint64_t partTime, uint64_t totalTime);
        char*                           commatize(uint64_t in, char* out);
        void                            printStatistics();
        void                            printTime(const char* msg, uint64_t partTime, uint64_t totalTime);
        char*                           commatize(uint64_t in, char* out);
@@ -392,6 +393,7 @@ private:
        std::set<ObjectFile::Atom*>                                                     fLiveAtoms;
        std::set<ObjectFile::Atom*>                                                     fLiveRootAtoms;
        std::vector<class ObjectFile::Reader::Stab>                     fStabs;
        std::set<ObjectFile::Atom*>                                                     fLiveAtoms;
        std::set<ObjectFile::Atom*>                                                     fLiveRootAtoms;
        std::vector<class ObjectFile::Reader::Stab>                     fStabs;
+       std::vector<class ObjectFile::Atom*>                            fAtomsWithUnresolvedReferences;
        bool                                                                                            fCreateUUID;
        SectionOrder                                                                            fSectionOrder;
        unsigned int                                                                            fNextSortOrder;
        bool                                                                                            fCreateUUID;
        SectionOrder                                                                            fSectionOrder;
        unsigned int                                                                            fNextSortOrder;
@@ -408,6 +410,7 @@ private:
        uint64_t                                                                                        fStartLoadUndefinesTime;
        uint64_t                                                                                        fStartResolveTime;
        uint64_t                                                                                        fStartSortTime;
        uint64_t                                                                                        fStartLoadUndefinesTime;
        uint64_t                                                                                        fStartResolveTime;
        uint64_t                                                                                        fStartSortTime;
+       uint64_t                                                                                        fStartDebugTime;
        uint64_t                                                                                        fStartWriteTime;
        uint64_t                                                                                        fEndTime;
        uint64_t                                                                                        fTotalObjectSize;
        uint64_t                                                                                        fStartWriteTime;
        uint64_t                                                                                        fEndTime;
        uint64_t                                                                                        fTotalObjectSize;
@@ -570,7 +573,7 @@ void Linker::link()
        this->sortAtoms();
        this->tweakLayout();
        this->writeDotOutput();
        this->sortAtoms();
        this->tweakLayout();
        this->writeDotOutput();
-       this->collectStabs();
+       this->collectDebugInfo();
        this->writeOutput();
        this->printStatistics();
 
        this->writeOutput();
        this->printStatistics();
 
@@ -645,7 +648,8 @@ void Linker::printStatistics()
                printTime(" build atom list",           fStartLoadUndefinesTime -       fStartBuildAtomsTime,           totalTime);
                printTime(" load undefines",            fStartResolveTime -                     fStartLoadUndefinesTime,        totalTime);
                printTime(" resolve references",        fStartSortTime -                        fStartResolveTime,                      totalTime);
                printTime(" build atom list",           fStartLoadUndefinesTime -       fStartBuildAtomsTime,           totalTime);
                printTime(" load undefines",            fStartResolveTime -                     fStartLoadUndefinesTime,        totalTime);
                printTime(" resolve references",        fStartSortTime -                        fStartResolveTime,                      totalTime);
-               printTime(" sort output",                       fStartWriteTime -                       fStartSortTime,                         totalTime);
+               printTime(" sort output",                       fStartDebugTime -                       fStartSortTime,                         totalTime);
+               printTime(" process debug info",        fStartWriteTime -                       fStartDebugTime,                        totalTime);
                printTime(" write output",                      fEndTime -                                      fStartWriteTime,                        totalTime);
                fprintf(stderr, "pageins=%u, pageouts=%u, faults=%u\n", endVMInfo.pageins-fStartVMInfo.pageins,
                                                                                endVMInfo.pageouts-fStartVMInfo.pageouts, endVMInfo.faults-fStartVMInfo.faults);
                printTime(" write output",                      fEndTime -                                      fStartWriteTime,                        totalTime);
                fprintf(stderr, "pageins=%u, pageouts=%u, faults=%u\n", endVMInfo.pageins-fStartVMInfo.pageins,
                                                                                endVMInfo.pageouts-fStartVMInfo.pageouts, endVMInfo.faults-fStartVMInfo.faults);
@@ -873,7 +877,8 @@ void Linker::addJustInTimeAtoms(const char* name)
        // give indirect readers a chance
        for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
                ObjectFile::Reader* reader = it->reader;
        // give indirect readers a chance
        for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
                ObjectFile::Reader* reader = it->reader;
-               if ( reader != NULL ) {
+               // for two-level namespace, only search re-exported indirect libraries
+               if ( (reader != NULL) && ((it->reExportedViaDirectLibrary != NULL) || (fOptions.nameSpace() != Options::kTwoLevelNameSpace)) ) {
                        std::vector<class ObjectFile::Atom*>* atoms = reader->getJustInTimeAtomsFor(name);
                        if ( atoms != NULL ) {
                                this->addAtoms(*atoms);
                        std::vector<class ObjectFile::Atom*>* atoms = reader->getJustInTimeAtomsFor(name);
                        if ( atoms != NULL ) {
                                this->addAtoms(*atoms);
@@ -1006,6 +1011,7 @@ void Linker::markLive(ObjectFile::Atom& atom, struct Linker::WhyLiveBackChain* p
                                }
                                else {
                                        // mark as undefined, for later error processing
                                }
                                else {
                                        // mark as undefined, for later error processing
+                                       fAtomsWithUnresolvedReferences.push_back(&atom);
                                        fGlobalSymbolTable.require(targetName);
                                }
                        }
                                        fGlobalSymbolTable.require(targetName);
                                }
                        }
@@ -1089,6 +1095,39 @@ void Linker::deadStripResolve()
                markLive(**it, &rootChain);
        }
 
                markLive(**it, &rootChain);
        }
 
+       // it is possible that there are unresolved references that can be resolved now
+       // this can happen if the first reference to a common symbol in an archive.
+       // common symbols are not in the archive TOC, but the .o could have been pulled in later.
+       // <rdar://problem/4654131> ld64 while linking cc1 [ when dead_strip is ON]
+       for (std::vector<ObjectFile::Atom*>::iterator it=fAtomsWithUnresolvedReferences.begin(); it != fAtomsWithUnresolvedReferences.end(); it++) {
+               std::vector<class ObjectFile::Reference*>& references = (*it)->getReferences();
+               for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                       ObjectFile::Reference* reference = *rit;
+                       if ( reference->isTargetUnbound() ) {
+                               ObjectFile::Atom* target = fGlobalSymbolTable.find(reference->getTargetName());
+                               if ( target != NULL ) {
+                                       reference->setTarget(*target, reference->getTargetOffset());
+                                       fLiveAtoms.insert(target);
+                                       // by just adding this atom to fLiveAtoms set, we are assuming it has no
+                                       // references, which is true for commons.
+                                       if ( target->getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition )
+                                               fprintf(stderr, "warning: ld64 internal error %s is not a tentative definition\n", target->getDisplayName());
+                               }
+                       }
+                       if ( reference->hasFromTarget() && reference->isFromTargetUnbound() ) {
+                               ObjectFile::Atom* target = fGlobalSymbolTable.find(reference->getFromTargetName());
+                               if ( target != NULL ) {
+                                       reference->setFromTarget(*target);
+                                       fLiveAtoms.insert(target);
+                                       // by just adding this atom to fLiveAtoms set, we are assuming it has no
+                                       // references, which is true for commons.
+                                       if ( target->getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition )
+                                               fprintf(stderr, "warning: ld64 internal error %s is not a tentative definition\n", target->getDisplayName());
+                               }
+                       }
+               }
+       }
+       
        // now remove all non-live atoms from fAllAtoms
        fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), NotLive(fLiveAtoms)), fAllAtoms.end());
 }
        // now remove all non-live atoms from fAllAtoms
        fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), NotLive(fLiveAtoms)), fAllAtoms.end());
 }
@@ -1105,7 +1144,6 @@ void Linker::sortAtoms()
 }
 
 
 }
 
 
-
 // make sure given addresses are within reach of branches, etc
 void Linker::tweakLayout()
 {
 // make sure given addresses are within reach of branches, etc
 void Linker::tweakLayout()
 {
@@ -1325,7 +1363,7 @@ typedef __gnu_cxx::hash_map<const char*, std::vector<uint32_t>, __gnu_cxx::hash<
 static PathToSums sKnownBINCLs;
 
 
 static PathToSums sKnownBINCLs;
 
 
-void Linker::collectStabs(ObjectFile::Reader* reader, std::map<class ObjectFile::Atom*, uint32_t>& atomOrdinals)
+void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals)
 {
        bool log = false;
        bool minimal = ( fOptions.readerOptions().fDebugInfoStripping == ObjectFile::ReaderOptions::kDebugInfoMinimal );
 {
        bool log = false;
        bool minimal = ( fOptions.readerOptions().fDebugInfoStripping == ObjectFile::ReaderOptions::kDebugInfoMinimal );
@@ -1374,7 +1412,7 @@ void Linker::collectStabs(ObjectFile::Reader* reader, std::map<class ObjectFile:
                                break;
                        case N_FUN:
                                {
                                break;
                        case N_FUN:
                                {
-                                       std::map<class ObjectFile::Atom*, uint32_t>::iterator pos = atomOrdinals.find(it->atom);
+                                       std::map<const class ObjectFile::Atom*, uint32_t>::iterator pos = atomOrdinals.find(it->atom);
                                        if ( pos != atomOrdinals.end() ) {
                                                uint32_t ordinal = pos->second;
                                                if ( ordinal > highestOrdinal ) {
                                        if ( pos != atomOrdinals.end() ) {
                                                uint32_t ordinal = pos->second;
                                                if ( ordinal > highestOrdinal ) {
@@ -1550,166 +1588,208 @@ void Linker::collectStabs(ObjectFile::Reader* reader, std::map<class ObjectFile:
 }
 
 
 }
 
 
-void Linker::synthesizeStabs(ObjectFile::Reader* reader)
+// used to prune out atoms that don't need debug notes generated
+class NoDebugNoteAtom
+{
+public:
+       NoDebugNoteAtom(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals) 
+                       : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals) {}
+
+       bool operator()(const ObjectFile::Atom* atom) const {
+               if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn )
+                       return true;
+               if ( atom->getName() == NULL )
+                       return true;
+               if ( fReadersWithDwarfOrdinals.find(atom->getFile()) == fReadersWithDwarfOrdinals.end() )
+                       return true;
+               return false;
+       }
+
+private:
+       const std::map<class ObjectFile::Reader*, uint32_t>& fReadersWithDwarfOrdinals;
+};
+
+// used to sort atoms with debug notes
+class ReadersWithDwarfSorter
+{
+public:
+       ReadersWithDwarfSorter(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals, 
+                                                  const std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals) 
+                       : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals), fAtomOrdinals(atomOrdinals) {}
+
+       bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right) const
+       {
+               // first sort by reader
+               unsigned int leftReaderIndex  = fReadersWithDwarfOrdinals.find(left->getFile())->second;
+               unsigned int rightReaderIndex = fReadersWithDwarfOrdinals.find(right->getFile())->second;
+               if ( leftReaderIndex != rightReaderIndex )
+                       return (leftReaderIndex < rightReaderIndex);
+
+               // then sort by atom ordinal
+               unsigned int leftAtomIndex  = fAtomOrdinals.find(left)->second;
+               unsigned int rightAtomIndex = fAtomOrdinals.find(right)->second;
+               return leftAtomIndex < rightAtomIndex;
+       }
+
+private:
+       const std::map<class ObjectFile::Reader*, uint32_t>& fReadersWithDwarfOrdinals;
+       const std::map<const class ObjectFile::Atom*, uint32_t>& fAtomOrdinals;
+};
+
+
+
+
+
+void Linker::synthesizeDebugNotes(std::vector<class ObjectFile::Atom*>& allAtomsByReader)
 {
        // synthesize "debug notes" and add them to master stabs vector
        const char* dirPath = NULL;
        const char* filename = NULL;
        bool wroteStartSO = false;
 {
        // synthesize "debug notes" and add them to master stabs vector
        const char* dirPath = NULL;
        const char* filename = NULL;
        bool wroteStartSO = false;
-       std::vector<const char*> seenFiles;
-       for (std::vector<class ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); ++it) {
+       __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals>  seenFiles;
+       for (std::vector<ObjectFile::Atom*>::iterator it=allAtomsByReader.begin(); it != allAtomsByReader.end(); it++) {
                ObjectFile::Atom* atom = *it;
                ObjectFile::Atom* atom = *it;
-               if ( atom->getFile() == reader ) {
-                       const char* name = atom->getName();
-                       if ( (name != NULL) && (atom->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn) ) {
-                               const char* newDirPath;
-                               const char* newFilename;
-                               if ( atom->getTranslationUnitSource(&newDirPath, &newFilename) ) {
-                                       // gdb like directory SO's to end in '/', but dwarf DW_AT_comp_dir usually does not have trailing '/'
-                                       if ( (newDirPath != NULL) && (strlen(newDirPath) > 1 ) && (newDirPath[strlen(newDirPath)-1] != '/') )
-                                               asprintf((char**)&newDirPath, "%s/", newDirPath);
-                                       // need SO's whenever the translation unit source file changes
-                                       if ( newFilename != filename ) {
-                                               if ( filename != NULL ) {
-                                                       // translation unit change, emit ending SO
-                                                       ObjectFile::Reader::Stab endFileStab;
-                                                       endFileStab.atom                = NULL;
-                                                       endFileStab.type                = N_SO;
-                                                       endFileStab.other               = 1;
-                                                       endFileStab.desc                = 0;
-                                                       endFileStab.value               = 0;
-                                                       endFileStab.string              = "";
-                                                       fStabs.push_back(endFileStab);
-                                               }
-                                               // new translation unit, emit start SO's
-                                               ObjectFile::Reader::Stab dirPathStab;
-                                               dirPathStab.atom                = NULL;
-                                               dirPathStab.type                = N_SO;
-                                               dirPathStab.other               = 0;
-                                               dirPathStab.desc                = 0;
-                                               dirPathStab.value               = 0;
-                                               dirPathStab.string              = newDirPath;
-                                               fStabs.push_back(dirPathStab);
-                                               ObjectFile::Reader::Stab fileStab;
-                                               fileStab.atom           = NULL;
-                                               fileStab.type           = N_SO;
-                                               fileStab.other          = 0;
-                                               fileStab.desc           = 0;
-                                               fileStab.value          = 0;
-                                               fileStab.string         = newFilename;
-                                               fStabs.push_back(fileStab);
-                                               // Synthesize OSO for start of file
-                                               ObjectFile::Reader::Stab objStab;
-                                               objStab.atom            = NULL;
-                                               objStab.type            = N_OSO;
-                                               objStab.other           = 0;
-                                               objStab.desc            = 1;
-                                               objStab.value           = reader->getModificationTime();
-                                               objStab.string          = assureFullPath(reader->getPath());
-                                               fStabs.push_back(objStab);
-                                               wroteStartSO = true;
-                                       }
-                                       filename = newFilename;
-                                       dirPath = newDirPath;
-                                       seenFiles.push_back(filename);
-                                       if ( atom->getSegment().isContentExecutable() && (strncmp(atom->getSectionName(), "__text", 6) == 0) ) {
-                                               // Synthesize BNSYM and start FUN stabs
-                                               ObjectFile::Reader::Stab beginSym;
-                                               beginSym.atom           = atom;
-                                               beginSym.type           = N_BNSYM;
-                                               beginSym.other          = 1;
-                                               beginSym.desc           = 0;
-                                               beginSym.value          = 0;
-                                               beginSym.string         = "";
-                                               fStabs.push_back(beginSym);
-                                               ObjectFile::Reader::Stab startFun;
-                                               startFun.atom           = atom;
-                                               startFun.type           = N_FUN;
-                                               startFun.other          = 1;
-                                               startFun.desc           = 0;
-                                               startFun.value          = 0;
-                                               startFun.string         = name;
-                                               fStabs.push_back(startFun);
-                                               // Synthesize any SOL stabs needed
-                                               std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
-                                               if ( lineInfo != NULL ) {
-                                                       // might be nice to set the source file path to seenFiles so it does not show up in SOLs
-                                                       const char* curFile = NULL;
-                                                       for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
-                                                               if ( it->fileName != curFile ) {
-                                                                       bool alreadySeen = false;
-                                                                       for (std::vector<const char*>::iterator sit = seenFiles.begin(); sit != seenFiles.end(); ++sit) {
-                                                                               if ( strcmp(it->fileName, *sit) == 0 ) {
-                                                                                       alreadySeen = true;
-                                                                                       break;
-                                                                               }
-                                                                       }
-                                                                       if ( ! alreadySeen ) {
-                                                                               seenFiles.push_back(it->fileName);
-                                                                               ObjectFile::Reader::Stab sol;
-                                                                               sol.atom                = 0;
-                                                                               sol.type                = N_SOL;
-                                                                               sol.other               = 0;
-                                                                               sol.desc                = 0;
-                                                                               sol.value               = 0;
-                                                                               sol.string              = it->fileName;
-                                                                               fStabs.push_back(sol);
-                                                                       }
-                                                                       curFile = it->fileName;
-                                                               }
+               const char* newDirPath;
+               const char* newFilename;
+               //fprintf(stderr, "debug note for %s\n", atom->getDisplayName());
+               if ( atom->getTranslationUnitSource(&newDirPath, &newFilename) ) {
+                       // need SO's whenever the translation unit source file changes
+                       if ( newFilename != filename ) {
+                               // gdb like directory SO's to end in '/', but dwarf DW_AT_comp_dir usually does not have trailing '/'
+                               if ( (newDirPath != NULL) && (strlen(newDirPath) > 1 ) && (newDirPath[strlen(newDirPath)-1] != '/') )
+                                       asprintf((char**)&newDirPath, "%s/", newDirPath);
+                               if ( filename != NULL ) {
+                                       // translation unit change, emit ending SO
+                                       ObjectFile::Reader::Stab endFileStab;
+                                       endFileStab.atom                = NULL;
+                                       endFileStab.type                = N_SO;
+                                       endFileStab.other               = 1;
+                                       endFileStab.desc                = 0;
+                                       endFileStab.value               = 0;
+                                       endFileStab.string              = "";
+                                       fStabs.push_back(endFileStab);
+                               }
+                               // new translation unit, emit start SO's
+                               ObjectFile::Reader::Stab dirPathStab;
+                               dirPathStab.atom                = NULL;
+                               dirPathStab.type                = N_SO;
+                               dirPathStab.other               = 0;
+                               dirPathStab.desc                = 0;
+                               dirPathStab.value               = 0;
+                               dirPathStab.string              = newDirPath;
+                               fStabs.push_back(dirPathStab);
+                               ObjectFile::Reader::Stab fileStab;
+                               fileStab.atom           = NULL;
+                               fileStab.type           = N_SO;
+                               fileStab.other          = 0;
+                               fileStab.desc           = 0;
+                               fileStab.value          = 0;
+                               fileStab.string         = newFilename;
+                               fStabs.push_back(fileStab);
+                               // Synthesize OSO for start of file
+                               ObjectFile::Reader::Stab objStab;
+                               objStab.atom            = NULL;
+                               objStab.type            = N_OSO;
+                               objStab.other           = 0;
+                               objStab.desc            = 1;
+                               objStab.value           = atom->getFile()->getModificationTime();
+                               objStab.string          = assureFullPath(atom->getFile()->getPath());
+                               fStabs.push_back(objStab);
+                               wroteStartSO = true;
+                               // add the source file path to seenFiles so it does not show up in SOLs
+                               seenFiles.insert(newFilename);
+                       }
+                       filename = newFilename;
+                       dirPath = newDirPath;
+                       if ( atom->getSegment().isContentExecutable() && (strncmp(atom->getSectionName(), "__text", 6) == 0) ) {
+                               // Synthesize BNSYM and start FUN stabs
+                               ObjectFile::Reader::Stab beginSym;
+                               beginSym.atom           = atom;
+                               beginSym.type           = N_BNSYM;
+                               beginSym.other          = 1;
+                               beginSym.desc           = 0;
+                               beginSym.value          = 0;
+                               beginSym.string         = "";
+                               fStabs.push_back(beginSym);
+                               ObjectFile::Reader::Stab startFun;
+                               startFun.atom           = atom;
+                               startFun.type           = N_FUN;
+                               startFun.other          = 1;
+                               startFun.desc           = 0;
+                               startFun.value          = 0;
+                               startFun.string         = atom->getName();
+                               fStabs.push_back(startFun);
+                               // Synthesize any SOL stabs needed
+                               std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
+                               if ( lineInfo != NULL ) {
+                                       const char* curFile = NULL;
+                                       for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
+                                               if ( it->fileName != curFile ) {
+                                                       if ( seenFiles.count(it->fileName) == 0 ) {
+                                                               seenFiles.insert(it->fileName);
+                                                               ObjectFile::Reader::Stab sol;
+                                                               sol.atom                = 0;
+                                                               sol.type                = N_SOL;
+                                                               sol.other               = 0;
+                                                               sol.desc                = 0;
+                                                               sol.value               = 0;
+                                                               sol.string              = it->fileName;
+                                                               fStabs.push_back(sol);
                                                        }
                                                        }
+                                                       curFile = it->fileName;
                                                }
                                                }
-                                               // Synthesize end FUN and ENSYM stabs
-                                               ObjectFile::Reader::Stab endFun;
-                                               endFun.atom                     = atom;
-                                               endFun.type                     = N_FUN;
-                                               endFun.other            = 0;
-                                               endFun.desc                     = 0;
-                                               endFun.value            = 0;
-                                               endFun.string           = "";
-                                               fStabs.push_back(endFun);
-                                               ObjectFile::Reader::Stab endSym;
-                                               endSym.atom                     = atom;
-                                               endSym.type                     = N_ENSYM;
-                                               endSym.other            = 1;
-                                               endSym.desc                     = 0;
-                                               endSym.value            = 0;
-                                               endSym.string           = "";
-                                               fStabs.push_back(endSym);
                                        }
                                        }
-                                       else {
-                                               ObjectFile::Reader::Stab globalsStab;
-                                               if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
-                                                       // Synthesize STSYM stab for statics
-                                                       const char* name = atom->getName();
-                                                       if ( name[0] == '_' ) {
-                                                               globalsStab.atom                = atom;
-                                                               globalsStab.type                = N_STSYM;
-                                                               globalsStab.other               = 1;
-                                                               globalsStab.desc                = 0;
-                                                               globalsStab.value               = 0;
-                                                               globalsStab.string              = name;
-                                                               fStabs.push_back(globalsStab);
-                                                       }
-                                               }
-                                               else {
-                                                       // Synthesize GSYM stab for other globals (but not .eh exception frame symbols)
-                                                       const char* name = atom->getName();
-                                                       if ( (name[0] == '_') && (strcmp(atom->getSectionName(), "__eh_frame") != 0) ) {
-                                                               globalsStab.atom                = atom;
-                                                               globalsStab.type                = N_GSYM;
-                                                               globalsStab.other               = 1;
-                                                               globalsStab.desc                = 0;
-                                                               globalsStab.value               = 0;
-                                                               globalsStab.string              = name;
-                                                               fStabs.push_back(globalsStab);
-                                                       }
-                                               }
+                               }
+                               // Synthesize end FUN and ENSYM stabs
+                               ObjectFile::Reader::Stab endFun;
+                               endFun.atom                     = atom;
+                               endFun.type                     = N_FUN;
+                               endFun.other            = 0;
+                               endFun.desc                     = 0;
+                               endFun.value            = 0;
+                               endFun.string           = "";
+                               fStabs.push_back(endFun);
+                               ObjectFile::Reader::Stab endSym;
+                               endSym.atom                     = atom;
+                               endSym.type                     = N_ENSYM;
+                               endSym.other            = 1;
+                               endSym.desc                     = 0;
+                               endSym.value            = 0;
+                               endSym.string           = "";
+                               fStabs.push_back(endSym);
+                       }
+                       else {
+                               ObjectFile::Reader::Stab globalsStab;
+                               if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
+                                       // Synthesize STSYM stab for statics
+                                       const char* name = atom->getName();
+                                       if ( name[0] == '_' ) {
+                                               globalsStab.atom                = atom;
+                                               globalsStab.type                = N_STSYM;
+                                               globalsStab.other               = 1;
+                                               globalsStab.desc                = 0;
+                                               globalsStab.value               = 0;
+                                               globalsStab.string              = name;
+                                               fStabs.push_back(globalsStab);
+                                       }
+                               }
+                               else {
+                                       // Synthesize GSYM stab for other globals (but not .eh exception frame symbols)
+                                       const char* name = atom->getName();
+                                       if ( (name[0] == '_') && (strcmp(atom->getSectionName(), "__eh_frame") != 0) ) {
+                                               globalsStab.atom                = atom;
+                                               globalsStab.type                = N_GSYM;
+                                               globalsStab.other               = 1;
+                                               globalsStab.desc                = 0;
+                                               globalsStab.value               = 0;
+                                               globalsStab.string              = name;
+                                               fStabs.push_back(globalsStab);
                                        }
                                }
                        }
                }
        }
                                        }
                                }
                        }
                }
        }
+
        if ( wroteStartSO ) {
                //  emit ending SO
                ObjectFile::Reader::Stab endFileStab;
        if ( wroteStartSO ) {
                //  emit ending SO
                ObjectFile::Reader::Stab endFileStab;
@@ -1723,19 +1803,18 @@ void Linker::synthesizeStabs(ObjectFile::Reader* reader)
        }
 }
 
        }
 }
 
-void Linker::collectStabs()
+
+
+
+void Linker::collectDebugInfo()
 {
 {
+       std::map<const class ObjectFile::Atom*, uint32_t>       atomOrdinals;
+       fStartDebugTime = mach_absolute_time();
        if ( fOptions.readerOptions().fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone ) {
 
        if ( fOptions.readerOptions().fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone ) {
 
-               // make mapping from atoms to ordinal
-               std::map<class ObjectFile::Atom*, uint32_t>     atomOrdinals;
-               uint32_t ordinal = 1;
-               for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
-                       atomOrdinals[*it] = ordinal++;
-               }
-
-               fStabs.reserve(1024); // try to minimize re-allocations
-               // get stabs from each reader, in command line order
+               // determine mixture of stabs and dwarf
+               bool someStabs = false;
+               bool someDwarf = false;
                for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
                                it != fReadersThatHaveSuppliedAtoms.end();
                                it++) {
                for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
                                it != fReadersThatHaveSuppliedAtoms.end();
                                it++) {
@@ -1743,17 +1822,16 @@ void Linker::collectStabs()
                        if ( reader != NULL ) {
                                switch ( reader->getDebugInfoKind() ) {
                                        case ObjectFile::Reader::kDebugInfoNone:
                        if ( reader != NULL ) {
                                switch ( reader->getDebugInfoKind() ) {
                                        case ObjectFile::Reader::kDebugInfoNone:
-                                               // do nothing
                                                break;
                                        case ObjectFile::Reader::kDebugInfoStabs:
                                                break;
                                        case ObjectFile::Reader::kDebugInfoStabs:
-                                               collectStabs(reader, atomOrdinals);
+                                               someStabs = true;
                                                break;
                                        case ObjectFile::Reader::kDebugInfoDwarf:
                                                break;
                                        case ObjectFile::Reader::kDebugInfoDwarf:
-                                               synthesizeStabs(reader);
+                                               someDwarf = true;
                                                fCreateUUID = true;
                                                break;
                                    case ObjectFile::Reader::kDebugInfoStabsUUID:
                                                fCreateUUID = true;
                                                break;
                                    case ObjectFile::Reader::kDebugInfoStabsUUID:
-                                               collectStabs(reader, atomOrdinals);
+                                               someStabs = true;
                                                fCreateUUID = true;
                                                break;
                                        default:
                                                fCreateUUID = true;
                                                break;
                                        default:
@@ -1761,10 +1839,70 @@ void Linker::collectStabs()
                                }
                        }
                }
                                }
                        }
                }
-               // remove stabs associated with atoms that won't be in output
-               std::set<class ObjectFile::Atom*>       allAtomsSet;
-               allAtomsSet.insert(fAllAtoms.begin(), fAllAtoms.end());
-               fStabs.erase(std::remove_if(fStabs.begin(), fStabs.end(), NotInSet(allAtomsSet)), fStabs.end());
+               
+               if ( someDwarf || someStabs ) {
+                       // try to minimize re-allocations
+                       fStabs.reserve(1024); 
+
+                       // make mapping from atoms to ordinal
+                       uint32_t ordinal = 1;
+                       for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
+                               atomOrdinals[*it] = ordinal++;
+                       }
+               }
+                       
+               // process all dwarf .o files as a batch
+               if ( someDwarf ) {
+                       // make mapping from readers with dwarf to ordinal
+                       std::map<class ObjectFile::Reader*, uint32_t>   readersWithDwarfOrdinals;
+                       uint32_t readerOrdinal = 1;
+                       for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
+                                       it != fReadersThatHaveSuppliedAtoms.end();
+                                       it++) {
+                               ObjectFile::Reader* reader = *it;
+                               if ( (reader != NULL) && (reader->getDebugInfoKind() == ObjectFile::Reader::kDebugInfoDwarf) ) {
+                                       readersWithDwarfOrdinals[reader] = readerOrdinal++;
+                               }
+                       }
+               
+                       // make a vector of atoms 
+                       std::vector<class ObjectFile::Atom*> allAtomsByReader(fAllAtoms.begin(), fAllAtoms.end());
+                       // remove those not from a reader that has dwarf
+                       allAtomsByReader.erase(std::remove_if(allAtomsByReader.begin(), allAtomsByReader.end(), 
+                                                               NoDebugNoteAtom(readersWithDwarfOrdinals)), allAtomsByReader.end());
+                       // sort by reader then atom ordinal
+                       std::sort(allAtomsByReader.begin(), allAtomsByReader.end(), ReadersWithDwarfSorter(readersWithDwarfOrdinals, atomOrdinals));
+                       // add debug notes for each atom
+                       this->synthesizeDebugNotes(allAtomsByReader);
+               }
+               
+               // process all stabs .o files one by one
+               if ( someStabs ) {
+                       // get stabs from each reader, in command line order
+                       for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
+                                       it != fReadersThatHaveSuppliedAtoms.end();
+                                       it++) {
+                               ObjectFile::Reader* reader = *it;
+                               if ( reader != NULL ) {
+                                       switch ( reader->getDebugInfoKind() ) {
+                                               case ObjectFile::Reader::kDebugInfoDwarf:
+                                               case ObjectFile::Reader::kDebugInfoNone:
+                                                       // do nothing
+                                                       break;
+                                               case ObjectFile::Reader::kDebugInfoStabs:
+                                               case ObjectFile::Reader::kDebugInfoStabsUUID:
+                                                       collectStabs(reader, atomOrdinals);
+                                                       break;
+                                               default:
+                                                       throw "Unhandled type of debug information";
+                                       }
+                               }
+                       }
+                       // remove stabs associated with atoms that won't be in output
+                       std::set<class ObjectFile::Atom*>       allAtomsSet;
+                       allAtomsSet.insert(fAllAtoms.begin(), fAllAtoms.end());
+                       fStabs.erase(std::remove_if(fStabs.begin(), fStabs.end(), NotInSet(allAtomsSet)), fStabs.end());
+               }
        }
 }
 
        }
 }
 
@@ -1799,7 +1937,7 @@ ObjectFile::Reader* Linker::createReader(const Options::FileInfo& info)
                                uint32_t fileOffset = OSSwapBigToHostInt32(archs[i].offset);
                                len = OSSwapBigToHostInt32(archs[i].size);
                                // if requested architecture is page aligned within fat file, then remap just that portion of file
                                uint32_t fileOffset = OSSwapBigToHostInt32(archs[i].offset);
                                len = OSSwapBigToHostInt32(archs[i].size);
                                // if requested architecture is page aligned within fat file, then remap just that portion of file
-                               if ( (fileOffset && 0x00000FFF) == 0 ) {
+                               if ( (fileOffset & 0x00000FFF) == 0 ) {
                                        // unmap whole file
                                        munmap((caddr_t)p, info.fileLen);
                                        // re-map just part we need
                                        // unmap whole file
                                        munmap((caddr_t)p, info.fileLen);
                                        // re-map just part we need
@@ -2300,7 +2438,7 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                        case kWeakAndWeak:
                                // have another weak atom, use whichever has largest alignment requirement
                                // because codegen of some client may require alignment
                        case kWeakAndWeak:
                                // have another weak atom, use whichever has largest alignment requirement
                                // because codegen of some client may require alignment
-                               useNew = ( newAtom.getAlignment() > existingAtom->getAlignment() );
+                               useNew = ( newAtom.getAlignment().leadingZeros() > existingAtom->getAlignment().leadingZeros() );
                                break;
                        case kWeakAndTent:
                                // replace existing weak atom with tentative one ???
                                break;
                        case kWeakAndTent:
                                // replace existing weak atom with tentative one ???
@@ -2323,6 +2461,9 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                // use largest
                                if ( newAtom.getSize() < existingAtom->getSize() ) {
                                        useNew = false;
                                // use largest
                                if ( newAtom.getSize() < existingAtom->getSize() ) {
                                        useNew = false;
+                               } else {
+                                       if ( newAtom.getAlignment().leadingZeros() < existingAtom->getAlignment().leadingZeros() )
+                                               fprintf(stderr, "ld64 warning: alignment lost in merging tentative definition %s\n", newAtom.getDisplayName());
                                }
                                break;
                        case kTentAndExtern:
                                }
                                break;
                        case kTentAndExtern:
index 118aa497da57c7b8b18be16b3c3d7720ae8c1363..1d7aec59e42d130626b2b3b62ed8af1d8c0cb099 100644 (file)
@@ -336,7 +336,7 @@ void MachOChecker<A>::checkLoadCommands()
                                        throwf("section %s vm address not within segment", sect->sectname());
                                if ( (sect->addr()+sect->size()) > endAddr )
                                        throwf("section %s vm address not within segment", sect->sectname());
                                        throwf("section %s vm address not within segment", sect->sectname());
                                if ( (sect->addr()+sect->size()) > endAddr )
                                        throwf("section %s vm address not within segment", sect->sectname());
-                               if ( (sect->flags() &SECTION_TYPE) != S_ZEROFILL ) {
+                               if ( ((sect->flags() &SECTION_TYPE) != S_ZEROFILL) && (segCmd->filesize() != 0) ) {
                                        if ( sect->offset() < startOffset )
                                                throwf("section %s file offset not within segment", sect->sectname());
                                        if ( (sect->offset()+sect->size()) > endOffset )
                                        if ( sect->offset() < startOffset )
                                                throwf("section %s file offset not within segment", sect->sectname());
                                        if ( (sect->offset()+sect->size()) > endOffset )
@@ -402,10 +402,12 @@ void MachOChecker<A>::checkLoadCommands()
                                        const macho_dysymtab_command<P>* dsymtab = (struct macho_dysymtab_command<P>*)cmd;
                                        fIndirectTable = (uint32_t*)((char*)fHeader + dsymtab->indirectsymoff());
                                        fIndirectTableCount = dsymtab->nindirectsyms();
                                        const macho_dysymtab_command<P>* dsymtab = (struct macho_dysymtab_command<P>*)cmd;
                                        fIndirectTable = (uint32_t*)((char*)fHeader + dsymtab->indirectsymoff());
                                        fIndirectTableCount = dsymtab->nindirectsyms();
-                                       if ( dsymtab->indirectsymoff() < linkEditSegment->fileoff() )
-                                               throw "indirect symbol table not in __LINKEDIT";
-                                       if ( (dsymtab->indirectsymoff()+fIndirectTableCount*8) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
-                                               throw "indirect symbol table not in __LINKEDIT";
+                                       if ( fIndirectTableCount != 0  ) {
+                                               if ( dsymtab->indirectsymoff() < linkEditSegment->fileoff() )
+                                                       throw "indirect symbol table not in __LINKEDIT";
+                                               if ( (dsymtab->indirectsymoff()+fIndirectTableCount*8) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
+                                                       throw "indirect symbol table not in __LINKEDIT";
+                                       }
                                        fLocalRelocationsCount = dsymtab->nlocrel();
                                        if ( fLocalRelocationsCount != 0 ) {
                                                fLocalRelocations = (const macho_relocation_info<P>*)((char*)fHeader + dsymtab->locreloff());
                                        fLocalRelocationsCount = dsymtab->nlocrel();
                                        if ( fLocalRelocationsCount != 0 ) {
                                                fLocalRelocations = (const macho_relocation_info<P>*)((char*)fHeader + dsymtab->locreloff());
index ab62f9bd6da48ffe7e4c32f486f8afaccae7a45b..e47ce34e9950955f67f37d984bf9ad3700b3b271 100644 (file)
@@ -406,6 +406,8 @@ void Rebaser<A>::adjustSymbolTable()
                if ( entry->n_sect() != NO_SECT )
                        entry->set_n_value(entry->n_value() + fSlide);
        }
                if ( entry->n_sect() != NO_SECT )
                        entry->set_n_value(entry->n_value() + fSlide);
        }
+       
+       // FIXME Â¥Â¥Â¥ adjust dylib_module if it exists
 }
 
 template <typename A>
 }
 
 template <typename A>
diff --git a/unit-tests/test-cases/align-modulus/Makefile b/unit-tests/test-cases/align-modulus/Makefile
new file mode 100644 (file)
index 0000000..bf79c29
--- /dev/null
@@ -0,0 +1,43 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is to verify that the modules of
+# symbol _b is maintained.  The address for _b must be
+# 3 mod 16.  Therefore the last hexdigit of the address 
+# must be 3.
+
+run: all
+
+all:
+       ${CC} ${ASMFLAGS} -dynamiclib -single_module -dead_strip foo.c align.s  -exported_symbols_list foo.exp -o foo.${ARCH}.dylib
+       nm foo.${ARCH}.dylib | grep "3 d _b" | ${PASS_IFF_STDIN}
+
+
+clean:
+       rm -rf foo.${ARCH}.dylib 
+       
+       
+
diff --git a/unit-tests/test-cases/align-modulus/align.s b/unit-tests/test-cases/align-modulus/align.s
new file mode 100644 (file)
index 0000000..a288960
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+       .data
+       .align 0
+_a:    .byte 3
+       .byte 3
+       .byte 3
+       .globl _b
+_b: .byte 4                    ;# address is 3
+       .align 4
+L1: .quad 0
+_c: .long 8
+
+       .subsections_via_symbols
+       
diff --git a/unit-tests/test-cases/align-modulus/foo.c b/unit-tests/test-cases/align-modulus/foo.c
new file mode 100644 (file)
index 0000000..0b88dff
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+extern char b;
+int my = 2;
+
+char foo()
+{
+       return my+b;
+}
+
+
diff --git a/unit-tests/test-cases/align-modulus/foo.exp b/unit-tests/test-cases/align-modulus/foo.exp
new file mode 100644 (file)
index 0000000..70eefe9
--- /dev/null
@@ -0,0 +1 @@
+_foo
diff --git a/unit-tests/test-cases/dead_strip-archive/Makefile b/unit-tests/test-cases/dead_strip-archive/Makefile
new file mode 100644 (file)
index 0000000..c2e66c0
--- /dev/null
@@ -0,0 +1,43 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test that -dead_strip removes unreference code/data from archives
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.c -c -o foo.o
+       libtool -static foo.o -o libfoo.a
+       ${CC} ${CCFLAGS}  main.c -mdynamic-no-pic -Os libfoo.a -dead_strip -o main
+       ${FAIL_IF_BAD_MACHO} main
+       nm -j  main | grep dead_wood | ${PASS_IFF_EMPTY}
+       
+
+clean:
+       rm -rf  main libfoo.a foo.o
+       
+
diff --git a/unit-tests/test-cases/dead_strip-archive/foo.c b/unit-tests/test-cases/dead_strip-archive/foo.c
new file mode 100644 (file)
index 0000000..be1b438
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+void foo() {}
+
+
+int my_common;
+
diff --git a/unit-tests/test-cases/dead_strip-archive/main.c b/unit-tests/test-cases/dead_strip-archive/main.c
new file mode 100644 (file)
index 0000000..f6a7d5a
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+extern void foo();
+extern int my_common;
+
+int main()
+{
+       // the reference to the common symbol has to be first
+       my_common += 1;
+       // refrence to foo is next
+       foo();
+       return 0;
+}
+
+
index b7f4eeb2bebb95edb47665841e73ce9ba4f01ded..8159cd9c18b56c75ec0abbb127575ca4e9714aa3 100644 (file)
@@ -40,7 +40,7 @@ all: foobar.o main.o crt1.o
        ${PASS_IFF} diff dwarf-test-${ARCH}.stabs expected-stabs
 
 foobar.o : foo.o bar.o
        ${PASS_IFF} diff dwarf-test-${ARCH}.stabs expected-stabs
 
 foobar.o : foo.o bar.o
-       ${LD} -r foo.o bar.o -o foobar.o
+       ${LD} -r -arch ${ARCH} foo.o bar.o -o foobar.o
        
 foo.o : foo.cxx
        ${CXX} ${CCXXFLAGS} -gdwarf-2 foo.cxx -c -o foo.o -mdynamic-no-pic
        
 foo.o : foo.cxx
        ${CXX} ${CCXXFLAGS} -gdwarf-2 foo.cxx -c -o foo.o -mdynamic-no-pic
index 4853628fe5bf591a940d03052f4ebde6703d36a3..f8abc124767132d47e7bec677ce5137669ffbbb0 100644 (file)
@@ -1,4 +1,12 @@
 0000    SO CWD/
 0000    SO CWD/
+0000    SO main.cxx
+0001   OSO CWD/main.o
+0000 BNSYM 
+0000   FUN _main
+0000   FUN 
+0000 ENSYM 
+0000    SO 
+0000    SO CWD/
 0000    SO foo.cxx
 0001   OSO CWD/foo.o
 0000 BNSYM 
 0000    SO foo.cxx
 0001   OSO CWD/foo.o
 0000 BNSYM 
 0000   FUN 
 0000 ENSYM 
 0000    SO 
 0000   FUN 
 0000 ENSYM 
 0000    SO 
-0000    SO CWD/
-0000    SO main.cxx
-0001   OSO CWD/main.o
-0000 BNSYM 
-0000   FUN _main
-0000   FUN 
-0000 ENSYM 
-0000    SO 
diff --git a/unit-tests/test-cases/indirect-dylib/Makefile b/unit-tests/test-cases/indirect-dylib/Makefile
new file mode 100644 (file)
index 0000000..32cb276
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# The point of this test is a sanity check that an indirect
+# library is not accidentally searched for symbols.
+#
+# <rdar://problem/4681062> wrong error message when symbol is found in unused indirect library#
+#
+
+run: all
+
+all: 
+       ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib
+       ${CC} ${CCFLAGS} foo.c libbar.dylib -dynamiclib -o libfoo.dylib 
+       ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} main.c -o main libfoo.dylib 2> fail.log
+       grep ordinal fail.log | ${PASS_IFF_EMPTY}
+
+clean:
+       rm libfoo.dylib libbar.dylib main fail.log
+       
+
diff --git a/unit-tests/test-cases/indirect-dylib/bar.c b/unit-tests/test-cases/indirect-dylib/bar.c
new file mode 100644 (file)
index 0000000..f39ee21
--- /dev/null
@@ -0,0 +1,31 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+// function called by a loaded bundle
+int bar() 
+{
+       return 1;
+}
+
diff --git a/unit-tests/test-cases/indirect-dylib/foo.c b/unit-tests/test-cases/indirect-dylib/foo.c
new file mode 100644 (file)
index 0000000..ba78c28
--- /dev/null
@@ -0,0 +1,31 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+extern int bar();
+
+int foo()
+{
+       return bar();
+}
diff --git a/unit-tests/test-cases/indirect-dylib/main.c b/unit-tests/test-cases/indirect-dylib/main.c
new file mode 100644 (file)
index 0000000..13f57d7
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+extern void bar();
+
+int main()
+{
+       bar();
+       return 0;
+}
+
index 0629125241deb65c3a9ca02664399cc9dc415188..afacc62139699d20f7869c92aa6c942058f64467 100644 (file)
@@ -220,13 +220,17 @@ _test_loads:
 
        # 1-byte store
        movb  $0x12, _a(%rip)
 
        # 1-byte store
        movb  $0x12, _a(%rip)
+       movb  $0x12, _a+2(%rip)
+       movb  $0x12, L0(%rip)
 
        # 4-byte store
        movl  $0x12345678, _a(%rip)
 
        # 4-byte store
        movl  $0x12345678, _a(%rip)
+       movl  $0x12345678, _a+4(%rip)
+       movl  $0x12345678, L0(%rip)
        
        # test local labels
        
        # test local labels
-#      lea L1(%rip), %rax              ### assembler bug
-#      movl L0(%rip), %eax             ### assembler bug
+       lea L1(%rip), %rax              
+       movl L0(%rip), %eax             
 
        ret
 
 
        ret
 
@@ -281,9 +285,9 @@ _prev:
 L1:    .quad _test_branches - _test_diffs
        .quad _test_branches - _test_diffs + 4
        .long _test_branches - _test_diffs
 L1:    .quad _test_branches - _test_diffs
        .quad _test_branches - _test_diffs + 4
        .long _test_branches - _test_diffs
-#      .long LCL0-.                            ### assembler bug: content value should be (address(LCL0) - 0x24)
+#      .long LCL0-.                            ### assembler bug: should SUB/UNSIGNED with content= LCL0-24, or single pc-rel SIGNED reloc with content = LCL0-.+4
        .quad L1
        .quad L1
-#      .quad L0                                        ### assembler bug: should be internal reloc to L0
+       .quad L0                                        
        .quad _test_branches - .
        .quad _test_branches - L1
        .quad L1 - _prev                        
        .quad _test_branches - .
        .quad _test_branches - L1
        .quad L1 - _prev                        
index a691e4a511b4c1a86c66a0f51ffc44d1a8866b07..1ca215766d2decd553edaea196e4c7afa9841109 100644 (file)
@@ -34,7 +34,6 @@
 
 
 @implementation Foo
 
 
 @implementation Foo
-
 - (id) init
 {
        self = [super init];
 - (id) init
 {
        self = [super init];
 {
        [self class];
 }
 {
        [self class];
 }
+@end
+
 
 
+
+@interface Base
 @end
 
 @end
 
+
+@implementation Base
+@end
+
+
+